GNU Make: chdir make process itself

277 Views Asked by At

Is it possible to use a makefile that directs the make process itself to chdir? I want to write a makefile that expects to be executed from the build directory.

Suppose I have a project directory structure that looks like this

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

and the first thing the make directory does is make a build directory.

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

Is it possible to direct the makefile to chdir into _build to simplify my rules?

I want to be able to write (for example)

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

rather than

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

I know I can add the build directory to the VPATH in order to affect path resolution, but it seems cleaner to just chdir Make itself. Is there a way to do this (preferably without using guile)?

2

There are 2 best solutions below

0
On BEST ANSWER

You can make a simple Makefile that forwards everything:

.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:
0
On

GNU Make is not capable of doing this, but NetBSD's bmake can do exactly this.

Suppose we have a project with the following structure:

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

foo.c is a simple C program that depends only on the standard library.

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

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

The makefile uses the common subset of GNU Make and bmake. In general, sticking to the common subset is tedious and not worth doing, this is just for the sake of example.

default: foo

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

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

Running bmake produces the following output

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

and produces the following directory structure

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

It's clear from inspecting the output that bmake almost immediately chdired into the obj directory. Paths to outputs in the obj directory are relative and paths inside the source directory are absolute.