与gnu make的两步编译程序

时间:2016-08-01 01:56:17

标签: gnu-make

我有一堆文件(*.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脚本。 / p>

我的操作系统是Linux。

[新信息]

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

以下是"古怪"的一个例子。在翻译我的src和dst-paths时:

$(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
  3. 但是,由于很难在gnu-make中进行多字符串替换,例如,gnu-make一次只支持单个%(词干)字符串替换,我想我必须使用更高级的gnu - 制作语法。因此,我正在寻找一种方法来为每个.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脚本。那是为什么?

    如果我将调用附加到python.py命令中的shell,例如$(shell python.py $(2) $(3)),则实际调用python.py脚本。但是,使用shell命令会使并行性成为不可能。不幸的是,无法并行执行python.py脚本不适合我。

1 个答案:

答案 0 :(得分:0)

有点不清楚每个文本文件是否只创建一个具有匹配名称的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 $@ $<

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

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

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

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