GNU Make:chdir make 进程本身

GNU Make: chdir make process itself

是否可以使用将 make 进程本身定向到 chdir 的 makefile?我想编写一个希望从构建目录执行的 makefile。

假设我有一个如下所示的项目目录结构

project/
├── Makefile
├── include
│   └── Foo.h
├── src
│   └── Foo.cpp
└── test
    └── FooTest.cpp

make 目录做的第一件事就是创建一个构建目录。

project/
├── Makefile
├── _build
├── include
│   └── Foo.h
├── src
│   └── Foo.cpp
└── test
    └── FooTest.cpp

是否可以将 chdir 的 makefile 定向到 _build 以简化我的规则?

我希望能够写作(例如)

foo : Foo.o
    $(LD) $^ -o $@ $(LDFLAGS)

而不是

_build/foo : _build/Foo.o
    $(LD) $^ -o $@ $(LDFLAGS)

我知道我可以将构建目录添加到 VPATH 以影响路径解析,但仅 chdir Make 本身似乎更干净。有没有办法做到这一点(最好不使用诡计)?

您可以制作一个简单的 Makefile 来转发所有内容:

.DEFAULT_GOAL := all
.PHONY: ${MAKECMDGOALS}
$(filter-out all,${MAKECMDGOALS}) all: .forward-all ; @:
.forward-all:
        ${MAKE} -C build ${MAKECMDGOALS}
# Never try to remake this makefile.
${MAKEFILE_LIST}: ;
.SUFFIXES:

GNU Make 无法做到这一点,但 NetBSD 的 bmake 可以做到这一点。

假设我们有一个具有以下结构的项目:

.
├── foo.c
├── makefile
└── obj/

foo.c是一个简单的C程序,只依赖于标准库。

/* foo.c */
#include <stdio.h>

int main() {
    printf("%s\n", "hi there");
}

makefile 使用 GNU Make 和 bmake 的通用子集。一般来说,坚持公共子集是乏味的,不值得做,这只是为了举例。

default: foo

.c.o:
    $(CC) -c -o $@ $<

foo : foo.o
    $(CC) -o $@ foo.o

运行 bmake 产生以下输出

$ bmake
cc -c -o foo.o /tmp/make-example/foo.c
cc -o foo foo.o

并生成以下目录结构

.
├── foo.c
├── makefile
└── obj/
    ├── foo
    └── foo.o

通过检查输出可以清楚地看到 bmake 几乎立即 chdir 进入了 obj 目录。 obj 目录中的输出路径是相对路径,源目录中的路径是绝对路径。