Makefile与源/目标文件在不同的目录中

时间:2017-12-06 01:02:34

标签: linux makefile compilation

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

         $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创建的。我遇到makefile的问题,指定源文件在$tests/*/*.e中,目标文件在$doc/tests/*.rst中。

我已经看过几个类似的问题,但是无法使用正确的makefile语法。

此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

我在使用完整的对象列表时遇到了麻烦,例如

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'.

1 个答案:

答案 0 :(得分:3)

(这个问题看起来非常熟悉 - 我几乎发誓已经提出并回答了一个基本相同的问题。)

让我们分阶段进行。我们可以一次写一条规则:

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

但这很乏味。正是这种情况迫切需要一个通配符解决方案,例如模式规则,但Make的一个严重缺点是它对通配符的粗略处理。重复使用通配符的模式规则:

$(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))
...

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

TESTS := test1 test2 ...

$(foreach TEST,$(TESTS),$(eval $(call template,$(TEST)))

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

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

all: $(TARGETS)

将所有这些放在一起很简单,但这个答案很长。