【问题标题】:File not found when using variable file names使用可变文件名时找不到文件
【发布时间】:2018-12-04 23:58:35
【问题描述】:

我刚刚开始尝试在 makefile 中同时使用静态模式规则和 for 循环,我对使用 makefile 还是比较陌生,所以如果我遗漏了一些明显的东西,请原谅我。

在下面的代码中,我尝试使用 for 循环创建 6 个可执行文件,每个唯一文件两个。

这是生成文件:

vpath %.h ../headers/
CXX      := g++
CXXFLAGS := -std=c++11 -I../headers/
LDFLAGS  :=
SUFFIX   := fileA fileB fileC

memory-%.exe: primary-%.o memory.cpp
       $(CXX) $(CXXFLAGS) $^ -o $@
timing-%.exe: primary-%.o timing.cpp
       $(CXX) $(CXXFLAGS) $^ -o $@

all:   for i in $(SUFFIX); \
       do \
       testing-$$i.exe: primary-$$i.o; \
       memory-$$i.exe: primary-$$i.o; \
       done

我遇到了错误:

\bin\sh: 3: memory-fileA.exe:: not found
\bin\sh: 4: timing-fileA.exe:: not found
\bin\sh: 3: memory-fileB.exe:: not found
\bin\sh: 4: timing-fileB.exe:: not found
\bin\sh: 3: memory-fileC.exe:: not found
\bin\sh: 4: timing-fileC.exe:: not found
make: *** [all] Error 127

首先这是否可能?我只是想知道使用这种方法是否可以提高效率。

感谢任何帮助,因为我想更多地了解 makefile 允许的可能性。 谢谢你。

【问题讨论】:

  • 仔细查看错误,\bin\sh: 3: memory-fileA.exe:: not found。请注意额外的冒号 (:),它是文件名的一部分。您是否有一个名为 memory-fileA.exe: 的文件,其末尾有一个冒号 (:)?我打赌不会。 testing-$$i.exe: primary-$$i.o 中冒号的作用是什么?你的意思是,也许,testing-$$i.exe primary-$$i.o
  • 该行的想法是遵循静态模式规则,以便创建文件“memory-fileA.exe”
  • 配方中的每一行都由 shell 执行,而不是 Make 本身。您正在尝试的可能可以通过简单的make 函数来完成;在 GNU Make 文档中查找 $(foreach ...)$(patsubst ...) 以及 $(eval ...)
  • @tripleee 我明白你在说什么,我觉得这将是一个好主意。如果我的意思是正确的,那就使用 $(foreach program, $(SUFFIX), $(eval $(patsubstr ...))) 但是我迷路了。我一直在环顾四周,但我不明白如何创建正确的命令来执行该过程。如果可能的话,你能引导我朝着正确的方向前进吗?对不起,我无法理解我在网上其他地方可以找到的内容。

标签: makefile sh


【解决方案1】:

您正在混合外壳并制作构造。正如tripleee 指出的那样,make 规则的配方是 shell 脚本,而不是其他 make 规则。

此外,您的 Makefile 存在一些问题:

  1. 您解释说您想使用static pattern rules,但您写的是“简单pattern rules
  2. 您不需要引用您的后缀。而且您不应该, make 不是外壳,它会保留它们。因此,您会收到错误消息。
  3. 您使用标准的CXXFLAGS make 变量是非常不寻常的。传统上,它仅限于编译器的标志,而不是使用 CXX 的编译器本身。
  4. 您正在同时编译源文件和链接。这也不太常见。它会导致无用的重新编译。
  5. g++c++11 选项对我来说是新的。确定不是-std=c++11
  6. vpath 指令没有用,因为您没有表达对头文件的依赖关系。但是,让我们保留它吧,我猜您并没有展示所有内容。

总而言之,您可以通过以下方式实现您想要的:

vpath %.h ../headers/
CXX      := g++
CXXFLAGS := -std=c++11 -I../headers/
LDFLAGS  :=
SUFFIX   := fileA fileB fileC
TESTING  := $(patsubst %,testing-%.exe,$(SUFFIX))
MEMORY   := $(patsubst %,memory-%.exe,$(SUFFIX))

.PHONY: all

all: $(TESTING) $(MEMORY)

%.o: %.cpp
    $(CXX) $(CXXFLAGS) -c $^ -o $@

$(TESTING): testing-%.exe: primary-%.o memory.o
    $(CXX) $(LDFLAGS) $^ -o $@

$(MEMORY): memory-%.exe: primary-%.o timing.o
    $(CXX) $(LDFLAGS) $^ -o $@

%.o: %.cpp... 规则是pattern rule。它告诉 make 如何从相应的 C++ 源文件生成任何目标文件。最后两条规则真的是static pattern rules。例如,两者中的第一个声明$(TESTING) 中列出的每个目标testing-<suffix>.exe 依赖于相应的primary-<suffix>.omemory.o。因此,这个单一的静态模式规则等同于以下 3 条简单规则:

testing-fileA.exe: primary-fileA.o memory.o
    g++ primary-fileA.o memory.o -o testing-fileA.exe

testing-fileB.exe: primary-fileB.o memory.o
    g++ primary-fileB.o memory.o -o testing-fileB.exe

testing-fileC.exe: primary-fileC.o memory.o
    g++ primary-fileC.o memory.o -o testing-fileC.exe

不需要循环。请注意,如果您正确使用标准 make 变量 CXXCXXFLAGS,则可以删除模式规则 (%.o: %.cpp...),它是 make 已经知道的众多 implicit rules 之一。

【讨论】:

  • 非常感谢您,这对我很有帮助,并为我展示了一种更好的方法;但是,我遇到了命令行告诉我:没有规则可以让所有人都需要目标“testing-fileA.exe”。在处理这个问题的大部分时间里,我一直遇到这个问题
  • 我无法重现您的问题。你有primary-fileA.cppmemory.cpp 源文件和你的Makefile 在同一个目录吗?您是否从同一目录调用 make ?您是否仔细复制粘贴了我的示例并在食谱中用制表符替换了前导空格?
  • 我已将使用上述代码时出现的问题发布到原件中 - 请检查它以防我遗漏了一些明显的东西。谢谢,非常感谢您的时间和帮助。
  • 正如我在上一条评论中所写,查看您的编辑,您没有primary-fileA.cpp 文件。你想如何构建primary-fileA.o?如果没有源文件,make 或 g++ 将无能为力。
猜你喜欢
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2023-03-03
相关资源
最近更新 更多