Linux 使用不同目录中的源/对象文件生成文件

Linux 使用不同目录中的源/对象文件生成文件,linux,makefile,compilation,Linux,Makefile,Compilation,我有一个具有以下目录结构的项目: $tests/ $doc/ | |-makefile +------+-------+ | | | | tests/ test1/ test2/ test3/ | | | | test1.rst, test2.rst,

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

         $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
(这个问题看起来很熟悉——我几乎可以发誓,有人问过并回答了一个基本相同的问题。)

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

$(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))
...
然后,我们可以将其委托给
通配符
,并使用相同的列表来构建目标文件列表,而不是编写测试列表:

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

all: $(TARGETS)

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

事实上,在本例中是
$(tests)。test1.test1.e
。感谢Beta,这非常有效。在我的教育中,没有办法创建新的规则,以便对于任何目标.rst文件,make在e源上以相同的名称启动脚本,而不管源/目标目录如何
.e.rst:$(脚本)/wr_rst.py--infle$
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))
...
TESTS := test1 test2 ...

$(foreach TEST,$(TESTS),$(eval $(call template,$(TEST)))
TESTS := $(notdir $(wildcard $(tests)/*))
TARGETS := $(patsubst %,$(doc)/tests/%.rst,$(TESTS))

all: $(TARGETS)