Skip to content

Instantly share code, notes, and snippets.

@charmoniumQ
Created April 28, 2019 02:12
Show Gist options
  • Save charmoniumQ/a2b2df12caa767ca79f028f00069996a to your computer and use it in GitHub Desktop.
Save charmoniumQ/a2b2df12caa767ca79f028f00069996a to your computer and use it in GitHub Desktop.
Epic makefile that automatically detects dependencies and only recompiles when one of them changes
# Project-specific
# location to create for binaries
BUILD_DIR := build
# location of source code
SOURCE_DIR := source
# name of main executable in $(SOURCE_DIR) without .c
EXECUTABLE := main
# Space-separated pkg-config libraries used by this project
LIBS := gmp gmpxx
# source ext. Some people use .cxx, .cc, .cpp
SOURCE_EXT := cpp
DEBUG := t
# Flags
ifeq ($(DEBUG),t)
CXXOPTIMIZATION := -Og
CXXDEBUG := -g -fsanitize=address
CXXWARNINGS := #-Wall -Wextra #-Werror
else
CXXOPTIMIZATION := -O3
CXXDEBUG :=
CXXWARNINGS := #-Wall
CXXFLAGS += -DNDEBUG
endif
CXXVERSION := -std=c++11
CXXLIBS := $(if $(LIBS),$(shell pkg-config --cflags $(LIBS)))
CXXFLAGS += $(CXXDEBUG) $(CXXVERSION) $(CXXWARNINGS) $(CXXOPTIMIZATION) $(CXXVERSION) $(CXXLIBS)
LDLIBS := $(if $(LIBS),$(shell pkg-config --libs $(LIBS)))
LDFLAGS += $(LDLIBS) $(CXXDEBUG) -lstdc++
# sane env
SHELL := /bin/sh
MKDIR := mkdir
# `find` recurses into subdirectories to get all your source files
SOURCE_FILES := $(shell find $(SOURCE_DIR)/ -name '*'.$(SOURCE_EXT))
# rename them to .o for the object files and put them in build/
OBJECT_FILES := $(patsubst $(SOURCE_DIR)/%.$(SOURCE_EXT),$(BUILD_DIR)/%.o,$(SOURCE_FILES))
# DEPENDENCY_FILES will be for dependnecy mapping
DEPENDENCY_FILES := $(patsubst $(SOURCE_DIR)/%.$(SOURCE_EXT),$(BUILD_DIR)/%.d,$(SOURCE_FILES))
# See GCC's -M option.
# The compiler will parse the file, but not compile.
# It looks for the included files and writes a Make rule.
# This way, I know that if included_file.h changes, we need to recompile file.o
# file.o: included_file.h included_file2.h file.cc
$(BUILD_DIR)/%.d: $(SOURCE_DIR)/%.$(SOURCE_EXT)
$(MKDIR) -p $$(dirname $@) && \
$(CXX) -MT $(BUILD_DIR)/$*.o -MM $< > $@
-include $(DEPENDENCY_FILES)
# Compile object files
# This way big projects don't have to recompile every file; only what changed
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.$(SOURCE_EXT)
@$(START_TIME)
$(CXX) -c $(CXXFLAGS) $< -o $@
@$(END_TIME)
# Link executable from object files
$(BUILD_DIR)/$(EXECUTABLE): $(OBJECT_FILES)
$(CXX) $(LDFLAGS) $^ -o $@
all: $(BUILD_DIR)/$(EXECUTABLE)
run: $(BUILD_DIR)/$(EXECUTABLE)
./$(BUILD_DIR)/$(EXECUTABLE)
clean:
$(RM) -rf $(BUILD_DIR)/
.PHONY: clean all run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment