Leif Andersen
Leif Andersen

Reputation: 22342

Automatically make files with Gnu Make utility with different build structure than source

I've seen the following technique used to automatically compile all of the C (or C++, or I suppose whatever extension you wanted) files in a particular directory.

SOURCE_DIRS = .
SOURCES := $(subst ./,,$(wildcard $(SOURCE_DIRS:=/*.cpp)))
HEADERS := $(subst ./,,$(wildcard $(SOURCE_DIRS:=/*.h)))
OBJECTS := $(addprefix build/,$(SOURCES:.cpp=.o))
CXX = g++
CXXFLAGS = -Wall -pedantic -g
#LDFLAGS = 

all: build/exe_name

build/exe_name: $(OBJECTS)
        $(CXX) -o $@ $(OBJECTS) $(LDFLAGS)

build/%.o: %.cpp $(HEADERS) Makefile
        mkdir -p $(dir $@)
        $(CXX) -o $@ $(CXXFLAGS) -c $<

The only problem is that it builds all of the files in the same structure as is in the source directory. So if you had a sub folder with code in it, than the build would have a matching sub folder.

So, how can I modify this (or what else can be done), to get all of the outputted targets to be placed directly in the build/ directory, rather than in a hierarchy that matches the source directory?

I've thought about trying to strip any directories that may be presented in the '%' when it's used in the target, but I can't find any good commands to do that. Also, it seems a bit problematic to try to change the OBJECTS path when created, as I have no idea how the '%' variable reads it, other than that it is magically compiling everything in the OBJECTS list.

Thank you for any help you can give.

Upvotes: 2

Views: 295

Answers (2)

Jack Kelly
Jack Kelly

Reputation: 18667

The easiest (although not strictly make-only) way would be to use automake and not set the subdir-options option.

Upvotes: 0

Beta
Beta

Reputation: 99172

In order,

  1. I don't see how this can work as it is. Your wildcard method will not recurse into subfolders of the source folder, and your %.o rule will not work in any case other than `SOURCE_DIRS=.`.
  2. Your %.o rule is kind of loose. If you change one header, Make will rebuild all object files.
  3. Incorporating every source that can be found into your executable is probably not wise. In this scheme it is difficult to have more than one executable with shared code.
  4. To overcome the problems of 1) and write a makefile I could test, I would have to mess with "find", which I hate, so the following is untested.
  5. I think this will do it (in GNUMake):
SOURCES := whatever...
vpath %.cpp $(dir $(SOURCES))
SOURCES := $(notdir $(SOURCES))

Upvotes: 3

Related Questions