makefile - 在不同的目录中,具有源/对象文件

  显示原文与译文双语对照的内容
57 4

我有一个具有以下目录结构的项目:

 $tests/$doc/
 | |-makefile 
 +------+-------+ |
 | | | tests/
 test1/test2/test3/|
 | | | test1.rst, test2.rst, test3.rst
 test1.e test2.e test3.e

$doc/tests 目录 比如 test1.rst 中的文件是从 $tests/test1/test1.e 创建的。指定源文件位于 $tests/*/*.e 中且目标文件位于 $doc/tests/*.rst 中时,生成文件出现问题。

我已经看到几个类似的问题,但是还不能正确地练习makefile语法。

这里生成文件适用于单个文件示例

SOURCES = $(wildcard $(tests)/*/*.e)
OBJECTS = $(addprefix $(doc)/tests/,$(notdir $(SOURCES:.e=.rst)))
# single file trial
SRC = $(tests)/test1/test1.e
OBJ = $(doc)/tests/test1.rst
$(OBJ): $(SRC)
debugvars:
 @echo SOURCES=$(SOURCES)
 @echo OBJECTS=$(OBJECTS)
# define how to create any RST file from a testcase
%.rst:
 $(scripts)/wr_rst.py --infile $<
# define how to create an RST file from a testcase
%.rst: %.e
 $(scripts)/wr_rst.py --infile $<
.e.rst:
 $(scripts)/wr_rst.py --infile $<
.SUFFIXES:. e. rst

我在使用 i.e.的完整列表时遇到了问题

all: $(OBJECTS)
$(OBJECTS): $(SOURCES)
 $(scripts)/wr_rst.py --infile $<

test1.rst 生成 3次,而忽略 test2,3.rst$(SOURCES)$(OBJECTS) 是正确的。我怀疑 $< 不会对 (SOURCES) 进行迭代

下面是 make -d的一些输出

 No implicit rule found for `$tests/test3/test3.e'. 
 Finished prerequisites of target file `$tests/test3/test3.e'. 
No need to remake target `$tests/test3/test3.e'. 
Considering target file `tests/test3.rst'.
 File `tests/test3.rst' does not exist.
 Pruning file `$tests/test1/test1.e'.
 Pruning file `$tests/test2/test2.e'.
 Pruning file `$tests/test3/test3.e'.
 Finished prerequisites of target file `tests/test3.rst'.
Must remake target `tests/test3.rst'.
$scripts/wr_rst.py --inile $tests/test1/test1.e
Putting child 0x00ee6420 (tests/test3.rst) PID 11720 on the chain.
Live child 0x00ee6420 (tests/test3.rst) PID 11720
Writing RST file $doc/tests/test1.rst
Reaping winning child 0x00ee6420 PID 11720
Removing child 0x00ee6420 PID 11720 from chain.
Successfully remade target file `tests/test3.rst'.
时间:原作者:0个回答

62 3

( 这个问题看起来非常的familiar--,我几乎会保证一个实质上是相同的。)

让我们循序渐进。我们可以一次写一个规则:

$(doc)/tests/test1.rst: $(tests)/test1/test1.e
. . .

但这很烦人,这种情况对通配符解决方案( 例如 Pattern 规则) 是一种粗糙的处理。在其中重复通配符的Pattern 规则:

$(doc)/tests/%.rst: $(tests)/%/%.e
. . .

不允许,但我们可以使用 eval 编写规则:

define template
$(doc)/tests/$(1).rst: $(tests)/$(1)/$(1).e
 use some tool to build $$@ from $$<
endef
$(eval $(call template,test1))
$(eval $(call template,test2))
...

然后,我们可以将该作业委托给 foreach,而不是编写所有的eval 语句:

TESTS := test1 test2.. .
$(foreach TEST,$(TESTS),$(eval $(call template,$(TEST)))

我们可以将该列表委托给 wildcard,而不用编写该测试列表,而是使用相同的列表来构造目标文件列表:

TESTS := $(notdir $(wildcard $(tests)/*))
TARGETS := $(patsubst %,$(doc)/tests/%.rst,$(TESTS))
all: $(TARGETS)

把所有这些都放在一起是很简单的,但是这个答案很长。

原作者:
...