Smarty77
Smarty77

Reputation: 1348

Why this simple makefile does not rebuild the source on changes?

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

Answers (2)

Omada
Omada

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

MadScientist
MadScientist

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

Related Questions