24

I have a Makefile that looks like this

CXX = g++ -O2 -Wall

all: code1 code2

code1: code1.cc utilities.cc
   $(CXX) $^ -o $@

code2: code2.cc utilities.cc
   $(CXX) $^ -o $@

What I want to do next is to include clean target so that every time I run make it will automatically delete the existing binary files of code1 and code2 before creating the new ones.

I tried to put these lines at the very end of the makefile, but it doesn't work

clean: 
    rm -f $@
    echo Clean done

What's the right way to do it?

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
neversaint
  • 60,904
  • 137
  • 310
  • 477

3 Answers3

40

The best thing is probably to create a variable that holds your binaries:

binaries=code1 code2

Then use that in the all-target, to avoid repeating:

all: clean $(binaries)

Now, you can use this with the clean-target, too, and just add some globs to catch object files and stuff:

.PHONY: clean

clean:
    rm -f $(binaries) *.o

Note use of the .PHONY to make clean a pseudo-target. This is a GNU make feature, so if you need to be portable to other make implementations, don't use it.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 11
    +1 for `.PHONY` (which is a GNU-ism, but Mostly Harmless elsewhere). However, it's a bad idea to put `clean` as a dependency of `all`; that increases build time and noise. Better to define all the *real* dependencies so that changes to source get propagated exactly as far as necessary. – Donal Fellows Apr 14 '10 at 08:46
22

In makefile language $@ means "name of the target", so rm -f $@ translates to rm -f clean.

You need to specify to rm what exactly you want to delete, like rm -f *.o code1 code2

qrdl
  • 34,062
  • 14
  • 56
  • 86
2

By the way it is written, clean rule is invoked only if it is explicitly called:

make clean

I think it is better, than make clean every time. If you want to do this by your way, try this:

CXX = g++ -O2 -Wall

all: clean code1 code2

code1: code1.cc utilities.cc
   $(CXX) $^ -o $@

code2: code2.cc utilities.cc
   $(CXX) $^ -o $@

clean: 
    rm ...
    echo Clean done
Alex F
  • 42,307
  • 41
  • 144
  • 212
  • As qrdl explained, this is wrong. "rm -f $@" becomes "rm -f clean", which would not work. – Bjarke Freund-Hansen Apr 14 '10 at 07:24
  • 1
    No downvote, but usually this is a bad idea. Anything but a very small project takes some time to build from scratch, and you really don't want to have to wait that long every time you have made a small change. – Thomas Padron-McCarthy Apr 14 '10 at 07:27
  • bjarkef: right, I just answered to the part of auto-delete. Thomas Padron-McCarthy: agree, and this is written in my post. – Alex F Apr 14 '10 at 07:30
  • 4
    Apart from this not working, one of Makefiles' aims and strengths is that you need to recompile only what you really need to recompile, not the whole project. Cleaning everytime takes away this feature from you. – ki92 Dec 19 '15 at 19:30
  • 1
    What is more, you have no guarantee that 'clean' will actually perform before 'code1' and 'code2' as there is no ordering in dependencies of 'all'. – CygnusX1 Nov 13 '16 at 16:57