Search code examples
c++makefileg++

Makefile setup for custom source/output directories


Goal

Create a makefile that successfully compiles my program with the following constraints (I like a clean project root directory).

  1. Output final binary to root project directory (or possibly a ./bin directory).
  2. Maintain all source files inside ./src directory (*.cpp, *.h)
  3. Makefile should sit inside root project directory
  4. All object files should be output adjacent to their source files inside ./src

What I've tried

Thus far, I've only been able to create a makefile where all object files are output to the root project directory.

CXXFLAGS += -std=c++11
OUTPUT := main

$(OUTPUT): main.o util.o
        $(CXX) $(CXXFLAGS) -o $(OUTPUT) main.o util.o

main.o: main.cpp ./src/util.h
        $(CXX) $(CXXFLAGS) -c main.cpp

util.o: ./src/util.h ./src/util.cpp
        $(CXX) $(CXXFLAGS) -c ./src/util.cpp

Solution

  • You didn't really show us what you tried. You only showed us what worked. If you'd shown us what you tried that DIDN'T work we could explain why. However, this will work:

    CXXFLAGS += -std=c++11
    OUTPUT := main
    
    $(OUTPUT): src/main.o src/util.o
                $(CXX) $(CXXFLAGS) -o $@ $^
    
    src/main.o: src/main.cpp src/util.h
                $(CXX) $(CXXFLAGS) -c -o $@ $<
    
    src/util.o: ./src/util.cpp ./src/util.h
                $(CXX) $(CXXFLAGS) -c -o $@ $<
    

    The key is that make starts from the END (main) and works backwards. So you have to tell it where you want the object files to end up, in the prerequisite list of main.

    But, you don't even have to do all this because GNU Make already knows how to build object files in the same directory as source files. This makefile is good enough:

    CXXFLAGS += -std=c++11
    OUTPUT := main
    
    $(OUTPUT): src/main.o src/util.o
                $(CXX) $(CXXFLAGS) -o $@ $^
    
    src/main.o src/util.o: src/util.h