【问题标题】:Makefile rule to copy sources from many folders从多个文件夹复制源的 Makefile 规则
【发布时间】:2016-05-04 14:51:53
【问题描述】:

我有大量的 Makefile,它们在整个目录集合中生成 XML 文件。我想编写一个“客户端”Makefile 来挑选一些最终产品,并仅复制已修改的产品。我可以很容易地为每个文件制定规则,但鉴于每个源文件的文件夹不同,我没有看到如何使用模式规则。我宁愿只需要将源文件弹出到列表中,让其他一切正常工作。比如:

SOURCE_DIR = somedir
TARGET_DIR = otherdir
SOURCES = \
        $(SOURCE_DIR)/dir1/file1.xml \
        $(SOURCE_DIR)/dir2/file2.xml \
        $(SOURCE_DIR)/dir3/file3.xml \
        $(SOURCE_DIR)/dir4/file4.xml
TARGETS = $(patsubst %,$(TARGET_DIR)/%,$(addsuffix xml,$(basename $(SOURCES))))

all: $(TARGETS)

$(TARGET_DIR)/%.xml: $(???)/%.xml:
        cp $< $@

我不知道要在 $(???) 中添加什么。

编辑:根据 cmets 添加示例

这是我想到的一个例子:

SOURCE_DIR = /project/Data
TARGET_DIR = src/XML
SOURCES = \
        $(SOURCE_DIR)/Airports/airports.xml \
        $(SOURCE_DIR)/Product/ISIC/isic.xml \
        $(SOURCE_DIR)/PortSources/ports.xml \
        $(SOURCE_DIR)/Commodity/htscodes.xml

目标最终会解决为:

  • src/XML/airports.xml
  • src/XML/isic.xml
  • src/XML/ports.xml
  • src/XML/htscodes.xml

因此,例如,如果/project/Data/Product/ISIC/isic.xmlsrc/XML/isic.xml 更新,并且/project/Data/Product/Commodity/htscodes.xmlsrc/XML/htscodes.xml 更新,那么make 的输出应该是:

cp /project/Data/Product/ISIC/isic.xml src/XML/isic.xml
cp /project/Data/Commodity/htscodes.xml src/XML/htscodes.xml

【问题讨论】:

  • 我不明白您为什么要删除 .xml 后缀,然后再重新添加。但是由于您正在尝试复制目录结构(据我所知......如果您展示了所需源和目标路径名的明确示例 - 例如“正确”调用的示例cp) 你不能用SOURCE_DIR 代替???吗?
  • 我不打算这样做,但我不知道如何告诉 $(basename) 只删除目录而不删除后缀。
  • 好吧,basename 不会删除目录。这就是为什么我在评论中说您正在复制目录结构。在 GNU make 手册中的示例中,$(basename src/foo.c) 扩展为 src/foo。如果你真的希望它扩展到foo.c,你应该使用notdir,而不是basename
  • 如果您想避免不必要地复制内容,使用rsync 代替cp 怎么样?

标签: makefile


【解决方案1】:

好的,既然我看到了你的例子,你想要什么就更清楚了:你创建TARGETS 的方式不适合你想做的事情。正如我在上面的评论中一样,您需要notdir

你可以用VPATH做你想做的事,像这样:

SOURCE_DIR = /project/Data
TARGET_DIR = src/XML
SOURCES = \
    $(SOURCE_DIR)/Airports/airports.xml \
    $(SOURCE_DIR)/Product/ISIC/isic.xml \
    $(SOURCE_DIR)/PortSources/ports.xml \
    $(SOURCE_DIR)/Commodity/htscodes.xml

vpath %.xml $(sort $(dir $(SOURCES)))

TARGETS = $(addprefix $(TARGET_DIR)/,$(notdir $(SOURCES)))

all: $(TARGETS)
.PHONY: all

$(TARGET_DIR)/%.xml : %.xml
        cp $< $@

【讨论】:

  • 这很有意义,谢谢。不知道为什么,但是在修改了 Makefile 之后,我现在得到“make: *** No rule to make target src/XML/ports.xml', needed by all'。停止。”
  • 这意味着它在 vpath 目录中找不到ports.xml。您必须使用$(info $(sort $(dirname $(SOURCES)))) 来查看目录列表并确保它们是正确的,并且可能在运行-d 调试的情况下运行make(这将提供大量输出)。此解决方案假定这些文件在 make 启动之前已经存在。如果 SOURCES 文件本身必须从其他目标生成,则不能使用 vpath。
  • 啊,它应该是 $(dir,而不是 $(dirname。它现在工作正常。它不会让我编辑你的帖子,因为差异小于六个字符。:-/
  • 糟糕。固定的。对不起。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多