Reputation: 1348
I wrote this simple makefile, which works fine until I want to do some changes and apply them into binary. Then I need to do 'make clean' and 'make' again, because obj. file will not be rebuilt. Althought it seems like a simple task so far I failed to modify it in order to make obj. file rebuild implicitly (So I can write only 'make' when I modify source).
COMPILER=g++-5.3
CXXFLAGS=-std=c++11 -O2 -pedantic
build : a.o
$(COMPILER) a.o -o a
a.o:
$(COMPILER) $(CXXFLAGS) -c a.cpp -o a.o
clean :
rm -f *.o *~ a
Edit: I tried changes suggested by Omada (I tried the same myself before I wrote this question) and this is result:
me@pc: ~/mypath$ cat a.cpp
#include <iostream>
int main(int argc, char* argv[])
{
if ( argc!=2 ){
std::ceaaarr<<"Prrogram expects 1 argument\n";
return 1;
}
return 0;
}me@pc: ~/mypath$ make
g++-5.3 a.o -o a
me@pc: ~/mypath$ cat Makefile
#init
COMPILER=g++-5.3
CXXFLAGS=-std=c++11 -O2 -pedantic
build: a.o
$(COMPILER) a.o -o a
a.o: a.cpp
$(COMPILER) $(CXXFLAGS) -c a.cpp -o a.o
clean:
rm -f *.o *~ a
Upvotes: 3
Views: 2908
Reputation: 784
Since you never told the makefile that a.o
depends on a.cpp
, it won't be able to determine that when a.cpp
changes, it should rebuild a.o
.
To fix this change
a.o:
$(COMPILER) $(CXXFLAGS) -c a.cpp -o a.o
to this
a.o: a.cpp
$(COMPILER) $(CXXFLAGS) -c a.cpp -o a.o
Let me know if it doesn't work, I'm a bit rusty on my makefiles.
Upvotes: 5
Reputation: 100836
If you tell make what to do, it will do what you say. If you write a rule with a target that builds a.o
and has no prerequisites listed, then make thinks that the target has no prerequisites: in that case if the target (a.o
) exists, then make will assume it's up to date. Omada tells you how to avoid that by adding prerequisites. You could also, instead of defining your own rule, simply use make's built-in rules that already know how to create an object file from a .cpp
file (but, it uses the CXX
variable not COMPILER
).
Similarly, if you define a rule build: a.o
, that tells make that in order to build the target named build
, it should see if a file named build
exists and if a.o
is newer than it. If the file build
doesn't exist, then it will run the recipe you've provided.
Since your recipe, $(COMPILER) $(CXXFLAGS) a.o -o a
doesn't actually create a file named build
, it's always out of date and will always be run.
You must ensure that your recipe actually creates the name of the target you're trying to build:
a: a.o
$(COMPILER) a.o -o a
Upvotes: 1