使用Makefile目标设置构建选项

7
这可能有些琐碎,或者与make的使用哲学相悖,但我想要一个类似于“make debug”而不是“make DEBUG=1”的命令行。我尝试创建一个名为debug的伪目标,除了设置DEBUG变量外没有任何操作,但是这样会导致“make debug build”和“make build debug”之间存在差异--也就是说,在某些情况下,变量在编译后才被设置。
是否有一种方法可以使某些目标具有优先级?
感谢您的帮助。
6个回答

5

10
提到一下只需要为目标执行target: DEBUG=1,而不是将他指向文档... 对吗? - dlamotte
这难道不解决了“make build debug”和“make debug build”不等价的问题吗?这个特定的功能正是我尝试的。 - leoger
1
回想起来,我可以看出那与你的问题相符,但你没有表述清楚。Make目标总是有序的,所以我认为你正在执行一个不可能的任务。 - bmargulies
在这种情况下,那正是我需要知道的。谢谢! - leoger

3
你可以通过查看MAKECMDGOALS变量来实现。
ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
DEBUG = 1
endif

build:
    @echo build and DEBUG is [$(DEBUG)]

debug:

这是你调用它时会发生的事情:
$ make build
build and DEBUG is []
$ make build debug
build and DEBUG is [1]
make: Nothing to be done for `debug'.
$ make debug build
make: Nothing to be done for `debug'.
build and DEBUG is [1]

1

你可以写以下内容:

.PHONY: debug
debug:
        $(MAKE) -$(MAKEFLAGS) build DEBUG=1

build:
        echo makeflags='$(MAKEFLAGS)' debug=${DEBUG}

这个至少可以与GNU Make、BSD Make和Interix Make一起使用。我没有尝试过所有其他的实现。


以可移植性为代价,进行make文件的递归评估。 - dmckee --- ex-moderator kitten

1

GnuMake 的一个功能是使用宏,这些宏可以扩展为带有 foreach 内置规则的规则。例如:

TARGETS := build all foo bar baz

define DEBUG_TARGET_RULE
$(1).debug:
        $$(MAKE) DEBUG=1 $(1)
debug.$(1):
        $$(MAKE) DEBUG=1 $(1)
endef

$(foreach target,$(TARGETS),$(eval $(call DEBUG_TARGET_RULE,$(target))))

这将允许您键入make debug.foomake foo.debug,它会自动转换为make DEBUG=1 foo,并且对于您放置在$(TARGETS)中的任何目标都有效。

不完全是我想要的,但是很酷的解决方法,也展示了 make 的一个有用特性。 - leoger

0
一种方法是在构建和调试目标中设置依赖项和构建规则,但将调试选项添加到调试目标中。一个简单的例子:
Makefile
program:        program.c
                gcc -o program program.c
debug:          program.c
                gcc -D DEBUG -o program program.c

Program.c

#include <stdio.h>
int main(void) {
#ifdef DEBUG
  printf("DEBUG on!\n");
#endif
  printf("in the program\n");
  return 0;
}

0
如果你的调试仅用于构建目标,那么最好让调试调用构建,这样你只需输入make debugmake build,其中make build将是非调试版本。

至于你实际的问题,我对Makefile不够熟悉,无法回答。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接