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

对着背影说爱祢 提交于 2019-11-30 05:16:24

问题


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.


回答1:


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.




回答2:


Keeping variant sets of object files (as in bobbogo's solution) is probably the best way, but if for some reason you don't want to do that, you can use empty files as markers, to indicate which way you last built the executable:

%-marker:
        @rm -f $(OBJECTS) *-marker
        @touch $@

debug: GCCFLAGS += -ggdb

debug: SOMEOTHERFLAG = WHATEVER

all debug: % : %-marker
        @echo making $@
        @$(MAKE) -S GCCFLAGS='$(GCCFLAGS)' SOMEOTHERFLAG='$(SOMEOTHERFLAG)' main

There are other variants on this idea; you could have a small file containing the flag settings, which the makefile would build and include. That would be clever, but not really any cleaner than this.




回答3:


The only clean solution is to incorporate the difference into the target names. E.g. you can define a variable $(DEBUG) and consistently use it in all targets that depend on the compile step.



来源:https://stackoverflow.com/questions/5221989/how-do-you-implement-a-makefile-that-remembers-the-last-build-target

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!