I have a question about make all command
Example Makefile:
.PHONY: all clean
all: kaldi.done python check_install
When I make all,
which of three is done first?
Related
I have the following Makefile where the all make target depends on a separate setup make target that also takes an argument. However when I make all the setup target is not invoked with the argument
setup:
...command
clean:
...command
all: setup myarg=value clean myarg=value
#echo "setup & clean"
I think what you're asking is if a prerequisite can inherit a target-specific variable. In which case, yes it can -- Note, in your example you tried to intersperse the target specific variables and the prerequisites, which you can't do. But beware -- this has sharp sticks attached. Consider the following makefile:
all:
setup:
#echo "building $#: myarg=$(myarg)"
all: myarg:=value
all: setup
#echo "building $#: myarg=$(myarg)"
blah: setup
#echo "building $#: myarg=$(myarg)"
If I do make all, I get:
tmp> make all
building setup: myarg=value
building all: myarg=value
Which is what you want. But if I do make blah, then setup is run as a prerequisite of blah, and does not have the value set as you might expect. It will not be rebuilt for main, even though the variable is different:
tmp> make blah all
building setup: myarg=
building blah: myarg=
building all: myarg=value
See the make manual for more details
The command line of the make program is not free-form. You can't just pass it a bunch of stuff and have that "stuff" passed through make to appear somehow inside your recipes. make can only take arguments that it's defined to take: all arguments (not options) are either targets or variable assignments. See the documentation or the man page.
It is not possible in general to pass arbitrary values on the make command line. However, as I said, make does allow variables to be set on its command line.
If you run make setup myarg=value then this will set the make variable myarg to have the value value, and ask make to build the setup target.
So, if you write your makefile:
setup:
...command $(myarg)
referencing the make variable myarg, then it will "work" (I guess, you haven't made clear exactly what you want to run using myarg).
The point is that I want to have some dependencies centralized in one variable, but the dependencies themselves are contained in variables.
a=meow
b=squeek
$(a):
touch $#
$(b):
touch $#
targs=$(a) $(b)
all: $(targs)
In the real case rules for a and b differ so I need them to be in separate targets.
When I try to build such a target, only last nested dependency gets executed:
$ make
touch meow
$ ls
. .. Makefile meow
Could anyone please explain me how do I fix the situation or where I'm wrong?
I can make a phony target like targs: $(a) $(b), but if there's a way to keep the structure I mentioned, I'd like to know about it.
Thanks in advance!
UPD: solved. My mistake: instead of running make all I ran make and make executed the first target instead of all.
Make's default is to use the first target in the Makefile. Either move the all target to the beginning or use the following line somewhere in your Makefile
.DEFAULT_GOAL := all
Summary: I'm dealing with a make script that generates (and optionally 'makes') a makefile. Historically it used a make make "phony target" to do so. I want to change this to make makefile because it seems more coherent and representative of what's going on. But when I change it and switch to the .FORCE idiom so it will be generated dependent on an artificial phony target, it seems the makefile is created 4 extra times for a reason I do not understand.
Details: The way the script works is that you can write either:
make -f makefile.boot
or:
make -f makefile.boot make
In the first case, it assumes you want to use the rules in makefile.boot to generate a platform-specific makefile, and then run make on that file. In the second case it assumes you only want to create the makefile but not execute it.
Here is a stripped down version of makefile.boot in make make terms that works:
top: make
$(MAKE)
make:
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
The makefile we "generate" wants to be a superset of makefile.boot. It wants to be able to do the make make generation process as well, but its top target is an actual build. So makefile.fake contains
top: product
make:
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
product:
#echo "Pretending to make build product..."
echo "Build Product" >> product
It works, but I had a thought:
"make make" is confusing to read, and it would be clearer if it was "make makefile" instead
An immediate problem with that is when you have a real target instead of a phony one, then if the file exists and has no dependencies it won't get rebuilt. I wanted this makefile to be created every time you did make makefile or make -f makefile.boot makefile. So I used the .FORCE idiom to depend on a phony target. Updated makefile.boot:
.FORCE
top: makefile
$(MAKE)
makefile: .FORCE
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
And an updated makefile.fake:
.FORCE:
top: product
makefile: .FORCE
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
product:
#echo "Pretending to make build product..."
echo "Build Product" >> product
Which seems all well and good, but it now runs the makefile generation five times:
/test$ make -f makefile.boot
Pretending to generate makefile...
cp makefile.fake makefile
make
make[1]: Entering directory '/test'
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to make build product...
echo "Build Product" >> product
make[1]: Leaving directory '/test'
The first one I want, and seems like the only one I asked for. Where are all the other calls coming from? What's triggering the four additional requests for makefile? Or in the absence of understanding, is there an alternative way of achieving my intent?
Do recall that makefile is a magic target in many make implementations, including GNU Make.
If the target makefile exists, then make will remake the makefile before doing anything else, and when it's finished it'll restart processing with the new makefile. That means that your makefile target may be run even if you don't ask for it.
Since the default action when you do make -f makefile.boot is to run make, then that's at least two potential runs of the makefile target's actions right there, before it's even looked at the product target. I can't quite make this add up to five runs, but I'd lay money that it's this special behaviour that's causing the unexpected repeats.
I have a makefile in directory foo and would like to use the same makefile in a subdirectory bar. I have been doing the following:
all:
<do work in foo>
cd bar;
make -f ../Makefile <target to make in bar>
This gets very messy when I try to do target specific variable values as I need to pass them on the command line when calling make in bar. Is there a cleaner way to do this?
I cannot tell from the question whether the following solution suites your needs, it might - or might not - work for you.
If your situation is that you simply want the same Makefile features available, include could be a solution. You can create a Makefile in directory bar in which you do everything you need specific to bar, and besides that, you do:
include ../foo/Makefile
Caveat! This doesn't work straight-forward. There cannot be two recipes with the same name. For example, if you want foo/Makefile to do recipeBar for all, and you want foo/Makefile to do recipeFoo and recipeBar for all, the following does not work:
foo/Makefile:
.PHONY: all
all:
recipeFoo
bar/Makefile:
.PHONY: all
all:
reciveBar
include foo/Makefile
Instead, the recipes have to be separated into unique names. However, dependency rules can be there multiple times, so it's not really a challenge to workaround this caveat. So, the following would work:
foo/Makefile:
.PHONY: all
all: allFoo
.PHONY: allFoo
allFoo:
recipeFoo
bar/Makefile:
.PHONY: all
all: allBar
.PHONY: allBar
allBar:
recipeBar
include foo/Makefile
Now, if you run make in bar, it would run recipeFoo and recipeBar.
If the sequence matters to you and recipeFoo must run before recipeBar, make allBar dependent on allFoo, like this:
bar/Makefile:
.PHONY: all
all: allBar
.PHONY: allBar
allBar: allFoo
recipeBar
include foo/Makefile
If you want your target-specific variables available when you call another make (for which I recommend to use $(MAKE) not make), you can export your variables - with the corresponding consequences (environment space overflow risk on some Windows versions, .
For example, if you have a target-specific variable FOO for target all in Makefile, and you want that when calling Submake.mak that variable is known, it works like this:
Makefile:
all: export FOO:=bar
.PHONY: all
all:
$(MAKE) -f Submake.mak
Submake.mak:
.PHONY: all
all:
echo $(FOO)
Create a link (hard or symbolic, your choice) in bar to ../Makefile. Then, as Carl points out in his comment, you can make -C bar and everything should work. (As of gmake 3.81, at least, make switches to the new directory first, then does its thing. I cannot speak for gmake 4.0.)
I know this has been asked before, but please bear with me. run_test is the name of the file I would like to make. I prefer invoking as 'make run_test'. I want the prereq's makefile to be called each time I call make run_test. But I don't want the call to the prereq's make to force run_test to be rebuilt.
run_test: build_prereq prereq_dir/prereq_ts
rebuild_test.sh
.PHONY: build_prereq
build_prereq:
make -C prereq_dir
prereq_dir/prereq_ts is updated if make -C prereq (prereq_dir/makefile) detects that prereq's dependencies are old and prereq needs to be rebuilt.
The problem with this is that rebuilt_test.sh is always called, and I assume that is because one of run_test's dependencies is executed (as it is PHONY).
I have resolved this issue by changing run_test to:
run_test:: build_prereq
run_test:: prereq_dir/prereq_ts
rebuild_test.sh
.PHONY: build_prereq
build_prereq:
make -C prereq_dir
Is this a good solution? This first runs build_prereq, and then it runs rebuild_test.sh if prereq_dir/prereq_ts is updated (which would happen in build_prereq's make call if needed).
Is there a more proper way of doing this. I do not want to create additional targets as that doesn't allow a direct call of make ie 'make run_test'.
Make supports exactly what you want.
.PHONY: build_prereq
build_prereq:
${MAKE} -C prereq_dir
prereq_dir/prereq_ts: build_prereq ;
run_test: prereq_dir/prereq_ts
rebuild_test.sh
So, you ask make to build run_test.
To ensure prereq_dir/prereq_ts is up to date it first runs the
recipe for build_prereq.
Next it runs the recipe for prereq_dir/prereq_ts (which does nothing—see that ;).
Now it checks the time-stamp of prereq_dir/prereq_ts to decide whether run_test is out of date.
Perfect.
If you're willing to be non-portable, GNU make supports order-only prerequisites (see the GNU make manual) which do exactly what you want:
run_test: | build_prereq
build_prereq:
$(MAKE) -C prereq_dir
(note always use $(MAKE) when invoking sub-makes, never make)