Reputation: 20173
So, I'm trying to understand makefiles. At this moment I have a project with some modules, which are more or less non-dependent on each others.
My directory tree is like this:
root/
- Source/ <-- referenced as $(INPUTPATH)
- Build/ <-- referenced as $(BUILDPATH)
- Release/ <-- referenced as $(OUTPUTPATH)
- Makefile
I want to have the source (.cpp/.h) on the Source/, the objects on the Build/, and the executable on the Release/*.
So, my idea was to have several different targets, and use them like this:
all: maps auxiliars methods
@echo "linking...";\
$(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o ${OUTPUTPATH}/MainProgram
dependency1: $(INPUTPATH)/foo.cpp
@echo "compiling ArbPrecision...";\
cd ${BUILDPATH};\
$(CC) $(CFLAGS) $(CINCLUDE) -c ../$?
dependency2: dependency1 $(INPUTPATH)/bar.cpp
@echo "compiling saddleConstructor...";\
cd ${BUILDPATH};\
$(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/bar.cpp
maps: dependency2 $(INPUTPATH)/*Map.cpp
@echo "compiling maps...";\
cd ${BUILDPATH};\
$(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/*Map.cpp
... (auxiliars and methods)
The $CINCLUDE and CFLAGS are just compiler stuff like headers and external libs.
Everything works almost perfect: on every target, it asks for other target's dependencies, and for the *cpp on the source. If this does not exist, it calls the target and compiles the *cpp. The executable is created without errors.
However, if I call the "make" twice, the time it takes to compile is the same for the first and second time, even if I don't make any changes on the source. So, apparently, I'm not putting the dependencies right.
Can anyone point me the right direction to perform this compilation? I'm doing something wrong and I'm not getting what it is.
Thanks, Jorge
Upvotes: 2
Views: 404
Reputation: 58442
Make expects to operate off of files. For each rule, it checks to see if the target file named by that rule (1) exists and (2) is up to date (i.e., modified after any of its dependencies). If the file is not up to date, then it executes the rule to bring it up to date.
Therefore, as your makefile is currently written, when you run make
, Make does the following:
all
is the first rule, so if you don't specify any arguments, make processes the all
rule.all
exists, so the all
rule needs to be executed.all
depends on the dependency1
rule. No file named dependency1
exists, so the dependency1
rule needs to be executed.dependency1
depends on the dependency2
rule. No file named dependency2
exists, so the dependency2
rule needs to be executed.What you instead want is something similar to the following:
OBJS := foo.o bar.o Map.o
all: $(OUTPUTPATH)/MainProgram
$(OUTPUTPATH)/MainProgram: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o $(OUTPUTPATH)/MainProgram
%.o: %.cpp
$(CC) $(CFLAGS) $(CINCLUDE) $< -c $@
.PHONY: all
Note the following:
$<
and $@
automatic variables are used to specify the first prerequisite (file) and the target (file), respectively.echo
yourself.all
is listed as a phony target, to keep Make from looking for a file named all
.Upvotes: 3