Skip to content

Instantly share code, notes, and snippets.

@tomdaley92
Last active April 5, 2026 12:01
Show Gist options
  • Select an option

  • Save tomdaley92/190c68e8a84038cc91a5459409e007df to your computer and use it in GitHub Desktop.

Select an option

Save tomdaley92/190c68e8a84038cc91a5459409e007df to your computer and use it in GitHub Desktop.
Generic makefile for C/C++ programs
# 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)
@tomdaley92
Copy link
Copy Markdown
Author

should work with any unix-y platform. tested on darwin and debian.

@RogueScholar
Copy link
Copy Markdown

RogueScholar commented Apr 5, 2026

Great little cheat sheet you made here; thanks for sharing it. 👍 🍻

I have a couple questions, just out of curiosity, mostly.

  1. 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"?
  2. 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