0

Using the simple scenario of a folder structure with a project folder where in this root there is a build and a sources folder:

project
- build
- sources

In the sources folder there is hello.cpp:

#include <iostream>

using namespace std;

int main() {
  cout << "Hello world!\n";
}

and a Makefile:

SOURCE_DIRECTORIES = ../ch1

vpath %.cpp $(SOURCE_DIRECTORIES)

hello: hello.cpp
    g++ ${SOURCE_DIRECTORIES}/hello.cpp -o hello

I run like this from build folder:

make -f ../sources/Makefile

The above works but the vpath isn't so useful. Even with vpath I have to add the SOURCE_DIRECTORIES path the the command line. I might as well not use vpath and just use $(SOURCE_DIRECTORIES) where required.

It is also a little brittle in that the build folder has to be at the same level as the sources folder. But I can live with that.

Is this the best approach? I am thinking there must be a better way to do this.

Lesmana
  • 25,663
  • 9
  • 82
  • 87
Angus Comber
  • 9,316
  • 14
  • 59
  • 107

1 Answers1

1

You don't need to use vpath, here's a way to have the makefile in your sources directory and let it use a BUILD variable with the build directory in question:

-include makefile.in # optionally read in config file

BUILD ?= build # or some other default...

$(BUILD)/hello: $(BUILD)/hello.o
    $(CXX) -o $@ $<

$(BUILD)/%.o: %.cpp
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<

This way, the default is to output everything in src/build (hence, no real out-of-source-build), but you can simply change that behavior with a makefile.in "configuration" file, which could simply be

BUILD = ../build

This is sufficient as in the makefile, BUILD ?= makes sure the variable is only set to the right hand side if it's not defined yet.

lubgr
  • 37,368
  • 3
  • 66
  • 117
  • I am having problems running this. I have created makefile.in in source folder. Tried running from build folder but then get makefile.in: no such file or directory – Angus Comber Nov 11 '19 at 10:24
  • I see... this is setup to be invoked from the source directory. Does that work? Also note that the `-` in front of the `include` is essential to make the existence of `makefile.in` optional. – lubgr Nov 11 '19 at 10:29
  • It works from source folder - good.. However, with no makefile.in get make: *** No rule to make target '%.cpp', needed by 'build'. Stop. – Angus Comber Nov 11 '19 at 10:39
  • The issue is that the default build directory doesn't exist. If no `makefile.in` is found, `BUILD` is initialized to `build`, hence the `makefile` assumes an existing directory called `build` in the sources directory. If you create that one, it should work. You can also change the default `BUILD` to something like `BUILD ?= ../build`. – lubgr Nov 11 '19 at 10:47
  • Hm... are you using GNU make? Maybe something in this makefile is specific to the GNU implementation of `make`?! – lubgr Nov 11 '19 at 10:55
  • yes using gnu make on ubuntu. Its ok, I can investigate, but running from source does what I want – Angus Comber Nov 11 '19 at 11:00