I'm trying to get a top-level makefile to call make in a number of subfolders. The top-level has several targets and the important bit is shown below:
MAKE_DIRS := $(dir $(wildcard apps/**/Makefile))
.PHONY: clean_apps apps $(MAKE_DIRS)
clean_apps: TARGET_INFO := clean
apps clean_aps: $(MAKE_DIRS)
$(MAKE_DIRS):
$(MAKE) -C $# $(TARGET_INFO)
Now this works fine when I call the targets independently:
make apps; make clean_apps
However if I call them on the same commandline with:
make clean_apps apps
Then the apps target justs say nothing to do. I guess it's something to do with the dependency on the directories not having changed between invocations, but I thought the .PHONY command would avoid that problem...
I'm happy to know if there's a better way to deal with this.
Thanks,
bob
It is something much more simpler :
SUBDIRS := $(dir $(shell find apps -name "Makefile"))
.PHONY: all clean
all clean:
$(foreach DIR, $(SUBDIRS), $(MAKE) $(MAKEFLAGS) -C $(DIR) $#;)
Related
I`m using a makefile and call some makefiles in subdirectories.
Can anyony explain me, why this works
$(MAKE) -C stub
$(MAKE) -C source
but this not
SUBDIRS = stub source
$(SUBDIRS):
$(MAKE) -C $#
First time I`m working with makefiles.
When you do not explicitly specify the target(s) to make, it will use the first target whose name doesn't start with a dot. Here, that target is stub.
Apparently, you expect all of the targets of the first rule to be used, but there can only be one default target.
The documentation isn't 100% clear on this.
You will get the desired behavior by prepending the rule:
all: $(SUBDIRS)
In the current system, there was a ghetto hack to initiate a parallel build for the system. For instance, to call a parallel make required make JOBS=8 instead of make -j8. I have since fixed the makefile, however there are a lot of previous dependencies on the JOBS flags within scripts that call make. I was hoping to recursively call make as a workaround as such:
ifdef JOBS
%:
$(MAKE) $(MAKECMDGOALS) JOBS= -j$(JOBS)
endif
This has some odd behavior though. It will first call make JOBS= -j8 as it should, but after this rule is completed it seems to go on and rebuild everything again that is in $(MAKECMDGOALS).
#Example
TARGETS = lib0 lib1 lib2
ifdef JOBS
%:
$(MAKE) $(MAKECMDGOALS) -j$(JOBS) JOBS=
endif
all: $(TARGETS)
lib%:
#echo g++ $#
Cmd: make JOBS=8.
This is fine for most rules, however it keeps wasting time rebuilding PHONY rules, so this should be fixed. Is there a way to completely reroute a make JOBS=N command to make -j$(JOBS) without executing any other rules redundantly in either scope? (meaning nothing executes except a submake in make JOBS=N, and the submake is only called once with all $(MAKECMDGOALS) at once.)
EDIT: I would also like to avoid large ifdef; else; endif statements, at the very most putting a self contained one at the top of the file. I'm starting to think the solution may require something like that though:
TARGETS = lib0 lib1 lib2
ifdef JOBS
%: unique_make
#echo $# built > /dev/null
.PHONY: unique_make
unique_make:
$(MAKE) $(MAKECMDGOALS) -j$(JOBS) JOBS=
else
all: $(TARGETS)
lib%:
#echo g++ $#
endif
In GNU make, you can modify the make flags within a Makefile. Why not try something like this:
ifdef JOBS
MAKEFLAGS+=-j$(JOBS)
endif
The question is about parallel making w/ GNU makefile.
Given a folder structure as below, the goal is to deliver a makefile that it supports make release/debug/clean in parallel.
project folder structure:
foo
+-foo1
+-foo2
+-foo3
The makefile may be sth like:
SUBDIR = foo1 foo2 foo3
.PHONY $(SUBDIR) release debug clean
release: $(SUBDIR)
$(SUBDIR):
$(MAKE) -C $# release
debug: $(SUBDIR)
#below is incorrect. $(SUBDIR) is overriden.
$(SUBDIR):
$(MAKE) -C $# debug
..
Sub directory list are set as phony targets for parallel making. but it lost the information of original target (release, debug, clean etc).
One method is to suffix the names for the directories and recover it in commands, but it is weird. another method might be to use variables, but not sure how to work it out.
The questions is:
How to write the rules for directories, that supports parallel making w/ different targets (release/debug/clean)?
Any hints are greatly appreciated.
Setting variables on the command line certainly works. You can also use MAKECMDGOALS (see the GNU make manual):
$(SUBDIR):
$(MAKE) -C $# $(MAKECMDGOALS)
I would like a makefile where I can call:
'make' / 'make <subdir>' / 'make clean' / 'make <subdir> clean'
But I do not want it to attempt to resolve clean when called on a subdir!
Here's an example of my makefile:
SUBDIRS := a b c
all :
#echo building a b and c
clean :
#echo cleaning a b and c
$(SUBDIRS) :
make - C $# $(MAKECMDGOALS)
All the calls work well except make <subdir> clean which calls make -C <subdir> clean, but then attempts to also resolve target clean separately. How can I get make to stop processing later targets?
To both answers:
thank you for your explanation. it is helpful to know what is and what is not meant to be done. i will not attempt this anymore.
Sigh
Yes, you can do this, but it'll be an ugly hack and totally contrary to the way Make is designed to work.
The set of targets you pass to Make is a set of targets, not a structured command with syntax. Make is expected to build them all. If the makefile includes a recipe for the target foo, then Make should build the target foo a certain way, regardless of whether it is invoked as Make foo or Make foo bar or Make bar foo. What you are attempting to do breaks the accepted behavior of Make, so you should try a different approach.
If you still wanted to do it, you could do it like this:
SUBDIRS := a b c
.PHONY: clean
ifneq ($(filter $(SUBDIRS), $(MAKECMDGOALS)),)
$(SUBDIRS) :
#echo make - C $# $(MAKECMDGOALS)
clean:
#: # do nothing
else
all :
#echo default
clean :
#echo cleaning
endif
I fully agree with Beta's statements on misusing make. Another way of achieving what you want, would be to introduce explicit targets for cleaning the subdirectories. This way, for instance, you can call make clean_<subdir>.
SUBDIRS := a b c
all:
#echo building a b and c
clean:
#echo cleaning a b and c
$(SUBDIRS):
make - C $#
$(addprefix clean_, $(SUBDIRS)): clean_%:
make -C $* clean
I have been working on makefiles and trying to reduce their compilation time. The structure of the my code consists of various sub directories each having its own makefile. The subdirectories in the main directory seem to be independent as whenever i run make in any of the subdirectories, it runs perfectly fine and shows no error. Thus, i want to run the sub-make for all subdirectories in parallel. Is it possible> and if yes, how?
Thank you in advance
Here is a crude but effective method:
SUBDIRS = /something /something/else /another
.PHONY: $(SUBDIRS) all
all: $(SUBDIRS)
$(SUBDIRS):
#$(MAKE) -s -C $#
Run this with make -j.