【问题标题】:vpath not picking up newly built objectsvpath 没有拾取新建的对象
【发布时间】:2020-06-25 20:26:42
【问题描述】:

我有这个 Makefile(和 GNU Make):

vpath %.o .objs

OBJDIR=.objs

all: symbol_tests.so

symbol_tests.so: symbol_tests.o symbol.o   # simulate linking
    @echo Linking target: $@, prerequisites: $^

%.o: %.c | $(OBJDIR)/
    gcc -o $(OBJDIR)/$@ -c $<

$(OBJDIR)/:
    -mkdir $@

但是构建(没有任何子目录或对象存在)给我这个:

mkdir .objs/
gcc -o .objs/symbol_tests.o -c symbol_tests.c
gcc -o .objs/symbol.o -c symbol.c
Linking target: symbol_tests.so, prerequisites: symbol_tests.o symbol.o

很明显,因为symbol.osymbol_test.o 都不存在,所以它们需要被构建。 并且它们被正确放置在子目录./objs

但是当“链接”时,vpath 不会在.objs 子目录中获取新创建的.o-文件。

这不是很奇怪吗?再次运行make 会得到:

Linking target: symbol_tests.so, prerequisites: .objs/symbol_tests.o .objs/symbol.o

在我看来,为了触发在子目录中搜索 .o,当调用 make 时,它们必须存在。这样就违背了vpath的目的,不是吗?

还是我的Makefile或对vpath的理解有问题?

注意:在 vpath 指令中包含 $(OBJDIR) 不起作用。为什么?

【问题讨论】:

标签: makefile gnu-make vpath automatic-variable


【解决方案1】:

这似乎不适用于 GNU Make 或我尝试过的任何其他 Make。

我认为 vpath$(VPATH) [和 BSD Make .PATH:] 仅对原始源(即在调用 Make 之前存在的文件,而不是任何中间目标)真正有效。

请特别参阅 GNU Autoconf 手册中的以下警告:

在显式规则中使用 $

在 Gnu Autoconf 手册部分12.14 VPATH and Make 中查看更多注意事项。

您当然可以通过在对 make 的递归调用中执行最后的链接步骤来欺骗它,但这似乎很浪费,特别是如果您为大量目标执行此操作。

BSD Make 管理对象目录的创建,方法是自动将当前工作目录更改为对象目录,然后通过${.CURDIR} 变量显式查找源——make 首次调用的位置。

不幸的是,GNU Make 只设置了它的$(CURDIR) 它处理-C 选项之后。似乎首选的 GNU Make 做事方式(尤其是与其他 GNU Autotools 结合使用)是为 Make 过程使用单独的构建目录。 IE。创建一个单独的空构建目录,然后在其中运行 configure 脚本,并带有构建目录的相对路径:

mkdir build
cd build
../configure

这会在构建目录中创建所有必要的Makefiles,然后您也可以在构建目录中运行 Make:

gmake

这当然是确保不会在源目录中创建目标(中间或其他目标)的最安全方法。

您也可以避免vpath,直接将对象目录添加到每个对象目标名称中,如此答案:https://stackoverflow.com/a/37469528/816536

【讨论】:

  • 我是从每个先决条件前面都有$(OBJDIR) 来的,感觉有点混乱,但至少它是明确的。我会考虑改用OBJDIR,但可能会忘记有一个单独的OBJDIR,反正我不会在这个项目中进行多架构编译。或者使用一些patsubst 魔法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
  • 2014-10-29
相关资源
最近更新 更多