|
| 1 | +#### PROJECT SETTINGS #### |
| 2 | +# The name of the executable to be created |
| 3 | +BIN_NAME := terminalquest |
| 4 | +# Compiler used |
| 5 | +CC ?= gcc |
| 6 | +# Extension of source files used in the project |
| 7 | +SRC_EXT = c |
| 8 | +# Path to the source directory, relative to the makefile |
| 9 | +SRC_PATH = . |
| 10 | +# Space-separated pkg-config libraries used by this project |
| 11 | +LIBS = |
| 12 | +# General compiler flags |
| 13 | +COMPILE_FLAGS = -std=c99 -Wall -Wextra -g |
| 14 | +# Additional release-specific flags |
| 15 | +RCOMPILE_FLAGS = -D NDEBUG |
| 16 | +# Additional debug-specific flags |
| 17 | +DCOMPILE_FLAGS = -D DEBUG |
| 18 | +# Add additional include paths |
| 19 | +INCLUDES = -I $(SRC_PATH) |
| 20 | +# General linker settings |
| 21 | +LINK_FLAGS = |
| 22 | +# Additional release-specific linker settings |
| 23 | +RLINK_FLAGS = |
| 24 | +# Additional debug-specific linker settings |
| 25 | +DLINK_FLAGS = |
| 26 | +# Destination directory, like a jail or mounted system |
| 27 | +DESTDIR = / |
| 28 | +# Install path (bin/ is appended automatically) |
| 29 | +INSTALL_PREFIX = usr/local |
| 30 | +#### END PROJECT SETTINGS #### |
| 31 | + |
| 32 | +# Optionally you may move the section above to a separate config.mk file, and |
| 33 | +# uncomment the line below |
| 34 | +# include config.mk |
| 35 | + |
| 36 | +# Generally should not need to edit below this line |
| 37 | + |
| 38 | +# Obtains the OS type, either 'Darwin' (OS X) or 'Linux' |
| 39 | +UNAME_S:=$(shell uname -s) |
| 40 | + |
| 41 | +# Function used to check variables. Use on the command line: |
| 42 | +# make print-VARNAME |
| 43 | +# Useful for debugging and adding features |
| 44 | +print-%: ; @echo $*=$($*) |
| 45 | + |
| 46 | +# Shell used in this makefile |
| 47 | +# bash is used for 'echo -en' |
| 48 | +SHELL = /bin/bash |
| 49 | +# Clear built-in rules |
| 50 | +.SUFFIXES: |
| 51 | +# Programs for installation |
| 52 | +INSTALL = install |
| 53 | +INSTALL_PROGRAM = $(INSTALL) |
| 54 | +INSTALL_DATA = $(INSTALL) -m 644 |
| 55 | + |
| 56 | +# Append pkg-config specific libraries if need be |
| 57 | +ifneq ($(LIBS),) |
| 58 | + COMPILE_FLAGS += $(shell pkg-config --cflags $(LIBS)) |
| 59 | + LINK_FLAGS += $(shell pkg-config --libs $(LIBS)) |
| 60 | +endif |
| 61 | + |
| 62 | +# Verbose option, to output compile and link commands |
| 63 | +export V := false |
| 64 | +export CMD_PREFIX := @ |
| 65 | +ifeq ($(V),true) |
| 66 | + CMD_PREFIX := |
| 67 | +endif |
| 68 | + |
| 69 | +# Combine compiler and linker flags |
| 70 | +release: export CFLAGS := $(CFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS) |
| 71 | +release: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(RLINK_FLAGS) |
| 72 | +debug: export CFLAGS := $(CFLAGS) $(COMPILE_FLAGS) $(DCOMPILE_FLAGS) |
| 73 | +debug: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(DLINK_FLAGS) |
| 74 | + |
| 75 | +# Build and output paths |
| 76 | +release: export BUILD_PATH := build/release |
| 77 | +release: export BIN_PATH := bin/release |
| 78 | +debug: export BUILD_PATH := build/debug |
| 79 | +debug: export BIN_PATH := bin/debug |
| 80 | +install: export BIN_PATH := bin/release |
| 81 | + |
| 82 | +# Find all source files in the source directory, sorted by most |
| 83 | +# recently modified |
| 84 | +ifeq ($(UNAME_S),Darwin) |
| 85 | + SOURCES = $(shell find $(SRC_PATH) -name '*.$(SRC_EXT)' | sort -k 1nr | cut -f2-) |
| 86 | +else |
| 87 | + SOURCES = $(shell find $(SRC_PATH) -name '*.$(SRC_EXT)' -printf '%T@\t%p\n' \ |
| 88 | + | sort -k 1nr | cut -f2-) |
| 89 | +endif |
| 90 | + |
| 91 | +# fallback in case the above fails |
| 92 | +rwildcard = $(foreach d, $(wildcard $1*), $(call rwildcard,$d/,$2) \ |
| 93 | + $(filter $(subst *,%,$2), $d)) |
| 94 | +ifeq ($(SOURCES),) |
| 95 | + SOURCES := $(call rwildcard, $(SRC_PATH), *.$(SRC_EXT)) |
| 96 | +endif |
| 97 | + |
| 98 | +# Set the object file names, with the source directory stripped |
| 99 | +# from the path, and the build path prepended in its place |
| 100 | +OBJECTS = $(SOURCES:$(SRC_PATH)/%.$(SRC_EXT)=$(BUILD_PATH)/%.o) |
| 101 | +# Set the dependency files that will be used to add header dependencies |
| 102 | +DEPS = $(OBJECTS:.o=.d) |
| 103 | + |
| 104 | +# Macros for timing compilation |
| 105 | +ifeq ($(UNAME_S),Darwin) |
| 106 | + CUR_TIME = awk 'BEGIN{srand(); print srand()}' |
| 107 | + TIME_FILE = $(dir $@).$(notdir $@)_time |
| 108 | + START_TIME = $(CUR_TIME) > $(TIME_FILE) |
| 109 | + END_TIME = read st < $(TIME_FILE) ; \ |
| 110 | + $(RM) $(TIME_FILE) ; \ |
| 111 | + st=$$((`$(CUR_TIME)` - $$st)) ; \ |
| 112 | + echo $$st |
| 113 | +else |
| 114 | + TIME_FILE = $(dir $@).$(notdir $@)_time |
| 115 | + START_TIME = date '+%s' > $(TIME_FILE) |
| 116 | + END_TIME = read st < $(TIME_FILE) ; \ |
| 117 | + $(RM) $(TIME_FILE) ; \ |
| 118 | + st=$$((`date '+%s'` - $$st - 86400)) ; \ |
| 119 | + echo `date -u -d @$$st '+%H:%M:%S'` |
| 120 | +endif |
| 121 | + |
| 122 | +# Version macros |
| 123 | +# Comment/remove this section to remove versioning |
| 124 | +USE_VERSION := false |
| 125 | +# If this isn't a git repo or the repo has no tags, git describe will return non-zero |
| 126 | +ifeq ($(shell git describe > /dev/null 2>&1 ; echo $$?), 0) |
| 127 | + USE_VERSION := true |
| 128 | + VERSION := $(shell git describe --tags --long --dirty --always | \ |
| 129 | + sed 's/v\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)-\?.*-\([0-9]*\)-\(.*\)/\1 \2 \3 \4 \5/g') |
| 130 | + VERSION_MAJOR := $(word 1, $(VERSION)) |
| 131 | + VERSION_MINOR := $(word 2, $(VERSION)) |
| 132 | + VERSION_PATCH := $(word 3, $(VERSION)) |
| 133 | + VERSION_REVISION := $(word 4, $(VERSION)) |
| 134 | + VERSION_HASH := $(word 5, $(VERSION)) |
| 135 | + VERSION_STRING := \ |
| 136 | + "$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH).$(VERSION_REVISION)-$(VERSION_HASH)" |
| 137 | + override CFLAGS := $(CFLAGS) \ |
| 138 | + -D VERSION_MAJOR=$(VERSION_MAJOR) \ |
| 139 | + -D VERSION_MINOR=$(VERSION_MINOR) \ |
| 140 | + -D VERSION_PATCH=$(VERSION_PATCH) \ |
| 141 | + -D VERSION_REVISION=$(VERSION_REVISION) \ |
| 142 | + -D VERSION_HASH=\"$(VERSION_HASH)\" |
| 143 | +endif |
| 144 | + |
| 145 | +# Standard, non-optimized release build |
| 146 | +.PHONY: release |
| 147 | +release: dirs |
| 148 | +ifeq ($(USE_VERSION), true) |
| 149 | + @echo "Beginning release build v$(VERSION_STRING)" |
| 150 | +else |
| 151 | + @echo "Beginning release build" |
| 152 | +endif |
| 153 | + @$(START_TIME) |
| 154 | + @$(MAKE) all --no-print-directory |
| 155 | + @echo -n "Total build time: " |
| 156 | + @$(END_TIME) |
| 157 | + |
| 158 | +# Debug build for gdb debugging |
| 159 | +.PHONY: debug |
| 160 | +debug: dirs |
| 161 | +ifeq ($(USE_VERSION), true) |
| 162 | + @echo "Beginning debug build v$(VERSION_STRING)" |
| 163 | +else |
| 164 | + @echo "Beginning debug build" |
| 165 | +endif |
| 166 | + @$(START_TIME) |
| 167 | + @$(MAKE) all --no-print-directory |
| 168 | + @echo -n "Total build time: " |
| 169 | + @$(END_TIME) |
| 170 | + |
| 171 | +# Create the directories used in the build |
| 172 | +.PHONY: dirs |
| 173 | +dirs: |
| 174 | + @echo "Creating directories" |
| 175 | + @mkdir -p $(dir $(OBJECTS)) |
| 176 | + @mkdir -p $(BIN_PATH) |
| 177 | + |
| 178 | +# Installs to the set path |
| 179 | +.PHONY: install |
| 180 | +install: |
| 181 | + @echo "Installing to $(DESTDIR)$(INSTALL_PREFIX)/bin" |
| 182 | + @$(INSTALL_PROGRAM) $(BIN_PATH)/$(BIN_NAME) $(DESTDIR)$(INSTALL_PREFIX)/bin |
| 183 | + |
| 184 | +# Uninstalls the program |
| 185 | +.PHONY: uninstall |
| 186 | +uninstall: |
| 187 | + @echo "Removing $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BIN_NAME)" |
| 188 | + @$(RM) $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BIN_NAME) |
| 189 | + |
| 190 | +# Removes all build files |
| 191 | +.PHONY: clean |
| 192 | +clean: |
| 193 | + @echo "Deleting $(BIN_NAME) symlink" |
| 194 | + @$(RM) $(BIN_NAME) |
| 195 | + @echo "Deleting directories" |
| 196 | + @$(RM) -r build |
| 197 | + @$(RM) -r bin |
| 198 | + |
| 199 | +# Main rule, checks the executable and symlinks to the output |
| 200 | +all: $(BIN_PATH)/$(BIN_NAME) |
| 201 | + @echo "Making symlink: $(BIN_NAME) -> $<" |
| 202 | + @$(RM) $(BIN_NAME) |
| 203 | + @ln -s $(BIN_PATH)/$(BIN_NAME) $(BIN_NAME) |
| 204 | + |
| 205 | +# Link the executable |
| 206 | +$(BIN_PATH)/$(BIN_NAME): $(OBJECTS) |
| 207 | + @echo "Linking: $@" |
| 208 | + @$(START_TIME) |
| 209 | + $(CMD_PREFIX)$(CC) $(OBJECTS) $(LDFLAGS) -o $@ |
| 210 | + @echo -en "\t Link time: " |
| 211 | + @$(END_TIME) |
| 212 | + |
| 213 | +# Add dependency files, if they exist |
| 214 | +-include $(DEPS) |
| 215 | + |
| 216 | +# Source file rules |
| 217 | +# After the first compilation they will be joined with the rules from the |
| 218 | +# dependency files to provide header dependencies |
| 219 | +$(BUILD_PATH)/%.o: $(SRC_PATH)/%.$(SRC_EXT) |
| 220 | + @echo "Compiling: $< -> $@" |
| 221 | + @$(START_TIME) |
| 222 | + $(CMD_PREFIX)$(CC) $(CFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ |
| 223 | + @echo -en "\t Compile time: " |
| 224 | + @$(END_TIME) |
0 commit comments