A clean, lightweight, and cross-platform Makefile for C++ projects.
Supports Windows (MinGW-w64/MSYS2), Linux, and macOS with minimal configuration.
Designed to be simple, readable, and easy to extend, ideal for game engines, tools, small-to-medium applications, learning projects, or as a starting point.
- β Cross-Platform: Windows, Linux, macOS with automatic detection
- β Build Types: Multiple configurations (release, debug, relwithdebinfo, analyze) with proper optimization levels
- β
Architecture Optimization: Architecture-specific optimization via
ARCHvariable (native, skylake, znver4, armv8-a, etc.) - β
Link-Time Optimization (LTO): Control LTO with
USE_LTOflag (disabled by default in release builds) - β
Static Analysis: Built-in
make analyzetarget for static code analysis - β
Dependency Tracking: Automatic
.dfile generation - β
Assembly Output: Generate assembly files (
make asm) and disassembly (make disassemble) - β Parallel Builds: Multi-core compilation support with automatic verbosity reduction
- β Sanitizers: AddressSanitizer and UndefinedBehaviorSanitizer support in debug builds (Linux/macOS)
- β Improved UI: Better build output with status indicators and build type information
- β Two Templates: Basic (simple) and Advanced (feature-rich)
In the root directory is a main Makefile for building three complete examples:
- Spinning ASCII Donut: A terminal-based 3D donut animation (in
examples/donut-basic/) - ImGui + GLFW Demo: A graphical window using ImGui and GLFW (in
examples/ImGui/) - Task Manager CLI: An advanced command-line task management system with JSON persistence (in
examples/task-manager/)
git clone https://github.com/DMsuDev/Basic-Makefile-Template.git
cd Basic-Makefile-Template# Option 1: View the spinning ASCII donut (terminal animation)
make run-donut
# Option 2: Open the ImGui window (graphical demo with GLFW)
make run-imgui
# Option 3: Run the task manager CLI example
make run-tm
# Option 4: Build all examples
make all
# Option 5: See available examples
make list
# Option 6: Get help
make helpNote: To run the ImGui example, copy the required glfw3.dll from the lib/ folder to the build/app/ directory after building.
For help: Type make help in the terminal to see all available commands.
project/
βββ build/
β βββ app/ β Executables
β βββ obj/ β Object files (.o)
β βββ dep/ β Dependency files (.d)
β βββ asm/ β Assembly files (.s) and disassembly
βββ src/Note: In v1.0.2 and earlier, executables were in
build/bin/. Update scripts if needed.
| Command | Description | When to use |
|---|---|---|
make |
Release build (default target) | Everyday development |
make release |
Explicit Release build with optimizations | Final/performance builds |
make debug |
Debug build + symbols + sanitizers | Bug hunting, ASan/UBSan |
make relwithdebinfo |
Release with debug info (best of both) | Profiling with symbol debugging |
make analyze |
Static analysis build | Code quality checks |
make run |
Release build + execute binary | Quick testing |
make run-debug |
Debug build + execute binary | Debugging sessions |
make asm |
Generate Intel-syntax .s assembly files |
Inspecting compiler output |
make disassemble |
Disassemble final binary (objdump) | Optimization / reverse engineering |
make clean |
Remove objects, deps, asm, binary | Fresh start for current config |
make clean-all |
Delete entire ./build/ directory |
Changing compiler or major flags |
make help |
Show help message | Quick reference |
make info |
Show project configuration summary | Verify paths, compiler, sources count |
The Makefile fully supports parallel compilation to use multiple CPU cores and dramatically reduce build times on modern machines.
# Use all available cores (recommended)
make -j$(nproc) run # Linux/WSL/macOS
make -j8 run # Windows or fixed number (adjust to your CPU)
# Example: build with 8 cores (rule `all` by default)
make -j8
# Or with run
make run -j12-
Automatic behavior: When you use
-j(parallel mode), the Makefile automatically reduces verbosity to avoid chaotic interleaved output.- No fancy colors or status icon per file
- Only essential messages and errors are shown
- This prevents the terminal from becoming a mess when compiling dozens/hundreds of files at once.
-
Note: Start with
-j4or-j8and increase until you find the sweet spot for your machine (too high can cause memory thrashing if RAM is limited). -
On linux: The verbose mode not deactivates automatically, so you can use
-sto reduce output if needed.
These variables control the behavior of the project and can be overridden directly from the command line:
| Variable | Description | Default |
|---|---|---|
| APP_NAME | Output executable name (no extension) | ProjectName |
| SRC_EXT | Source file extension | cpp |
| CXX_STD | C/C++ standard | c++23 |
| CXX | Compiler to use | g++ |
| USE_CONSOLE | Show console window on Windows | true |
| BUILD_TYPE | Build variant (release/debug/relwithdebinfo) | release |
| USE_LTO | Enable Link-Time Optimization | false |
| ANALYZE | Enable static analysis flags | false |
| ARCH | Target architecture (-march=) |
native |
| WARN_LEVEL | Warning strictness (minimal/normal/strict) | minimal |
| LIBS | Libraries to link (-l) |
|
| LDFLAGS | Library search paths (-L) |
-L./lib/ |
| SOURCE_DIRS | Source directories | src include |
| INCLUDE_DIRS | Include directories | include |
| OPT_RELEASE | Optimization flags (Release) | -O3 |
| OPT_DEBUG | Optimization flags (Debug) | -Og |
# Change app name
make APP_NAME=MyApp
# Use Clang++ and C++20 instead of G++ and C++23 (default values)
make CXX=clang++ CXX_STD=c++20
# Build without console window on Windows
make release USE_CONSOLE=false
# Optimize for specific CPU architecture
make release ARCH=znver4 # AMD Zen 4
make release ARCH=skylake # Intel 6thβ9th gen
make release ARCH=armv8-a # ARM (requires cross-compiler)
# Build with debug symbols and optimizations (best for profiling)
make relwithdebinfo
# Build with static analysis enabled
make ANALYZE=true release
# Debug build with all sanitizers and verbose output
make debug VERBOSE=1
# Release build without Link-Time Optimization (faster linking)
make release USE_LTO=false
# Compiler-aware LTO (automatic: thin for Clang, auto for GCC)
make release CXX=clang++ # Uses -flto=thin (optimized for Clang)
make release CXX=g++ # Uses -flto=auto (optimized for GCC)
# Parallel build with 8 cores (release configuration)
make -j8 releaseThe Makefile automatically selects the best LTO variant based on your compiler:
| Compiler | LTO Type | Benefit |
|---|---|---|
| Clang/clang++ | -flto=thin |
Faster compilation, good optimization |
| GCC/g++ | -flto=auto |
Best optimization, slower linking |
| Disabled | (none) | Fastest build time |
# Enable LTO (default in release builds)
make release USE_LTO=true CXX=clang++ # Automatically uses thin LTO
# Disable LTO if linking is too slow
make release USE_LTO=falseControl compiler warning strictness with the WARN_LEVEL variable. Perfect for managing warnings in different project phases or integrating with CI/CD pipelines.
| Level | Flags | Use Case |
|---|---|---|
| minimal | Base warnings only (-Wall -Wextra -pedantic-errors) |
Legacy code, third-party libraries |
| normal | + Type conversion, logic, and safety checks | Standard development (recommended) |
| strict | + Code quality warnings (-Wshadow, -Wunused, etc) |
New projects, CI/CD pipelines (default) |
# Production: Strict + Optimization
make release WARN_LEVEL=strict ARCH=native
# Cross-platform: Balanced with specific compiler
make WARN_LEVEL=normal CXX=clang++ -j8minimal:
-Wall -Wextra -pedantic-errorsnormal (minimal +):
-Wconversion -Wsign-conversion -Wdouble-promotion
-Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict
-Wnull-dereference -Wformat=2 -Wunreachable-codestrict (normal +):
-Wshadow -Wunused -Wunused-parameter- Release builds: Warnings become errors (
-Werror) regardless ofWARN_LEVEL - Debug builds: Warnings remain as warnings for easier iteration
# Warnings as errors
make release WARN_LEVEL=minimal
# Warnings only
make debug WARN_LEVEL=strictUncomment/add in the libraries section:
ifeq ($(OS),Windows_NT)
LIBS += -lglfw3dll -lopengl32 -lgdi32
endif
ifeq ($(OS_NAME),Linux)
LIBS += -lglfw -lGL -ldl -lpthread
endif
ifeq ($(OS_NAME),macOS)
LIBS += -lglfw -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
endifMyProject/
βββ src/
β βββ main.cpp
β βββ core/
β β βββ engine.cpp
β βββ renderer/
βββ include/
β βββ myproject/
βββ lib/ # optional: .a, .lib, .dll files
βββ build/
β βββ app/ # final executable
β βββ obj/ # object files
β βββ dep/ # .d dependency files
β βββ asm/ # assembly & disassembly output
βββ Makefile- MSYS2 (recommended): UCRT64 or MINGW64
- Compilers:
g++(MinGWβw64) orclang++
gccorclangmake- Dev packages depending on your project (e.g.,
build-essential,libglfw3-dev,libgl1-mesa-dev)
- Xcode Command Line Tools:
xcode-select --install - Homebrew packages (optional):
brew install gcc clang
objdump(formake disasm)gdborlldb(debugging)pkg-config(optional)
- Linking errors on Linux β Install missing dev packages (e.g., libglfw3-dev on Ubuntu/WSL)
makenot found on Windows β Usemingw32-make(included with MinGW-w64).- No rule to make target β Verify source files exist in
src/(or added folders) - Sanitizers not working on Windows β Disabled by design (partial support in MinGW)
- Double slashes in paths β Usually harmless; caused by empty variables in some shells
- Colors broken in CI β Parallel mode auto-disables fancy output
- Too much output with
-jβ Use-jN-sor redirect to log clearcommand not found (rare) β On some Windows shells, fallback toclshappens automatically
Note: This project has been primarily developed and tested on Windows and Linux/WSL. Support for macOS is not guaranteed and may require adjustments.
If you encounter any issues, platform-specific bugs, or inconsistencies, your feedback is extremely valuable. π
Contributions, issues and feature requests are welcome.
Feel free to check the issues page.
Happy coding! β€οΈ
