Last active
April 5, 2026 12:01
-
-
Save tomdaley92/190c68e8a84038cc91a5459409e007df to your computer and use it in GitHub Desktop.
Generic makefile for C/C++ programs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Thomas Daley | |
| # September 13, 2021 | |
| # A generic build template for C/C++ programs | |
| # executable name | |
| EXE = app | |
| # C compiler | |
| CC = gcc | |
| # C++ compiler | |
| CXX = g++ | |
| # linker | |
| LD = g++ | |
| # C flags | |
| CFLAGS = | |
| # C++ flags | |
| CXXFLAGS = | |
| # C/C++ flags | |
| CPPFLAGS = -Wall | |
| # dependency-generation flags | |
| DEPFLAGS = -MMD -MP | |
| # linker flags | |
| LDFLAGS = | |
| # library flags | |
| LDLIBS = | |
| # build directories | |
| BIN = bin | |
| OBJ = obj | |
| SRC = src | |
| SOURCES := $(wildcard $(SRC)/*.c $(SRC)/*.cc $(SRC)/*.cpp $(SRC)/*.cxx) | |
| OBJECTS := \ | |
| $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(wildcard $(SRC)/*.c)) \ | |
| $(patsubst $(SRC)/%.cc, $(OBJ)/%.o, $(wildcard $(SRC)/*.cc)) \ | |
| $(patsubst $(SRC)/%.cpp, $(OBJ)/%.o, $(wildcard $(SRC)/*.cpp)) \ | |
| $(patsubst $(SRC)/%.cxx, $(OBJ)/%.o, $(wildcard $(SRC)/*.cxx)) | |
| # include compiler-generated dependency rules | |
| DEPENDS := $(OBJECTS:.o=.d) | |
| # compile C source | |
| COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ | |
| # compile C++ source | |
| COMPILE.cxx = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ | |
| # link objects | |
| LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) $(OBJECTS) -o $@ | |
| .DEFAULT_GOAL = all | |
| .PHONY: all | |
| all: $(BIN)/$(EXE) | |
| $(BIN)/$(EXE): $(SRC) $(OBJ) $(BIN) $(OBJECTS) | |
| $(LINK.o) | |
| $(SRC): | |
| mkdir -p $(SRC) | |
| $(OBJ): | |
| mkdir -p $(OBJ) | |
| $(BIN): | |
| mkdir -p $(BIN) | |
| $(OBJ)/%.o: $(SRC)/%.c | |
| $(COMPILE.c) $< | |
| $(OBJ)/%.o: $(SRC)/%.cc | |
| $(COMPILE.cxx) $< | |
| $(OBJ)/%.o: $(SRC)/%.cpp | |
| $(COMPILE.cxx) $< | |
| $(OBJ)/%.o: $(SRC)/%.cxx | |
| $(COMPILE.cxx) $< | |
| # force rebuild | |
| .PHONY: remake | |
| remake: clean $(BIN)/$(EXE) | |
| # execute the program | |
| .PHONY: run | |
| run: $(BIN)/$(EXE) | |
| ./$(BIN)/$(EXE) | |
| # remove previous build and objects | |
| .PHONY: clean | |
| clean: | |
| $(RM) $(OBJECTS) | |
| $(RM) $(DEPENDS) | |
| $(RM) $(BIN)/$(EXE) | |
| # remove everything except source | |
| .PHONY: reset | |
| reset: | |
| $(RM) -r $(OBJ) | |
| $(RM) -r $(BIN) | |
| -include $(DEPENDS) |
Author
Great little cheat sheet you made here; thanks for sharing it. 👍 🍻
I have a couple questions, just out of curiosity, mostly.
- What's the thought process behind aggregating all of the various source files into the
$(SOURCES)variable? It's not called elsewhere in the file, so is there some sneaky implicit treatment a variable with that name always gets from Make "under the hood"? - In the recipe for
$(BIN)/$(EXE), you have the objects and the three directory variables all present as normal prerequisites. I was told a long time ago that directory instantiation variables like the latter three should generally be assigned as order-only prerequisites, i.e. at the end of the prerequisites list following a vertical bar character (|). Do you agree with that advice, or is there a reason why you prefer to leave them as normal and in front of the compilation objects? It's one of those things I was told to do very early in my career and so have just always done it that way, and now I'm at the point where I'd like to examine such things more deeply and for myself.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
should work with any unix-y platform. tested on darwin and debian.