I have a setup like this:
/Makefile
/foo/Makefile
/foo/bar/Makefile
/foo/baz/Makefile
The top-level Makefile contains a task which calls the /foo/Makefile. This Makefiles creates a list of makefiles in the subdirectories (bar, baz in the example). For each subdir, it calls the Makefiles:
$(SUB_DIRS):
$(MAKE) -C $@
Which is fine for, say, the all task. But if I want to do something else, I get stuck. Is there a possibility to pass the target to the list of sub-makefiles? For example:
$(SUB_DIRS):
$(MAKE) -C $@ <task>
clean: $(SUB_DIRS)-clean # or something?
Or is my whole concept wrong?
The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run. $%
Yes, a Makefile can have a directory as target. However, you shouldn't. When a file is added or removed from a directory, its mtime is updated. This can cause weird behaviour by causing multiple targets depending on a single directory to become implicitly rebuilt by one another.
I finally got it work. The approach is:
SUB_DIRS = $(wildcard */.)
SUB_DIRS_ALL = $(SUB_DIRS:%=all-%)
SUB_DIRS_TEST = $(SUB_DIRS:%=test-%)
SUB_DIRS_CLEAN = $(SUB_DIRS:%=clean-%)
#
# Standard task
#
all: $(SUB_DIRS_ALL)
test_uml: $(SUB_DIRS_TEST)
clean: $(SUB_DIRS_CLEAN)
$(SUB_DIRS_ALL):
@$(MAKE) $(MAKE_FLAGS) -C $(@:all-%=%)
$(SUB_DIRS_TEST):
@$(MAKE) $(MAKE_FLAGS) -C $(@:test-%=%) test
$(SUB_DIRS_CLEAN):
@$(MAKE) $(MAKE_FLAGS) -C $(@:clean-%=%) clean
I found this solution here: http://lackof.org/taggart/hacking/make-example/
You could simply use the MAKECMDGOALS variable:
Make will set the special variable
MAKECMDGOALSto the list of goals you specified on the command line. If no goals were given on the command line, this variable is empty.
$(SUB_DIRS):
+$(MAKE) -C $@ $(MAKECMDGOALS)
The + sign is important so the underlying job server also handles the recursive make calls with the right amount of threads/core.
You can also use the $(foreach ) function like this:
clean:
$(foreach DIR, $(SUB_DIRS), $(MAKE) -C $(DIR) $@;)
Do note as @musicmatze mentionned in the comments that Make flags (like -j) won't be passed to the sub-make processes correctly here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With