Last active
January 15, 2020 02:35
-
-
Save alekfrohlich/0a48d5f1a4f06646256e9829701a67da to your computer and use it in GitHub Desktop.
Example Makefile and Makedefs. Features automatic dependency generation and builds out-of-source. The Makefile was written to accommodate C++ source code but it should be easy to adapt it to other compiled languages.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Application. | |
APP_NAME := main | |
# Directories. | |
ROOT := $(abspath $(dir $(filter %Makedefs, $(MAKEFILE_LIST)))) | |
SRC := $(ROOT)/src | |
INCLUDE := $(ROOT)/include | |
BUILD := $(ROOT)/build | |
# C++ Compiler and Flags. | |
CXX := g++ | |
CXXFLAGS := -std=c++17 -I $(INCLUDE) | |
# Every rule that is not debug shall be compiled with release flags. | |
ifeq (, $(filter debug, $(MAKECMDGOALS))) | |
APP := $(APP_NAME).release | |
BUILD := $(ROOT)/build/release | |
CXXFLAGS += -O2 | |
else | |
APP := $(APP_NAME).debug | |
BUILD := $(ROOT)/build/debug | |
CXXFLAGS += -g | |
endif | |
# Source and Build Directory Trees. | |
SRC_DIR_TREE := $(shell find $(SRC) -type d) | |
BUILD_DIR_TREE := $(subst $(SRC),$(BUILD),$(SRC_DIR_TREE)) | |
# VPATH is similar to bash's PATH in that it allows make to find files | |
# in other directories without having to change directory. GCC does not | |
# know that, so we include the VPATH'ed source files. | |
INCLUDES := $(foreach dir, $(SRC_DIR_TREE), $(addprefix -I, $(dir))) | |
VPATH := $(SRC_DIR_TREE) | |
# C++ Source Code. | |
CXX_SRC := $(foreach dir,$(SRC_DIR_TREE),$(wildcard $(dir)/*.cc)) | |
# Object Files and Dependencies. | |
OBJS := $(subst $(SRC),$(BUILD),$(CXX_SRC:.cc=.o)) | |
DEPS := $(OBJS:.o=.d) | |
# Rules That do Not Depend on Source Files. | |
OTHER_RULES := clean veryclean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example Makefile | |
SHELL := /bin/bash | |
include Makedefs.mk | |
.PHONY: release debug clean directories veryclean | |
# Build options: [release|debug] | |
__common: | |
$(MAKE) directories | |
$(MAKE) $(APP) | |
release: __common | |
debug: __common | |
$(APP): $(OBJS) | |
$(CXX) $< -o $@ | |
directories: | |
mkdir -p $(BUILD_DIR_TREE) | |
# Function to generate Makefile rules for the given source code. Double dollar | |
# sign ($$) provides double expansion so that CXXFLAGS and INCLUDES are not | |
# evaluated when calling generate-rules. This allows variables to be evaluated | |
# only when the target's recipe is run. | |
define generate-rules | |
$(1)/%.o: %.cc | |
$(CXX) $$(CXXFLAGS) -c $$(INCLUDES) -o $$@ $$< -MMD | |
endef | |
# Generate rules for each build directory. | |
$(foreach targetdir, $(BUILD_DIR_TREE), \ | |
$(eval $(call generate-rules, $(targetdir)))) | |
# Avoid including dependencies when they're not needed. | |
ifeq (, $(filter $(OTHER_RULES),$(MAKECMDGOALS))) | |
-include $(DEPS) | |
endif | |
# Clean binary, object files and dependencies. | |
clean: | |
@find . -depth -type f \( -name "*.o" -o -name "*.d" \) -delete | |
@rm -f $(APP_NAME).release | |
# Also deletes build directory. | |
veryclean: clean | |
@rm -rf $(BUILD) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment