【问题标题】:How do I specify target dependant prerequisits with GNUMake?如何使用 GNU Make 指定依赖于目标的先决条件?
【发布时间】:2016-04-29 12:40:34
【问题描述】:

假设我有一个这样的源文件列表:

SOURCE=aaa.src bbb.src ccc.src

我想创建一个规则来在自己的文件夹中构建每个对应的目标,其名称取决于源文件。

源文件---->对应的输出文件/目标


aaa.src -------------------> aaa/aaa.out

bbb.src -------------------> bbb/bbb.out

ccc.src -------------------> ccc/ccc.out

如何使用 GNUMake 为此编写规则?我最大的努力是以下 Makefile:

.PHONY: all clean

CC=somecompiler

SOURCE := aaa.src bbb.src ccc.src
RTARGS := $(SOURCE:%.src=%.out)
TDIRS := $(addsuffix /,$(basename $(SOURCE)))
TARGS := $(join $(TDIRS), $(RTARGS))

all:$(TARGS)

%.out: $(SOURCE)     # Better source specification?
    @[ ! -d "$(dir $*)" ] && mkdir "$(dir $*)"
    $(CC) "$(patsubst %/,%,$(dir $*)).src" "$@"

clean:
    rm -f $(TARGS)
    rmdir --ignore-fail-on-non-empty $(TDIRS)

这里的问题是,任何一个目标(即.out 文件)都依赖于每个 源(即.src 文件),而不仅仅是具有相同基本名称的目标。我可以将注释行更改为%.out: %.src,但源文件必须与输出文件位于同一目录中。我也可以像这样编译它:

%.out: %.src
    $(CC) "$>" -o "$*/$@"

但是 make 总是会编译每个目标,不管它是否已经存在。

如何让 make 只使用适当的源文件。 在通用规则中分别指定每个目标的依赖关系的正确方法是什么?

【问题讨论】:

    标签: build-process gnu-make


    【解决方案1】:

    在 GNU Make 中,您可以与配方分开指定先决条件,并且仍然对所有 .out 文件有一个通用/模式规则:

    .PHONY: all clean
    
    all :
    
    SOURCES := aaa.src bbb.src ccc.src
    OUTPUTS := $(foreach src,${SOURCES},$(basename ${src})/${src:%.src=%.out})
    
    # Build dependencies in the form of x/x.out : x.src | x
    define ESTABLISH_DEPENDENCY =
    $(basename ${1})/${1:%.src=%.out} : ${1} | $(basename ${1}) # Also depend on the output directory.
    $(basename ${1}) : # Rule to create the output directory.
        mkdir $$@
    endef
    
    $(foreach src,${SOURCES},$(eval $(call ESTABLISH_DEPENDENCY,${src})))
    
    all : ${OUTPUTS}
    
    # Generice rule for all .out files.
    %.out :
        @echo "build $@ from $^"
        touch $@
    
    %.src : # For debugging only.
        touch $@
    
    .PHONY: all
    

    输出:

    $ make
    touch aaa.src
    mkdir aaa
    build aaa/aaa.out from aaa.src
    touch aaa/aaa.out
    touch bbb.src
    mkdir bbb
    build bbb/bbb.out from bbb.src
    touch bbb/bbb.out
    touch ccc.src
    mkdir ccc
    build ccc/ccc.out from ccc.src
    touch ccc/ccc.out
    

    请注意,对目录进行仅顺序依赖并让 make 创建它们比让每个配方首先检查目录是否存在更有效和优雅。

    【讨论】:

    • 好的,ESTABLISH_DEPENDENCY 在调用时所做的基本上是创建一个空规则,该规则仅指定依赖项和另一个创建目录的规则。我对吗?无论如何,这是非常狡猾的。谢谢!
    • @con-f-use 对。为了迂腐,它只为.out 创建了一个依赖项,没有规则。还有一个目录规则。
    • 再次感谢。请忽略我的编辑,我完全忽略了 all : 已经在第三行了
    猜你喜欢
    • 2011-03-06
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    相关资源
    最近更新 更多