vpath 没有拾取新建的对象

vpath not picking up newly built objects

我有这个 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.

但是当 "linking" 时 vpath 不会在 .objs 子目录中获取新创建的 .o 文件。

这不奇怪吗? 运行 make 再次给出:

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

对我来说,为了触发在子目录中搜索 .o,它们必须在调用 make 时存在。这种做法违背了 vpath 的目的,不是吗?

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

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

这看起来不适用于 GNU Make 或我尝试过的任何其他 Make。

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

请特别注意 GNU Autoconf 手册中的以下警告:

Using $< in explicit rules is not portable. The prerequisite file must be named explicitly in the rule. If you want to find the prerequisite via a VPATH search, you have to code the whole thing manually.

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

您当然可以通过在对 make 的递归调用中执行最后的 link 步骤来愚弄它,但这似乎很浪费,尤其是当您对很多目标执行此操作时。

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

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

mkdir build
cd build
../configure

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

gmake

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

您也可以避免 vpath 并直接将对象目录添加到每个对象目标名称,如以下答案所示: