Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you implement a Makefile that remembers the last build target?

Let's say you have a Makefile with two pseudo-targets, 'all' and 'debug'. The 'debug' target is meant to build the same project as 'all', except with some different compile switches (like -ggdb, for example). Since the targets use different compile switches, you obviously need to rebuild the entire project if you switch between the two. But GNUmake doesn't naturally recognize this.

So if you type make all you'll get

Building ...
...

Then if you type make debug, you get

make: Nothing to be done for `debug'.

So my question is: how do you implement a clean solution in the Makefile to notice that the last build used a different pseudo-target, or different compile switches, than the one you want currently? If they are different, the Makefile would rebuild everything.

like image 341
Elliot Cameron Avatar asked Mar 07 '11 16:03

Elliot Cameron


People also ask

What is := in makefile?

Expanded assignment = defines a recursively-expanded variable. := defines a simply-expanded variable.

What is all Target in makefile?

all target is usually the first in the makefile, since if you just write make in command line, without specifying the target, it will build the first target. And you expect it to be all . all is usually also a . PHONY target.

How do I use makefile clean?

The Cleanup Rule clean: rm *.o prog3 This is an optional rule. It allows you to type 'make clean' at the command line to get rid of your object and executable files. Sometimes the compiler will link or compile files incorrectly and the only way to get a fresh start is to remove all the object and executable files.


1 Answers

Put the build products into different directory trees (whilst keeping one copy of the source of course). That way you are always just a short compile from an up-to-date build, be it debug or release (or even others). No possibility of confusion either.

EDIT

Sketch of the above.

src := 1.c 2.c 3.c
bare-objs := ${src:%.c=%.o}
release-objs := ${bare-objs:%=Release/%}
debug-objs := ${bare-objs:%=Debug/%}

Release/prog: ${release-objs}
Debug/prog: ${debug-objs}

${release-objs}: Release/%.o: %.c # You gotta lurve static pattern rules
    gcc -c $< -o $@

${debug-objs}: Debug/%.o: %.c
    gcc -c $< -o $@

Release/prog Debug/prog:
    gcc $^ -o $@

.PHONY: all
all: Release/prog ; echo $@ Success

.PHONY: debug
debug: Debug/prog ; echo $@ Success

(Disclaimer: not tested, nor even run through make.)

There you go. It's even -j safe so you can do make -j5 all debug. There is a lot of obvious boiler plate just crying out for tidying up.

like image 142
bobbogo Avatar answered Nov 15 '22 12:11

bobbogo