summaryrefslogtreecommitdiffstats
path: root/Makefile
blob: 9359d29f6d69f049f1dec0acf089e248bba39596 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
### Adapted from https://github.com/fboulnois/modern-makefile
### Settings: Modify the parameters below to configure your project
###============================================================================

# program name and source directories
BIN_NAME :=
SRC_DIRS :=

# enable debug build
DEBUG = 1

# general program flags
ifdef DEBUG
	MY_CFLAGS = -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -g -fsanitize=address,undefined
else
	MY_CFLAGS = -O3
endif
MY_LIBS   =
WARNINGS  = -fstack-protector-strong -fpie -pedantic -Wall -Wextra

# language specific options
CFLAGS    = -std=c11
CXXFLAGS  = -std=c++11

# compiler defaults
CC  = gcc
CXX = g++

# static analysis / formatting tools
CFORMAT = clang-format
CTIDY = clang-tidy

### Advanced: You should generally not need to modify anything below this line
###============================================================================

## If no source dirs are specified use files in current working directory
##-----------------------------------------------------------------------------
ifeq ($(SRC_DIRS),)
	SRC_DIRS := .
endif

## Check if the software being built is a shared library
##-----------------------------------------------------------------------------
BIN_SHARED := $(filter -shared,$(MY_CFLAGS))

## If no program name is specified use current directory name or a.out
##-----------------------------------------------------------------------------
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
ifeq ($(BIN_NAME),)
	BIN_NAME := $(lastword $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR))))
	ifneq ($(BIN_SHARED),)
		BIN_NAME := $(addsuffix .so,$(addprefix lib,$(BIN_NAME)))
	endif
endif
ifeq ($(BIN_NAME),)
	BIN_NAME := a.out
endif

## Find source files in specified directories and name objects and dependencies
##-----------------------------------------------------------------------------
SRC_EXTS  := .c .C .cc .cp .cpp .CPP .cxx .c++
SRC_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(addprefix $(dir)/*,$(SRC_EXTS))))
SRC_CXX   := $(filter-out %.c,$(SRC_FILES))
OBJECTS   := $(addsuffix .o,$(basename $(SRC_FILES)))
DEPENDS   := $(OBJECTS:.o=.d)

## Compiler and linker related actions
##-----------------------------------------------------------------------------
CMP_C := $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(WARNINGS) -MD
LNK_C := $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)

CMP_CXX := $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(WARNINGS) -MD
LNK_CXX := $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)

## Clear built-in .SUFFIXES and set .PHONY targets
##-----------------------------------------------------------------------------
.SUFFIXES:

.PHONY: all check clean format objects

## Debug values of makefile variables, to check use 'make print-VARNAME'
##-----------------------------------------------------------------------------
print-%: ; @echo $*=$($*)

## Build everything
##-----------------------------------------------------------------------------
all: $(if $(DEBUG), format check) $(BIN_NAME)

## Static analysis
##-----------------------------------------------------------------------------
check: $(SRC_FILES)
	$(CTIDY) $(CPPFLAGS) $(SRC_FILES)

## Formatting
##-----------------------------------------------------------------------------
format: $(SRC_FILES)
	$(CFORMAT) -i $(SRC_FILES)

## Clean up build
##-----------------------------------------------------------------------------
clean:
	$(RM) $(DEPENDS) $(OBJECTS) $(BIN_NAME) $(BIN_NAME).exe

## Build object files
##-----------------------------------------------------------------------------
objects: $(OBJECTS)

%.o: %.c
	$(CMP_C) -c $< -o $@

%.o: %.C
	$(CMP_CXX) -c $< -o $@

%.o: %.cc
	$(CMP_CXX) -c $< -o $@

%.o: %.cp
	$(CMP_CXX) -c $< -o $@

%.o: %.cpp
	$(CMP_CXX) -c $< -o $@

%.o: %.CPP
	$(CMP_CXX) -c $< -o $@

%.o: %.cxx
	$(CMP_CXX) -c $< -o $@

%.o: %.c++
	$(CMP_CXX) -c $< -o $@

## Build dependencies
##-----------------------------------------------------------------------------
-include $(DEPENDS)

## Build executable
##-----------------------------------------------------------------------------
$(BIN_NAME): $(OBJECTS)
ifeq ($(SRC_CXX),)
	$(LNK_C) $(OBJECTS) $(MY_LIBS) -o $@
else
	$(LNK_CXX) $(OBJECTS) $(MY_LIBS) -o $@
endif
ifeq ($(BIN_SHARED),)
	@echo To execute program, type ./$@
else
	@echo To link shared library, use $@
endif