123
votes

My project directory looks like this:

/project
    Makefile
    main
    /src
        main.cpp
        foo.cpp
        foo.h
        bar.cpp
        bar.h
    /obj
        main.o
        foo.o
        bar.o

What I would like my makefile to do would be to compile all .cpp files in the /src folder to .o files in the /obj folder, then link all the .o files in /obj into the output binary in the top-level folder /project.

I have next to no experience with Makefiles, and am not really sure what to search for to accomplish this.

Also, is this a "good" way to do this, or is there a more standard approach to what I'm trying to do?

2
@aaa: I'm guessing the OP wants a solution that doesn't require explicitly listing each source file.Cascabel
I don't want to specify each source file I have, and I've tried to read that manual before, but I find it disorganized and hard to understand. I learn much better from an actual example that does what I expect it does and is well explained, rather than dry technical manuals.Austin Hyde
okay. But make documentation is excellent with good examples (it is not try technical manual). you are looking for pattern rules: gnu.org/software/make/manual/make.html#Pattern-RulesAnycorn
That looks a little more like what I want. Though, IMHO, the make manual is a little dry, as it seems more targeted to developers who are at an intermediate level with make, and beyond that is very large and in-depth. Perhaps too much so.Austin Hyde

2 Answers

194
votes

Makefile part of the question

This is pretty easy, unless you don't need to generalize try something like the code below (but replace space indentation with tabs near g++)

SRC_DIR := .../src
OBJ_DIR := .../obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...

main.exe: $(OBJ_FILES)
   g++ $(LDFLAGS) -o $@ $^

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
   g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

Automatic dependency graph generation

A "must" feature for most make systems. With GCC in can be done in a single pass as a side effect of the compilation by adding -MMD flag to CXXFLAGS and -include $(OBJ_FILES:.o=.d) to the end of the makefile body:

CXXFLAGS += -MMD
-include $(OBJ_FILES:.o=.d)

And as guys mentioned already, always have GNU Make Manual around, it is very helpful.

6
votes

Wildcard works for me also, but I'd like to give a side note for those using directory variables. Always use slash for folder tree (not backslash), otherwise it will fail:

BASEDIR = ../..
SRCDIR = $(BASEDIR)/src
INSTALLDIR = $(BASEDIR)/lib

MODULES = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(wildcard *.o)