Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile多目标与分离目标为模式提供了不同的结果_Makefile - Fatal编程技术网

Makefile多目标与分离目标为模式提供了不同的结果

Makefile多目标与分离目标为模式提供了不同的结果,makefile,Makefile,我的makefile失败了。我的想法是从某个文件中提取文件并将它们放在临时目录中。然后将其重新同步到源目录。由于rsync仅在文件发生更改时更新,因此除非必要,否则不会重新生成源目录中的makefile。我已将问题隔离如下: .PHONY: extract clean FILES = filea1.cc filea2.cc filea3.cc \ filea1.hh filea2.hh filea3.hh

我的makefile失败了。我的想法是从某个文件中提取文件并将它们放在临时目录中。然后将其重新同步到源目录。由于rsync仅在文件发生更改时更新,因此除非必要,否则不会重新生成源目录中的makefile。我已将问题隔离如下:

.PHONY: extract clean

FILES = filea1.cc filea2.cc filea3.cc                       \
        filea1.hh filea2.hh filea3.hh                       \
        filea1.py filea2.py filea3.py                       \
        dir-cc/filea1.cc dir-cc/filea2.cc dir-cc/filea3.cc  \
        dir-cc/filea1.hh dir-cc/filea2.hh dir-cc/filea3.hh  \
        dir-py/filea1.py dir-py/filea2.py dir-py/filea3.py

PATTERN   := $(sort $(addprefix build/%., $(patsubst .%,%,$(suffix $(FILES)))))

extract: $(addprefix build/, $(FILES))

$(PATTERN):
    mkdir -p $(dir $@); echo "hello!" > $@

#build/%.cc:;mkdir -p $(dir $@); echo "hello!" > $@
#build/%.hh:;mkdir -p $(dir $@); echo "hello!" > $@
#build/%.py:;mkdir -p $(dir $@); echo "hello!" > $@

temp:
    echo $(PATTERN)

clean:
    rm -rf build
执行make temp会得到“build/%.cc build/%.hh build/%.py”,但“make extract”无法生成所有文件:

build:
dir-cc  dir-py  filea1.cc  filea2.cc  filea3.cc

build/dir-cc:
filea1.cc  filea2.cc  filea3.cc

build/dir-py:
filea1.py  filea2.py  filea3.py
build:
dir-cc  filea1.cc  filea1.py  filea2.hh  filea3.cc  filea3.py
dir-py  filea1.hh  filea2.cc  filea2.py  filea3.hh

build/dir-cc:
filea1.cc  filea1.hh  filea2.cc  filea2.hh  filea3.cc  filea3.hh

build/dir-py:
filea1.py  filea2.py  filea3.py
hh文件丢失。令人难以置信的是,在实际工作中,cc文件丢失了。无论如何,注释掉$(模式)并删除注释,以使上述代码中的目标是分开的,确实会得到所有文件:

build:
dir-cc  dir-py  filea1.cc  filea2.cc  filea3.cc

build/dir-cc:
filea1.cc  filea2.cc  filea3.cc

build/dir-py:
filea1.py  filea2.py  filea3.py
build:
dir-cc  filea1.cc  filea1.py  filea2.hh  filea3.cc  filea3.py
dir-py  filea1.hh  filea2.cc  filea2.py  filea3.hh

build/dir-cc:
filea1.cc  filea1.hh  filea2.cc  filea2.hh  filea3.cc  filea3.hh

build/dir-py:
filea1.py  filea2.py  filea3.py

由于在实际工作中,所有内容都必须是自动的,并且所有目标的规则都是相同的(因此我不必重新键入),因此我非常喜欢第一个版本。我读了手册,但我不明白为什么要这样做。我使用的是GNU Make 4.1。

本节最后一段对此进行了解释:

模式规则可能有多个目标。与普通规则不同的是,这并不像许多具有相同先决条件和配方的不同规则那样起作用。如果模式规则有多个目标,make知道规则的配方负责生成所有目标。配方只执行一次以生成所有目标

您不能编写具有许多不同模式目标的模式规则,这样make将针对每个目标运行一次配方。这不是它的工作原理

对于非常简单的案例,您可以这样做:

FILETYPES := $(sort $(suffix $(FILES)))

$(foreach T,$(FILETYPES),$(eval build/%$T: ; mkdir -p $$(@D); echo "hello!" > $$@))

有一个很好的解决方案:使用普通(非模式)多目标 规则<代码>$(文件):;规则并定义要调整的模式特定变量值
将规则设置为文件扩展名。

Duh。谢谢帮助很大。尽管如此,令人困惑。自从make讲述mkdir-p build/以来,这个配方似乎已经运行了不止一次;echo“hello!”>build/filea1.cc mkdir-p build/;echo“hello!”>build/filea2.cc mkdir-p build/;echo“hello!”>build/filea3.cc mkdir-p build/dir cc/;echo“hello!”>build/dir cc/filea1.cc…当然,它会为每个匹配模式运行一次。也就是说,它将为
build/filea1.cc
运行一次,但是make希望运行此配方一次也会在目标列表中创建其他模式:
build/filea1.hh
build/filea1.py
,因此它不会尝试单独构建这些模式。但是make并不认为运行一个模式会创建所有可能与这些模式匹配的文件。好吧,它可以这样说,对于遇到这种情况的任何人来说:模式规则可能有多个目标。与普通规则不同的是,这并不像许多具有相同先决条件和配方的不同规则那样起作用。如果模式规则有多个目标,那么在配方的每次运行中,make都假设构建了配方运行中多目标列表中匹配的所有目标。应该注意的是,配方确实构建了所有这样的目标,因为make只尝试构建任何目标一次。