Makefile用于发布和调试目标

时间:2018-03-18 09:57:42

标签: makefile gnu-make

我正在尝试构建一个可以通过指定目标而不是变量来构建发布和调试目标的Makefile(例如make debug=1,而不是很好)我在这里有一个简洁的简化示例,模仿我的内容试图实现:

ifdef debug
    BINARY=my_binary_debug
    MODULE_1_BIN=abc_debug
    MODULE_2_BIN=xyz_debug
    export DBG=1
else
    BINARY=my_binary
    MODULE_1_BIN=abc
    MODULE_2_BIN=xyz
endif

FLAG=something

.PHONY: all debug clean

all: bin/$(BINARY).bin

bin/$(BINARY).bin: module_1/$(MODULE_1_BIN).bin module_2/$(MODULE_2_BIN).bin
    cat module_1/$(MODULE_1_BIN).bin $(FLAG) module_2/$(MODULE_2_BIN).bin > $@

module_1/$(MODULE_1_BIN).bin:
    $(MAKE) -C module_1

module_2/$(MODULE_2_BIN).bin:
    $(MAKE) -C module_2


clean:
    rm bin/*.bin
    $(MAKE) -C module_1 clean
    $(MAKE) -C module_2 clean

这个例子让我使用make debug=1,但我不是很喜欢它,觉得这个实现可能会更好。一种方法是使用目标特定变量,但我不完全确定如何在构建调试目标时依赖项还需要更改其名称时如何使用它们。类似的东西:

debug: export DBG:=1
debug: bin/$(BINARY)_debug.bin
debug: module_1/$(MODULE_1_BIN)_debug.bin
debug: module_2/$(MODULE_2_BIN)_debug.bin

bin/$(BINARY).bin bin/$(BINARY)_debug.bin: module_1/$(MODULE_1_BIN).bin module_2/$(MODULE_2_BIN).bin
        cat module_1/$(MODULE_1_BIN).bin module_2/$(MODULE_2_BIN).bin > $@

此处目标可以正常工作,因为在构建bin/$(BINARY).bin时不需要构建debug目标。但我不知道如何处理依赖项module_1/$(MODULE_1_BIN).bin和{{ 1}}在构建module_2/$(MODULE_2_BIN).bin

时的配方中

2 个答案:

答案 0 :(得分:1)

此答案的先前版本尝试使用特定于目标的变量,但它们的用途有限,因为它们用于配方,但在指定目标和先决条件时会被忽略。

隐式规则使用模式,但使用隐式目标my_binary捕获my_binary_debugmy_binary%不起作用,因为模式不起作用匹配空字符串。

然而,在这种情况下,隐式规则起作用,因为所有目标和依赖关系都具有公共结尾.bin,这是非空的。与%匹配的字符串在自动变量$*中是可用的。 所以这是我的解决方案:

.PHONY: all debug clean

FLAG=something 

# Maybe still needed by subdirectory makefiles
debug: export DBG:=1

all: bin/my_binary.bin
debug: bin/my_binary_debug.bin

# % will match both ".bin" and "_debug.bin"
# It won’t match the empty string.
bin/my_binary%: module_1/abc% module_2/xyz%
    cat module_1/abc$* $(FLAG) module_2/xyz$* > $@

# Maybe, by specifying the target in the sub-make commandline,
# you can get rid of the DBG variable altogether.
module_1/abc%:
    $(MAKE) -C module_1 $@

module_2/xyz%:
    $(MAKE) -C module_2 $@

clean:
    rm bin/*.bin
    $(MAKE) -C module_1 clean
    $(MAKE) -C module_2 clean

如果构建bin/my_binary.bin的配方可以一个接一个地重写所有模块并且在开头$(FLAG),则可以进行更多的简化:

.PHONY: all debug clean

MODULES = module_1/abc module_2/xyz
FLAG    = something 

# Maybe still needed by subdirectory makefiles
debug: export DBG:=1

all: bin/my_binary.bin
debug: bin/my_binary_debug.bin

bin/my_binary%: $(addsuffix %,$(MODULES))
    cat $(FLAG) $^ > $@

module_1/abc%:
    $(MAKE) -C module_1 $@

module_2/xyz%:
    $(MAKE) -C module_2 $@

clean:
    rm bin/*.bin
    for m in $(MODULES); do $(MAKE) -C $$(dirname $$m) clean; done

答案 1 :(得分:1)

正如我之前所说,您不能在该目标的先决条件中使用特定于目标的变量,只能在该目标的配方和递归先决条件中使用。根据你的需要,我认为你能做的最好的是:

RELEASE_SUFFIX:=#
DEBUG_SUFFIX:=_debug

BINARY:=my_binary
MODULE_1_BIN:=abc
MODULE_2_BIN:=xyz

FLAG=-u

.PHONY: all debug

all: bin/$(BINARY).bin

debug: export DBG:=1
debug: BINARY+=$(DEBUG_SUFFIX)
debug: bin/$(BINARY).bin


define rules

bin/$(BINARY)$($(1)): module_1/$(MODULE_1_BIN)$($(1)).bin module_2/$(MODULE_2_BIN)$($(1)).bin
    cat $(FLAG) $$^ > $$@

module_1/$(MODULE_1_BIN)$($(1)).bin:
    $(MAKE) -C $$(@D)

module_2/$(MODULE_2_BIN)$($(1)).bin:
    $(MAKE) -C $$(@D)

endef


$(foreach suffix, RELEASE_SUFFIX DEBUG_SUFFIX, $(eval $(call rules,$(suffix))))