GNU Makefile使用列表进行复制

时间:2014-05-21 17:25:28

标签: makefile

我对makefile很新。我发现make文件中存在一个缺陷,导致列表中的文件从单个源文件而不是列表中的每个文件中复制。

首先,有一个子模型变量SUB_MODEL_LIST,其中包含由空格分隔的0 1 2 3

以下是执行复制的细分:

$(TARGET_BIN_LIST_NEW) : $(TARGET_BIN_LIST)
    @echo copying from $< to $@
    $(call COPY, $(firstword $(TARGET_BIN_LIST)), $@)

TARGET_BIN_LIST_NEW包含由空格分隔的新文件名,由以下内容组成:

file001.200 file001.201 file001.202 file001.203

TARGET_BIN_LIST包含现有文件名,由以下内容组成:

file001c.200 file001c.201 file001c.202 file001c.203

文件扩展名的最后一位是型号。 当我读到这个时,makefile运行:

@echo copying from $< to $@
$(call COPY, $(firstword $(TARGET_BIN_LIST)), $@)

但是,由于TARGET_BIN_LIST功能,它总是使用firstword中的第一个文件名。这会导致file001.200, file001.201, file001.202, file001.203被创建,但它们都是file001c.200的副本,它们应该是列表中各自文件的副本。每个文件都与代码的子模型版本有关。

我想解决这个问题就是使用word函数。像这样:

$(TARGET_BIN_LIST_NEW) : $(TARGET_BIN_LIST)
    @echo copying from $< to $@
    $(call COPY, $(word $(sub), $(TARGET_BIN_LIST)), $@)

其中sub是SUB_MODEL_LIST的元素,但我不确定它是如何工作的。以上是否分为4个单独的调用,或者可以将其视为可以具有sub的增量值的循环

我还考虑过使用foreach循环:

$(foreach sub,$(SUB_MODEL_LIST),$(call COPY, $(word $(sub), $(TARGET_BIN_LIST)), $(word $(sub), $(TARGET_BIN_LIST_NEW)))

但我收到错误:

*** first argument to `word' function must be greater than 0.  Stop.

好的,我试过了:

$(foreach sub,$(SUB_MODEL_LIST),$(call COPY, $(word $(sub)+1, $(TARGET_BIN_LIST)), $(word $(sub)+1, $(TARGET_BIN_LIST_NEW)))

但后来我收到了错误:

*** non-numeric first argument to `word' function.  Stop.

现在我被卡住了。我希望尽可能保持现有的实现,但如果需要可以采用循环方法。

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

你必须退后一步。你误解了它是如何工作的。在制定具有多个目标的显式规则时,完全相同,因为多次编写相同的规则,每个目标一次。所以这个:

$(TARGET_BIN_LIST_NEW) : $(TARGET_BIN_LIST)
        @echo copying from $< to $@
        $(call COPY, $(firstword $(TARGET_BIN_LIST)), $@)

如果TARGET_BIN_LIST_NEWfile001.200 file001.201 file001.202 file001.203TARGET_BIN_LISTfile001c.200 file001c.201 file001c.202 file001c.203,则与撰写此内容相同:

file001.200 : file001c.200 file001c.201 file001c.202 file001c.203
        ...
file001.201 : file001c.200 file001c.201 file001c.202 file001c.203
        ...
file001.202 : file001c.200 file001c.201 file001c.202 file001c.203
        ...
file001.203 : file001c.200 file001c.201 file001c.202 file001c.203
        ...

因此,您可以清楚地看到,在运行每条规则时,$<$(firstword $(TARGET_BIN_LIST))的值将是相同的(file001c.200)。

是否真的出现这样的情况:每当fileXXXc.YYY个文件发生变化时,您想重建所有fileXXX.YYY个文件?这就是你的规则所做的事情,但根据食谱,它看起来并不像你想要的那样。

Make主要是编写一个规则来构建来自零个或多个先决条件的一个目标。如果您使用模式规则,则可以非常轻松地执行此操作:

all: $(TARGET_BIN_LIST_NEW)

file001.% : file001c.%
        @echo copying from $< to $@
        $(call COPY,$<,$@)

如果你的文件名可能有更复杂的命名约定,那么你需要更复杂的东西。

ETA:

由于您的命名惯例不适合制作模式规则功能,因此您必须做更高级的事情。您可以使用eval生成规则,如下所示:

all: $(TARGET_BIN_LIST_NEW)

define TARGET_BIN_COPY
$(1) : $(basename $(1))c$(suffix $(1))
        @echo copying from $$< to $$@
        $$(call COPY,$$<,$$@)
endef

$(foreach T,$(TARGET_BIN_LIST_NEW),$(eval $(call TARGET_BIN_COPY,$T)))

# uncomment this for debugging
#$(foreach T,$(TARGET_BIN_LIST_NEW),$(info $(call TARGET_BIN_COPY,$T)))

答案 1 :(得分:0)

首先,感谢MadScientist帮助澄清其工作原理。

这个实现对我有用:

 $(TARGET_BIN_LIST_NEW) : $(TARGET_BIN_LIST)
    @echo copying from $(filter %$(suffix $@), $(TARGET_BIN_LIST)) to $@
    $(call COPY, $(filter %$(suffix $@), $(TARGET_BIN_LIST)), $@)