Skip to content

Instantly share code, notes, and snippets.

@zobayer1
Last active May 24, 2024 08:53
Show Gist options
  • Save zobayer1/7265c698d1b024bb7723bc624aeedeb3 to your computer and use it in GitHub Desktop.
Save zobayer1/7265c698d1b024bb7723bc624aeedeb3 to your computer and use it in GitHub Desktop.
Generic Makefile for C++ projects with multiple cpp and h files
# Pre-compiler and Compiler flags
CXX_FLAGS := -Wall -Wextra -std=c++17 -ggdb
PRE_FLAGS := -MMD -MP
# Project directory structure
BIN := bin
SRC := src
LIB := lib
INC := include
MAINFILE := $(SRC)/main.cpp
# Build directories and output
TARGET := $(BIN)/main
BUILD := build
# Library search directories and flags
EXT_LIB :=
LDFLAGS :=
LDPATHS := $(addprefix -L,$(LIB) $(EXT_LIB))
# Include directories
INC_DIRS := $(INC) $(shell find $(SRC) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# Construct build output and dependency filenames
SRCS := $(shell find $(SRC) -name *.cpp)
OBJS := $(subst $(SRC)/,$(BUILD)/,$(addsuffix .o,$(basename $(SRCS))))
DEPS := $(OBJS:.o=.d)
# Run task
run: build
@echo "πŸš€ Executing..."
./$(TARGET) $(ARGS)
# Build task
build: clean all
# Main task
all: $(TARGET)
# Task producing target from built files
$(TARGET): $(OBJS)
@echo "🚧 Building..."
mkdir -p $(dir $@)
$(CXX) $(OBJS) -o $@ $(LDPATHS) $(LDFLAGS)
# Compile all cpp files
$(BUILD)/%.o: $(SRC)/%.cpp
mkdir -p $(dir $@)
$(CXX) $(CXX_FLAGS) $(PRE_FLAGS) $(INC_FLAGS) -c -o $@ $< $(LDPATHS) $(LDFLAGS)
# Clean task
.PHONY: clean
clean:
@echo "🧹 Clearing..."
rm -rf build
# Include all dependencies
-include $(DEPS)
@zobayer1
Copy link
Author

zobayer1 commented Jul 17, 2020

OS: Linux, GNU Make 4.2.1

Project Structure

Assuming standard C++ project structure,

.
β”œβ”€β”€ bin
β”‚   └── main
β”œβ”€β”€ data
β”‚   └── problem.in
β”œβ”€β”€ include
β”œβ”€β”€ lib
β”œβ”€β”€ Makefile
└── src
    β”œβ”€β”€ main.cpp
    └── nonogram
        β”œβ”€β”€ nonogram.cpp
        └── nonogram.h

Makefile

Makefile will compile all cpp sources, and generate dependency files. So there is no need to worry about including header files. All output and dependency files will be generated into build directory before making target in bin directory.

Makefile declares common tasks such as all, build, run and clean. Command line parameters can be passed with $ARGS variable which run task can make use of when executing the main target.

Tree After Make

.
β”œβ”€β”€ bin
β”‚   └── main
β”œβ”€β”€ build
β”‚   β”œβ”€β”€ main.d
β”‚   β”œβ”€β”€ main.o
β”‚   └── nonogram
β”‚       β”œβ”€β”€ nonogram.d
β”‚       └── nonogram.o
β”œβ”€β”€ data
β”‚   └── problem.in
β”œβ”€β”€ include
β”œβ”€β”€ lib
β”œβ”€β”€ Makefile
└── src
    β”œβ”€β”€ main.cpp
    └── nonogram
        β”œβ”€β”€ nonogram.cpp
        └── nonogram.h

Note

When copying, make sure indentations are actually TAB characters, otherwise make won't be happy.

@david-gettins
Copy link

david-gettins commented May 16, 2024

Firstly, thank you for this, it is excellent!

For Apple framework inclusion I added: FWFLAGS := -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework CoreServices and appended it to # Task producing target from built files.

I had to remove $(LDPATHS) $(LDFLAGS) from the # Compile all cpp files stage as I got warnings about unused flags. Is this normal?

@zobayer1
Copy link
Author

Firstly, thank you for this, it is excellent!

For Apple framework inclusion I added: FWFLAGS := -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework CoreServices and appended it to # Task producing target from built files.

I had to remove $(LDPATHS) $(LDFLAGS) from the # Compile all cpp files stage as I got warnings about unused flags. Is this normal?

Did you need to remove both or may be just LDPATHS. Are they empty? They are set in the # Library search directories and flags section.

@david-gettins
Copy link

Firstly, thank you for this, it is excellent!
For Apple framework inclusion I added: FWFLAGS := -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework CoreServices and appended it to # Task producing target from built files.
I had to remove $(LDPATHS) $(LDFLAGS) from the # Compile all cpp files stage as I got warnings about unused flags. Is this normal?

Did you need to remove both or may be just LDPATHS. Are they empty? They are set in the # Library search directories and flags section.

I had to remove both from the # Compile all cpp files section. I do have them set to something. But it seems those flags were only used in # Task producing target from built files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment