I have several modules I would like to compile, lets say foo and bar.
$MODULES = foo bar
They each are in a separate subdirectory with the same name (e.g. source/foo/foo.o), so my object files are:
$MODULE_OBJ := $(foreach module, $(MODULES), source/$(module)/$(module).o)
Now, I would like to write a generic rule for both modules, so that they depend on all the source files of their subdirectory (e.g. source/foo/*.f90), but only the one named just like the module is needed to compile it (e.g. $(FC) -c source/foo/foo.f90 is the recipe). I've read that this is commonly solved using eval and call. This doesn't work for me; I've tried to output the prerequisites for debugging, but no luck. Here is what I've tried:
define modulerule
$(1): $$(dir $(1))*.f90
$$(info prereq = $$^)
$$(FC) -c $$(basename $$#).f90
endef
$(foreach obj, %(MODULE_OBJ), $(eval $(call modulerule, $(obj))))
Expanding on what you have, one way of defining a generic rule would be
MODULES = foo bar
MODULE_OBJS := $(foreach module, $(MODULES), source/$(module)/$(module).o)
.SECONDEXPANSION:
$(MODULE_OBJS): $$(wildcard $$(dir $$#)*.f90)
$(FC) -c $(basename $#).f90 -o $#
Related
I have a Makefile that mixes Java and C++ with JNI and I would like to generate the JNI header automatically when needed.
Currently, I have the following:
$(OBJDIR)/org_some_package_%.cpp: $(INCDIR)/jni/org_some_package_%.h
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(OBJDIR)
$(CC) -c -o $# $(CFLAGS) \
-I$(INCDIR) -I../build/include -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/linux" \
-MD -MF $(patsubst %.o, %.d, $#) $<
.SECONDEXPANSION:
$(INCDIR)/jni/%.h: $(JAVA_TEST_BIN)/$$(subst _,/,%).class
#mkdir -p $(INCDIR)/jni
$(JAVAH) -d inc/jni -classpath TestJNI/bin/tests:$(JUNIT_JAR):$(HAMCREST_JAR) $(basename $(subst _,.,$(subst $(INCDIR)/jni/,,$#)))
The problem is that when a .o file is needed, the first rule is never applied:
$(OBJDIR)/org_some_package_%.cpp: $(INCDIR)/jni/org_some_package_%.h
If I replace this rule with a specific one (by replacing % by the name of a class), it works.
How can I make this generic rule work?
I don't want to do this:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(INCDIR)/jni/%.h
...because I may have .cpp files that do not correspond to JNI header.
You cannot create simple prerequisites using patterns. A pattern rule without any recipe doesn't define a prerequisite, it cancels a previously-existing pattern rule. The GNU make manual says:
You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe.
The only way to create a prerequisite is to make it explicit.
So, your $(INCDIR)/jni/a_b_c.h depend on $(JAVA_TEST_BIN)/a/b/c.class? You will have to use advanced make features. I assume that all *.class file under $(JAVA_TEST_BIN) correspond to a built header file. This (not tested) should do what you show in your question:
CLASSES := $(patsubst $(JAVA_TEST_BIN)/%.class,%,$(shell find $(JAVA_TEST_BIN) -type f -name '*.class'))
BUILT_HEADERS :=
# $(1): class
define BUILD_HEADER_rule
header := $$(INCDIR)/jni/$$(subst /,_,$(1)).h
$$(header): $$(JAVA_TEST_BIN)/$(1).class
BUILT_HEADERS += $$(header)
endef
$(foreach c,$(CLASSES),$(eval $(call BUILD_HEADER_rule,$(c))))
$(BUILT_HEADERS):
#mkdir -p $(dir $#)
$(JAVAH) -d inc/jni -classpath TestJNI/bin/tests:$(JUNIT_JAR):$(HAMCREST_JAR) $(basename $(subst _,.,$(subst $(INCDIR)/jni/,,$#)))
I would like a way to take the argument to a call invocation in a Makefile rule and pass that to a builtin function, in this case wildcard.
This doesn't seem to work:
MODULE_OBJS = $(patsubst %.cc, %.o, $(wildcard $(1)/*.cc))
lib%.a: $(call MODULE_OBJS, %)
#echo $# : $^
In this case I would expect make libfoo.a to print a list of .o files corresponding to the .cc files found under foo/, but nothing is printed. The parameter is getting there because if I append $(1) to the end of MODULE_OBJS the value of % gets printed, but it seems to be lost when getting passed into wildcard.
You need to understand that make will execute $(call MODULE_OBJS, %) before it has even begun building the dependency tree, you cannot accomplish this with a pattern rule. You could use eval hackery but there's a case to made against trying to be too clever with make.
Something like the following is easy enough to maintain
MODULE_OBJS = $(patsubst %.cc, %.o, $(wildcard $(1)/*.cc))
libfoo.a: $(call MODULE_OBJS, foo)
lib%.a:
#echo $#: $^
but after wrestling with clever ways of generating library and binary dependencies I prefer simply listing them explicitly.
I got what I wanted with some hacking of the eval rule:
EXCLUDE_MODULES = obj
MODULES = $(filter-out $(EXCLUDE_MODULES), $(patsubst %/, %, $(wildcard */)))
define MODULE_RULE
lib$(MODULE).a: $(patsubst %.cc, obj/%.o, $(wildcard $(MODULE)/*.cc))
#echo $# : $^
endef
$(foreach MODULE, $(MODULES), $(eval $(MODULE_RULE)))
This allows you to call make libfoo.a and get out a list of all the .o's corresponding with the .cc's in that subdirectory.
For those curious, I uploaded a complete example here.
The Metaprogramming Make articles were a useful resource here.
I have a set of .cpp files that I want to compile. These .cpp files are in a hierarchical directory structure. I want the corresponding .o files to all end up in one build folder.
Here's how I get GNU make to enumerate the files:
SRCS = \
$(wildcard $(CODE)/**/*.cpp) \
$(wildcard $(CODE)/AlgebraLibraries/**/*.cpp) \
$(wildcard $(CODE)/Calculator/Environments/**/*.cpp)
BARE_SRCS = $(notdir $(SRCS))
BARE_OBJS = $(BARE_SRCS:.cpp=.o)
OBJS = $(addprefix $(BUILD)/, $(BARE_OBJS))
Having done this, I have no idea how to create the rules that will create the .o files from the .cpp files. Intuitively, what I want to do is the following pseudocode:
for i=0, N do # <-- a for-loop!
$(OBJS)[i]: $(SRCS)[i] # <-- the rule!
$(CPP) -c $(SRCS)[i] -o $(OBJS)[i] # <-- the recipe
end
Of course, this is not valid GNU make code, but I trust you understand what it is here that I'm trying to do. The following will not work.
%.o: %.cpp
$(CPP) -c $< -o $#
This doesn't work, because GNU make is matching up the % signs, assuming that the .o files live along-side the .cpp files.
The alternative to all of this, which I know will work, but will be extremely tedious, is to enumerate all of the rules by-hand as explicit rules. There has to be a better way!
I've been researching GNU make's ability to generate rules, but there appears to be no way to do it without the built-in logic. It would be really nice if I could utilize some flow-control statements to generate the rules that I want to make. Is this asking too much of GNU-make?
In any case, is there a way to do what it is I'm trying to do with GNU make? If so, how?
This looks like a job for... several advanced Make tricks:
all: $(OBJS)
define ruletemp
$(patsubst %.cpp, $(BUILD)/%.o, $(notdir $(1))): $(1)
$$(CPP) -c $$< -o $$#
endef
$(foreach src,$(SRCS),$(eval $(call ruletemp, $(src))))
If $(BUILD) is constant, you can always just do:
$(BUILD)/%.o: %.cpp
$(CPP) -c $< -o $#
I am following a tutorial for compiling my own package in openwrt.
In the /package/helloworld directory:
.../packege/helloworld$ ls
src Makefile
.../packege/helloworld$ ls src
hello.c main.c Makefile
.../packege/helloworld$vi Makefile
#helloworld makefile
include $(TOPDIR)/rules.mk
PKG_NAME:=helloworld
PKG_RELEASE:=1
PKG_VERSION:=0.1
PKG_BUILD_DEPENDS:=
include $(INCLUDE_DIR)/package.mk
define Package/helloworld
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=#TARGET_etrax
TITLE:=Yet Another Helloworld Application
endef
define Package/helloworld/description
This is helloworld :p
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS)"
endef
define Package/helloworld/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin/
endef
$(eval $(call BuildPackage,helloworld))
I have two questions about this Makefile:
I found there are commands, such as mkdir, $(CP),$(MAKE). I changed $(CP) to cp, and the compiling goes well. So I don't understand why these two kinds of formats exsits.
Where the parameters, such as $(PKG_BUILD_DIR), $(INSTALL_DIR), are defined in openwrt? I just found the place where $(TOPDIR) is defined but not the others.
Thanks
These are not different kinds of formats, cp is a Linux command, $(CP) is a makefile construction for "getting the value of make variable CP". Thus, under Linux it should expand to cp (i.e. should be initialized with this value somewhere), and , most probably, to copy under Windows (this is all particular setup-dependent since cp is not fully the same as copy). The same with $(MKDIR) and other system tools.
1.1. $(MAKE) is actually another thing - this is a special make variable which expands to make tool name with arguments/flags passed from command line. Read this.
These are all variables controlling where to build and where to install. See description here.
I want to write a (gmake) makefile for a compiler that - unlike gcc - puts all output files into a specific directory. Unfortunately this behavior cannot be changed.
My sources are in multiple directories. How do I write a pattern-rule that lets me compile the sources.
Okay, that's a bit unclear. Here is an example. My sources look may like this:
./folder1/foo.c
./folder2/bar.c
and the output files will end up like this:
./obj/foo.obj
./obj/bar.obj
How should my rule to compile my sources look like?
%.obj : %.c
$(COMPILER) -c $<
will not work.
Any ideas? I'd like to avoid an implicit rule for each source file...
Extracted from some Makefile of mine:
OBJS := $(sort $(patsubst %.cpp,$(OBJECT_DIRECTORY)/%.o,$(patsubst %.c,$(OBJECT_DIRECTORY)/%.o,$(notdir $(SRCS)))))
Where OBJECT_DIRECTORY points to the object directory and SRCS is the list of source files (which you can even populate using $(wildcard)).
Then in the Makefile, I have:
define define_compile_rules
$(OBJECT_DIRECTORY)/%.o: $(1)%.c
#echo " + Compiling '$$<'"
#mkdir -p $$(#D)
$(CC) $$(CFLAGS) -o $$# -c $$<
endef
$(foreach directory,$(sort $(dir $(SRCS))),$(eval $(call define_compile_rules,$(directory))))
See the $(eval) function.