0
votes

I am setting up a makefile for a small project and am trying to get it to build all the object and binary files to a single output folder. There seems to be an issue when trying to compile cpp files from anywhere other than the folder containing the make file.

Currently I have the following files:

main.cpp

HelloWorld.cpp

Logger/Logger.cpp

And this is the debug build rule from my makefile:

#
# Debug rule
#
debug: $(DEBUG_BINARY)

$(DEBUG_BINARY): $(DEBUG_OBJ_FILES)
    $(CXX) $(CFLAGS) $(DEBUG_CFLAGS) -o $(DEBUG_BINARY) $^

$(DEBUG_BUILD_DIR)/%.o: %.cpp
    $(CXX) -c $(CFLAGS) $(DEBUG_CFLAGS) -o $@ $<

I am attempting to compile to the following folder:

build/debug/

But this is the output I get:

g++ -c -I. -DDEBUG -g -o build/debug/HelloWorld.o HelloWorld.cpp

g++ -c -I. -DDEBUG -g -o build/debug/main.o main.cpp

make: *** No rule to make target 'build/debug/Logger.o', needed by 'build/debug/MyApp'. Stop.

Edit:

If I explicitly add a rule for the Logger.cpp file it compiles fine, presumably because the last line using the % pattern matching symbol only creates build rules for all the cpp files in the current directory so how can I modify that rule to include all sub directories?

Here are the most notable variables I have:

SRC_FILES       =   $(wildcard *.cpp) \
                    $(wildcard Logger/*.cpp)
OBJ_FILES       = $(SRC_FILES:.cpp=.o)
DEP_FILES       = $(OBJ_FILES:.o=.d)

DEBUG_BUILD_DIR = $(BUILD_PREFIX)/debug
DEBUG_BINARY    = $(DEBUG_BUILD_DIR)/$(BINARY_NAME)
DEBUG_CFLAGS    = -DDEBUG -g
DEBUG_OBJ_FILES = $(addprefix $(DEBUG_BUILD_DIR)/, $(notdir $(OBJ_FILES)))

The last line (DEBUG_OBJ_FILES) transforms each cpp file path to the output folder (e.g. Logger/Logger.cpp becomes build/debug/Logger.o)

1
You're missing a critical piece of information from your question: how is the variable DEBUG_OBJ_FILES set? Without knowing that we can't help more.MadScientist
Thanks. I have modified accordingly.aatwo

1 Answers

2
votes

So in your makefile you're setting DEBUG_OBJ_FILES to the list of files without any path. So, your source files would be main.cpp and Logger/Logger.cpp, and your object files are build/debug/main.o and build/debug/Logger.o.

Your pattern rule is this:

$(DEBUG_BUILD_DIR)/%.o : %.cpp

So when make wants to build build/debug/Logger.o, what will the pattern % match? It matches Logger. So you've defined a rule that could build build/debug/Logger.o from Logger.cpp, but you don't have a Logger.cpp in your codebase, you only have a Logger/Logger.cpp. But make doesn't know how to build from that.

One option would be to define a new pattern rule for that:

$(DEBUG_BUILD_DIR)/%.o : Logger/%.cpp
        ...

And again for each subdirectory. This will work.

Another option is to use GNU make's VPATH facility to give make a list of paths to search for source files:

VPATH := Logger

(it always looks in the current directory first by default).