【问题标题】:Two step compilation procedure with gnu make使用 gnu make 的两步编译过程
【发布时间】:2016-08-01 01:56:16
【问题描述】:

我有一堆文件 (*.txt),我使用 python 脚本分析并从中生成代码 (*.cpp)。代码生成完成后,我希望将生成的代码编译成目标文件 (*.o)。

我想使用 gnu-make 来设置它。我的问题是我想不出一个有效的 Makefile 语法来完成这个。

这里有一些额外的细节让这更难:

由于我一开始不知道存在多少 *.txt 文件,所以我想使用 shell find 命令来发现它们。

files := $(shell find $(TXT_FILE_DIR) -type f -name '*.txt')

但是,我仍然希望 gnu-make 的精细依赖功能在这里工作。也就是说,如果任何 txt 文件发生更改,我希望 make 自动发现这些更改,并且仅发现这些更改,并为它们生成新的 .cpp 文件并将它们重新编译为 .o 文件。

我正在寻找一种解决方案,其中make 可以并行运行(并尊重 -j 标志)并调用将 *.txt 文件转换为 *.cpp 文件的 python 脚本。

我的操作系统是 Linux。

[新信息]

感谢 Grexis,感谢您的回答!但是,因为我在 src 和 dst-paths 之间的映射有点奇怪,所以我实际上正在寻找不同的解决方案。

以下是翻译我的 src 和 dst 路径时“奇怪”的示例:

$(TXT_DIR)/a/XXX.*XXX/b/c/file1.txt -> $(CPP_DIR)/a/YYY/b/c/file1.cpp $(TXT_DIR)/a/XXX.*XXX/b/c/file2.txt -> $(CPP_DIR)/a/YYY/b/c/file2.cpp $(TXT_DIR)/b/XXX.*XXX/c/d/file3.txt -> $(CPP_DIR)/b/YYY/c/d/file3.cpp

注意这里的路径被操纵了两次。因此,两者:

  1. $(TXT_DIR) 替换为 $(CPP_DIR)
  2. 正则表达式XXX.*XXX替换为固定字符串YYY

但是,由于在 gnu-make 中很难进行多个字符串替换,例如,gnu-make 一次只支持单个 % (stem) 字符串替换,我认为我必须使用更高级的 gnu -make 语法。因此,我正在寻找一种方法来定义“每个 .txt -> .cpp 对的不同配方”。我尝试了以下方法:

cleanPath = $(shell echo $(1) | sed s/XXX.*XXX/YYY/g) txt2cpp = $(subst $(TXT_DIR),$(CPP_DIR),$(patsubst %.txt,%.cpp,$(call cleanPath,$(1)))) txt2obj = $(subst $(TXT_DIR),$(OBJ_DIR),$(patsubst %.txt,%.o,$(call cleanPath,$(1)))) define analyse = $(2): $(1) python.py $(2) $(3) endef txt_files := $(shell find $(TXT_DIR) -type f -name '*.txt') cpps := $(foreach file,$(txt_files),$(eval $(call analyse,$(file),$(call txt2cpp,$(file)),$(call txt2obj,$(file))))) all: $(cpps)

但是,我的 python.py 脚本似乎从未被调用过。这是为什么呢?

如果我在shell-命令中包含对python.py 的调用,例如$(shell python.py $(2) $(3)),则实际上调用了python.py 脚本。然而,使用shell-command 使得并行性变得不可能。不幸的是,不能并行执行python.py 脚本对我来说不是一个选项。

【问题讨论】:

    标签: gnu-make


    【解决方案1】:

    不清楚每个文本文件是否只创建一个具有匹配名称的 C++ 源代码(即“foo.txt”被处理为“foo.cpp”,然后被处理为“foo.o”)。

    假设它是直接关系,您要查找的功能称为Pattern Rules

    TXT_FILES := $(wildcard $(TXT_FILE_DIR)/*.txt)
    OBJ_FILES := $(patsubst $(TXT_FILE_DIR)/%.txt,$(OUT_DIR)/%.o,$(TXT_FILES))
    
    main: $(OBJ_FILES)
        $(CXX) $(LDFLAGS) -o $@ $^
    
    $(SRC_DIR)/%.cpp: $(TXT_FILE_DIR)/%.txt
        $(PYTHON) process.py $<
    
    $(OUT_DIR)/%.o: $(SRC_DIR)/%.cpp
        $(CXX) -c $(CPPFLAGS) -o $@ $<
    

    分解上面的sn-p。 $(TXT_FILES) 设置为$(TXT_FILE_DIR) 中的每个*.txt 文件,并在make 中使用通配符操作。 $(OBJ_FILES) 使用$(TXT_FILES) 中的所有值进行模式替换。然后将每个 obj 文件作为依赖项添加到 main 可执行文件。

    如上面链接的模式规则链接文档中所述,每个.o 文件都需要$(SRC_DIR) 中的关联.cpp 文件(自动变量$@$^$&lt; 也记录在提供的链接)。反过来,每个.cpp 文件都需要一个同名的.txt

    不过,您可能需要调整您的 python 脚本的确切调用。如果需要指定特定的输出文件,则应使用$@ 自动变量。

    顶部用于检测所有源文件的部分来自this answer

    【讨论】:

    • 我喜欢这个答案,但我认为通过将模式规则更改为静态模式规则会有所改进。在这种情况下很容易:${OBJ_FILES}: ${OUT_DIR}/%.o: ${SRC_DIR}/%.cpp
    猜你喜欢
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 2011-05-27
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多