./configure and make seemingly hard-wired into my fingers, it seems a bit cumbersome to have to type mkdir build, cd build, and (for example) cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON each time you want to build something.
It got me thinking, and I haven’t come across anyone else suggesting it (I’m sure plenty of people have though)… why not drive CMake through a Makefile? Sure you can script it up easily enough, but it seems a bit single-purpose each time I do it, and my fingers are just itching to type `make`.
It seems a weird concept, because of course CMake is, amongst other things, a Makefile generator. But here’s my take on it. I love being able to type
make or make release:
Makefile:
# Usage:
# make -> debug build
# make release -> release build
# make test -> debug build + run tests
# make clean -> remove all build directories and symlink
APP_NAME := <<SET BINARY NAME HERE>>
BUILD_DIR_DEBUG := build/Debug
BUILD_DIR_RELEASE := build/Release
MAKEFLAGS += --no-print-directory
CMAKE := cmake
CMAKE_FLAGS :=
JOBS := $(shell nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)
.PHONY: all debug release test clean
# -----------------------
# Default target -> debug
# -----------------------
all: debug
# -----------
# Debug build
# -----------
debug: $(BUILD_DIR_DEBUG)/Makefile
$(CMAKE) --build $(BUILD_DIR_DEBUG) -- -j$(JOBS)
$(BUILD_DIR_DEBUG)/Makefile:
@mkdir -p $(BUILD_DIR_DEBUG)
$(CMAKE) -S . -B $(BUILD_DIR_DEBUG) -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_BUILD_TYPE=Debug $(CMAKE_FLAGS)
# -------------
# Release build
# -------------
release: $(BUILD_DIR_RELEASE)/Makefile
$(CMAKE) --build $(BUILD_DIR_RELEASE) -- -j$(JOBS)
$(BUILD_DIR_RELEASE)/Makefile:
@mkdir -p $(BUILD_DIR_RELEASE)
$(CMAKE) -S . -B $(BUILD_DIR_RELEASE) -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_BUILD_TYPE=Release $(CMAKE_FLAGS)
# ------------------------
# Test (debug build + run)
# ------------------------
test: $(BUILD_DIR_DEBUG)/Makefile
$(CMAKE) --build $(BUILD_DIR_DEBUG) --target $(APP_NAME)_tests -- -j$(JOBS)
@$(BUILD_DIR_DEBUG)/$(APP_NAME)_tests --reporter console || true
# -----
# Clean
# -----
clean:
@rm -rf build $(APP_NAME)
@echo "-> build directories and symlink removed"
Set APP_NAME to the same as your CMake
add_executable() name. This assumes you have a unit test framework and compiles a test suite in <APP_NAME>_tests (runnable with make test). It also symlinks the normal binary into your main project directory for easy running from the command line. Verbose building is as simple as typing VERBOSE=1 make. Tweak as you see fit.






