Greg Nisbet
Greg Nisbet

Reputation: 6994

GNU Make: chdir make process itself

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)?

Upvotes: 1

Views: 283

Answers (2)

Greg Nisbet
Greg Nisbet

Reputation: 6994

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.

Upvotes: 0

o11c
o11c

Reputation: 16046

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:

Upvotes: 1

Related Questions