9

Lets say I have files:

Libs:

  • one.cpp, one.h
  • two.cpp, two.h
  • three.cpp, three.h

Program:

  • program.cpp

Is there way, to create Makefile which will compile only that *.cpp which were modified from last compilation?

Currently I have something like that:

SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)

all: $(OBJS) program

.cpp.o:
    g++ -Wall -c $<

program:
    g++ -Wall $(OBJS) program.cpp -o program

clean:
    rm -f $(OBJS) program

I works fine, but when I compile my program and then change two.cpp or two.h I need to run "make clean" first, because when I secondly run "make" I get:

Nothing to be done for 'all'.

I would like to change my Makefile in that way, it would recognize my changes and recompile that file and its dependencies (if one.cpp uses code from two.cpp which was modified, both files should be recompiled).

So if I modify two.cpp, make should do:

g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program

But if one.cpp uses code from two.cpp which was modified, make shold do:

g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
user360872
  • 1,261
  • 4
  • 15
  • 15

3 Answers3

12

First we make the object files prerequisites of the executable. Once this is done, Make will rebuild program whenever one of the SRCS changes, so we don't need OBJS as an explicit target:

all: program

program: $(OBJS)
  g++ -Wall $(OBJS) program.cpp -o program

Then we make the header files prerequisites of the objects, so that if we change three.h, Make will rebuild three.o:

$(OBJS): %.o : %.h

And finally since one.cpp uses code from two.cpp by means of two.h (I hope), we make two.h a prerequisite of one.o:

one.o: two.h

And to make things cleaner and easier to maintain we use automatic variables:

program: $(OBJS)
  g++ -Wall $^ program.cpp -o $@

Put it all together and we get:

SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)

all: program

$(OBJS): %.o : %.h

one.o: two.h

.cpp.o:
  g++ -Wall -c $<

program: $(OBJS)
  g++ -Wall $^ program.cpp -o $@

clean:
  rm -f $(OBJS) program

There are a few more things we could do (like adding program.o to OBJS), but this is enough for today.

Beta
  • 96,650
  • 16
  • 149
  • 150
1

Add the files a command depends upon to run to the right of the target name.

Example:

default: hello.c
   gcc -o hello.bin hello.c

install: hello.bin
   cp hello.bin ../
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
mcandre
  • 22,868
  • 20
  • 88
  • 147
  • Isn't that what `$(OBJS)` is for? – JAB Jun 21 '10 at 18:52
  • You tell me, it's your code. I've never used variables in the dependency fields, but there's nothing logically that prevents that from working. – mcandre Jun 21 '10 at 19:23
  • Variables can be prerequisites, but there are other things that should be prereqs in the OP's makefile besides `$(OBJS)`. – Beta Jun 21 '10 at 22:34
0

All you need to do is tell make that the .o file depends on the .cpp file:

%.cpp.o: %.cpp
    g++ -Wall -c -o $@ $<
JSBձոգչ
  • 40,684
  • 18
  • 101
  • 169