What does this part mean in Makefile?
1 CC=gcc
2 CXX=g++
3 RM=rm
4 PROTOC=protoc
5 ODB=odb
Sorry, I'm a beginner
They're setting up substitutions so that you can later have a command like:
$(RM) x.o
and it will magically become, when executing:
rm x.o
It allows you to (for example) change it later to be rm -rf and you only change it in one place.
Typically you'll see things like:
$(CC) $(CFLAGS) -c -o object_file.o source_file.c
If you compile a compile of hundred C source files, and you suddenly discover they all needed a new -I directive, you probably want that in one single place :-)
See the "variables" section of the GNU Make manual for (much) more detail, if you wish.
We also use it in our shop for making our builds somewhat more "readable", things like:
PERM_FOR_EXE=chmod 700
PERM_FOR_CFG=chmod 400
PERM_FOR_DATA=chmod 500
RM=rm
FORCE_RM=rm -f
RM_DIR_AND_BELOW=rm -rf
PROTO_FOR_PY=protoc --output=betterproto
PROTO_FOR_CPP=protoc --output=cpp
PROTO_FOR_BCPL=echo FAT CHANCE
Related
I'm extremely new to makefiles and just spent a full day trying to figure out how to automate my testing. For this project I have one program, main.c and it accepts as parameters an input and an output file. The input file is of the form "test-{filler}.txt" so an example file could be "test-invalid-opcode.txt". The output file would be of the form "out-{filler}.txt", so it would be of the form "out-invalid-opcode.txt". I would then want to compare the output with the correct output saved in "correct-{filler}.txt", so this would be "correct-invalid-opcode.txt". Each test would therefore have an input, output, and correct output. I would want to check if the output and correct output have any differences and I would want this to run on every test file with the prefix "test-". I read through a lot of the makefile spec and a lot of different examples, but I'm really confused as to how to handle this. Any help would be really appreciated.
Here is what I have to run one test:
CC=gcc
CFLAGS=-o
main.o: main.c
$(CC) $(CFLAGS) main.o $<
.PHONY: test
test: main.o test-provided.txt test-out.cs
./program test-provided.txt test-out.txt
diff -q test-out.txt out-provided.txt
The layout of what I want the automatic test to be is something like
.PHONY: autotest
autotest: program
$(foreach <file with "test-" prefix> run:
main.o <test-name> <out-name>
diff -q <correct-name> <out-name>
But I really am lost on how to go about implementing that.
Thank you and sorry I couldn't post more code. I tried a lot of different things, but none of them were even close enough to be worth posting.
Edit to show working final version:
program: main.c
$(CC) $(CFLAGS) $a $<
TEST_INPUTS := $(wildcard test-*.txt)
.PHONY: autotest $(TEST_INPUTS)
autotest: $(TEST_INPUTS)
$(TEST_INPUTS): test-%.txt: program
echo '' > out-$*.txt
./$< $# out-$*.txt
diff -q correct-$*.txt out-$*.txt
In general using loops with make is not very "make-ish". A makefile is an entire language fundamentally based on iteration and recursion so trying to do "extra" iteration inside a recipe is often redundant.
If you need to iterate over something, most especially when that something is files, you should attempt to work with make by taking advantage of its target/prerequisite organization. Above you give an algorithm:
$(foreach <file with "test-" prefix> run:
main.o <test-name> <out-name>
diff -q <correct-name> <out-name>
which is perfectly suited to make's default behavior. To translate this into a makefile you write a rule which invokes a single iteration of the loop, then use prerequisites to run it for the files you want. Something like this:
TEST_INPUTS := $(wildcard test-*.txt)
.PHONY: autotest $(TEST_INPUTS)
autotest: $(TEST_INPUTS)
$(TEST_INPUTS): test-%.txt: program
$< $# test-out.txt
diff -q test-out.txt out-$*.txt
Not only is this much more make-like but it has other advantages: for example you can run make test-provided.txt and it will run just that one test instead of all the tests.
You have to use static pattern rules here not normal pattern rules because .PHONY targets can't work with pattern rules.
I have a project that consists a single target that requires ~30 files of type A, that are handled by one pattern rule, and one different target of type B, that is independent of the other 30. Here's some pseudo-code to show what I have, in a very simplified form:
OBJECTS=obj/obj1.o obj/obj2.o ...
SPECIAL=special/specialobj.o
libMyLibrary.so: $(OBJECTS) $(SPECIAL)
g++ -shared -o $# $^
obj/%.o: src/%.cxx
g++ -c -fPIC -o $# $^
$(SPECIAL): special/mySpecialCode.cxx
g++ -c -fPIC -o $# $^ -DFANCY_FLAG
The makefile works fine, and the dependency resolution is flawless. However, somehow, make always decides to build $(SPECIAL) last. While this doesn't matter at all, as it works either way, the compilation of $(SPECIAL) takes significantly longer than anything else in my case, almost as long as all other objects combined. Hence, it would be nice if one could encourage make to start with compiling $(SPECIAL), so that it can be compiled in parallel along the others, which would cut compile time dramatically.
Is it possible to achieve such a thing?
PS: I can live with non-portable versions, as the code is a very dedicated piece of software that will only be compiled and run on a very particular set of machines, the setup of which I know pretty well at development time.
EDIT
Following up on a comment made me realise that in the case I have shown here, the problem can indeed be solved by simply swapping the order $(OBJECTS) $(SPECIAL) to $(SPECIAL) $(OBJECTS) - sometimes, it's that simple.
However, in my actual usecase, this does not work, so I have built an MWE that (1) actually works (with gnumake) and is (2) a little bit closer to how things actually work in my project.
Here, the file that takes so long to compile actually depends on a source file that is only generated in an additional step. You can observe the change in order by swapping the two lines following the comment.
If somebody can provide a way how to fix the behavior also for this case, that would be great!
If it's not possible to change the order to the desired one in this case, I will accept any answer that explains to some details why it's impossible.
OBJECTS=obj/obj1.o obj/obj2.o obj/obj3.o obj/obj4.o obj/obj5.o
SPECIAL=special/specialobj.o
SPECIALSRC=special/mySpecialCode.cxx
OBJ_DIR=obj
SPECIAL_DIR=special
all: libMyLibrary
$(SPECIAL_DIR):
mkdir -p $#
$(OBJ_DIR):
mkdir -p $#
libMyLibrary: $(SPECIAL) $(OBJECTS)
cat $^ > $#
obj/%.o: | $(OBJ_DIR)
#echo creating $#
#echo $# > $#
$(SPECIALSRC): | $(SPECIAL_DIR)
#echo special > $#
# swap the following two lines to observe the change in ordering
# $(SPECIAL): $(SPECIALSRC) | $(SPECIAL_DIR)
$(SPECIAL): | $(SPECIAL_DIR)
#echo starting special
#echo special > $#
#sleep 1s
#echo special done
clean:
rm -rf libMyLibrary $(OBJ_DIR) $(SPECIAL_DIR)
I would like to change the working directory of a makefile.
(Extraneous info: I have a legacy makefile that I mostly want to reuse, though many targets and generated deps files make assume that the working directory will not be different. My idea is to create a makefile for my newer project, which is in a different directory, and include the old one, and set the working directory to the old directory.)
I easily can do this from the command line with
make -f /path/to/new/makefile -C /path/to/old/makefile
The users of this makefile would like not to type that out every time.
Attempt 1
Use MAKEFLAGS in the makefile itself. But neither of these seem to have any effect. (I understand why -f couldn't have an effect; I'm really wondering about -C.)
I've looked at http://www.gnu.org/software/make/manual/html_node/Options-Summary.html, but I can't find anything about what is allowed in MAKEFLAGS and what isn't.
Attempt 2
Create a makefile2 with the new targets
include path/to/old/makefile
foo: bar
and then makefile passes everything through
%:
$(MAKE) -f $(abspath makefile2) -C path/to/old/makfele /$*
I don't get nice autocompletion, parallel jobs don't work, and debug options (dry run) doesn't work.
So
(1) Why doesn't -C work MAKEFLAGS (it does work, but I made a mistake; it doesn't work, and it is documented; it doesn't work, and it is not documented but it is intentional; it doesn't work, and it is a bug)?
(2) Is there a better way of change a makefile's working directory?
Some things are wrong here :
make -f /path/to/new/makefile -C /path/to/old/makefile
The -f options specifies the name of the Makefile to be found when searched in the directory specified with -C (or the current directory if not provided). So it is more :
make -C /path/to/old/Makefile -f name_of_old_makefile
If the name is simply Makefile or makefile, there is no need to provide the -foption.
The MAKEFLAGS variable does not contains -f or -C in the called sub-Makefile.
To be able to pass multiple targets to another makefile, you need the MAKECMDGOALS variable.
Ultimately, all you have to do in your new Makefile is to have someting like this :
all:
$(MAKE) $(MAKEFLAGS) -C /path/to/old/Makefile -f old_Makefile_name $#
%:
$(MAKE) $(MAKEFLAGS) -C /path/to/old/Makefile -f old_Makefile_name $(MAKECMDGOALS)
I have a complex makefile with a lot of recipes. I would like run them with no parallel execution except for the generation of my objects files. I noticed that the .NOTPARALLEL target cannot take any prerequisites otherwise it would have been much easier to solve my issue.
My first guess was to use a nonexistent target named ".PARALLEL" with which I would have mentioned the objects files as dependancies like this:
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
.PARALLEL: $(OBJ)
%.o: %.c
gcc –c –o$# $< -M
a.out: $(OBJ)
gcc –o$# $^
A more functional solution I have found is to use an intermediate target. However, since MyObjects has no dependancies, make will always call MyObjects and recreate a.out.
%.o: %.c
$(CC) –c –o$# $< -M
MyObjects:
$(MAKE) -j $(OBJ)
a.out: MyObjects
$(CC) –o$# $(OBJ)
To avoid this I've found nothing better than using dummy files. I wrote this example to illustrate it:
NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SRC = $(addsuffix .c, $(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))
DUM = $(addsuffix .dummy,$(OBJ))
all: a.out
$(SRC):%.c:
touch $#
$(OBJ):%.o: %.c
cp $< $#
touch $(addsuffix .dummy, $#)
$(DUM):
$(MAKE) -j8 $(OBJ)
a.out: $(DUM) $(OBJ)
zip $# $(OBJ)
clean:
-rm *.o
-rm *.out
-rm *.c
-rm *.dummy
I'm sure this is not the best solution I can get. I would be glad to get some help.
P.S. MadScientist, thank you for your advices.
This is really not right:
MyObjects: $(OBJ)
$(MAKE) -j $(OBJ)
This means that before make tries to build the MyObjects target, it will first try to update all the $(OBJ) files. Once that's all done, then it will try to build the MyObjects target by recursively invoking make to rebuild them again. Obviously that's not what you want. Plus you're using -j which is basically "infinitely parallel" and is likely (if you have enough object files) to bring your system to its knees.
You want something like this:
MyObjects:
$(MAKE) -j5 $(OBJ)
As for your second question about trying to rebuild targets, there's no way we can help without some kind of specific example. Typically this happens because your rules are written incorrectly, and they don't actually update the target you told make they would. So for example, you have a target recipe_a but the rule for recipe_a updates some other target, not recipe_a.
I'll add a few notes based on your second question. Probably if you don't get it after this you should take this off of StackOverflow and ask on the help-make#gnu.org mailing list, or else consider breaking this up and asking several specific StackOverflow questions.
First, why you see make[1]: '15.o' is up to date. for every file in your recursive make: because make always prints that message for every target on the command line, so if you run make 1.o 2.o 3.o ... (doesn't matter whether you use -j or not or what value of -j you use) you'll get that message for every target which doesn't need to be rebuilt. Just as if you ran that same make command from the command line yourself.
Second, why you don't get a.out is up to date, because a.out is NOT up to date. It depends on the build target, and the file build doesn't exist, and thus it's out of date, and so it must be rebuilt every time. And that means anything that depends on the build target, like a.out, must be rebuilt every time. Which explains why it always re-runs the zip command.
Third, the behavior with all.c is because if you create a pattern rule like %.c: with no prerequisites, that tells make that it can create ANY file with a .c extension by running that command. Well, one of the targets you asked make to build is the all target. Since you didn't declare that as a .PHONY target, make tries to build it. Normally that attempt fails because make can't find any rules that know how to build all so nothing happens, but after you tell make how to build a .c file out of nothing (no prerequisites), then when make wants to build all it looks in its internal database of predefined rules and sees a pattern rule % : %.c, which tells make how to build an executable from a source file with the same name (on UNIX systems executables don't have any suffix like .exe: they're just make or cc etc.) So, make tries to run those rules and they fail.
For any target which you don't expect to actually be created, like all, clean, etc. you should declare them to be .PHONY so make won't try to build them.
As for your problem. I think the simplest thing to do is push the entire build of the zip file down into the recursive make, rather than trying to build the objects only in the recursive make. Something like this:
NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SRC = $(addsuffix .c,$(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))
all: recurse
recurse: non-parallel-targets
$(MAKE) -j8 a.out PARALLEL=true
ifneq($(PARALLEL),true)
.NOTPARALLEL:
endif
%.o: %.c
cp $< $#
a.out: $(OBJ)
zip $# $(OBJ)
init: $(SRC)
clean:
-rm *.o
-rm *.out
.PHONY: all clean init
I'm sure this is a totally normal thing to do, but I can't figure out how to get make to do this.
I have a compiler that generates make dependencies of the usual form:
M/A.o : M/A.hs
M/B.o : M/A.o
So I write a rule to compile %.hs into %.o, add a rule to link the binary, include the dependencies file, and all is well. But I want to have several binary targets with different flags. E.g. I want build/test built with -DTESTING and build/profile built with -prof. So I need to keep the .o files in a separate tree, where they will be compiled with special flags.
The straightforward way I can think of would be to have dependencies that look something like this:
build/test/M/A.o : M/A.hs
build/test/M/B.o : build/test/M/A.o
build/profile/M/A.o : M/A.hs
... etc.
And then rules so that %.hs to build/test/%.o compiles with -DTESTING, etc. I think this would work, but it's clumsy, means preprocessing the deps file to add all that build/whatever/ prefix stuff, and would multiply its size by however many kinds of builds.
VPATH appears to be designed for this sort of thing and my idea was that I could set the VPATH and compiler flags depending on the target, and it almost works, but:
%.o: %.hs
#mkdir -p build/M
cp $< build/$#
VPATH = build
main: M/A.o M/B.o
cat $^ >$#
M/A.o : M/A.hs
M/B.o : M/B.hs
The first time the main target wants to run 'cat M/A.o M/B.o >main' which seems contrary to the gnu make documentation that says $^ should include the include the VPATH directory in which the dependency was found. Curiously, if I remove 'main' and make again, this time it uses the correct path. This is GNU make, 3.81.
What's going on here? Is there a better way to build with different flags? VPATH seems like a clumsy tool, surely there is a better way?
Make is working correctly. It tries cat M/A.o M/B.o >main the first time because it can't find the prerequisites it needs, but it knows a rule for M/A.o' andM/B.o(<em>not</em>build/M/A.o' and build/M/B.o) and expects that that is what the rule will produce. If you remove main and try again, it will find build/M/A.o' andbuild/M/B.o` via VPATH.
Let's modify this makefile in stages. First we change the VPATH so that it can find the .hs files (Make is good at using things there to build things here, not vise-versa, and that's what VPATH is good for), and change the rules slightly:
build/%.o: %.hs
cp $< $#
VPATH = M
main: build/A.o build/B.o
cat $^ > $#
Now for the different object directories.
build/test/%.o build/project/%.o: %.hs
cp $< $#
VPATH = M
test: build/test/A.o build/test/B.o
cat $^ > $#
project: build/project/A.o build/project/B.o
cat $^ > $#
Then we simplify those last two rules, so that it's easy to add more object files and binary targets:
OBJECTS = A.o B.o
test: $(addprefix build/test/,$(OBJECTS))
project: $(addprefix build/project/,$(OBJECTS))
test project:
cat $^ > $#
Now for the different compiler flags:
build/test/%.o: FLAGS += test_flags
build/project/%.o: FLAGS += proj_flags
build/test/%.o build/project/%.o: %.hs
#echo building $# from $^ using flags $(FLAGS)
cp $< $#
Finally the dependencies. This is a little tricky. Suppose you want the dependency B.o : A.hs to apply to however many object you have. This is one approach:
OBJECT_PATHS = build/test/ build/project/
# The following is from the included file generated by the compiler
$(addsuffix B.o,$(OBJECT_PATHS)) : A.hs
To generate lines like that, I'd pipe the raw lines (e.g. B.o: A.hs) through sed 's/\(.*\):\(.*\)/\1:\2/', and note that if you want to put this in a makefile command, don't forget to double the $ signs to preserve them for the shell.
I know that's a lot to absorb. Take it one step at a time and let us know how it works out.
If you haven't solved your problem by now or are experiencing further problems, best give the autotools (automake and autoconf) a chance. They'll quickly build you a Makefile that supports more configurable and flexible out-of-tree builds.