-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGNUmakefile
218 lines (200 loc) · 6.19 KB
/
GNUmakefile
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#-----------------------------------------------------------------------------
# this GNU-makefile relies on the GCC toolchain
# nb: under Windows, the Mingw-w64 package provides the mingw32-make command
# ( see http://www.enib.fr/~harrouet/misc.html#mingw )
#~~~~ control global settings ~~~~
# make opt=1 --> enable optimisation, then disable debug
# make opt=0 --> disable optimisation, then enable debug
opt=0
# make clang=1 --> use clang/clang++, not gcc/g++
# make clang=0 --> use gcc/g++, not clang/clang++
clang=0
# make emcc=1 --> target javascript rather than the native platform
# make emcc=0 --> target the native platform rather than javascript
emcc=0
#~~~~ build library or programs ~~~~
# if LIB_TARGET is provided, this library will be built (with its
# platform-specific name), otherwise ${EXE_PREFIX}* programs will be built
LIB_TARGET=
EXE_PREFIX=prog
#~~~~ detect operating system ~~~~
ifneq (${OS},Windows_NT)
ifneq (,${findstring Microsoft,${shell cat /proc/version 2>/dev/null}})
# Windows-Subsystem-for-Linux
OS:=WSL
else ifneq (,${findstring Ubuntu,${shell lsb_release -i 2>/dev/null}})
OS:=Ubuntu
else ifneq (,${findstring Raspbian,${shell lsb_release -i 2>/dev/null}})
# Standard distribution for Raspberry-Pi
OS:=Raspbian
else
OS:=${strip ${shell uname -s}}
endif
endif
#~~~~ adjust project-specific settings ~~~~
CPPFLAGS=
# CPPFLAGS+=-I header/path
LDFLAGS=
# LDFLAGS+=-L library/path -Wl,-rpath,library/path -l library_name
CFLAGS=
CXXFLAGS=
ifeq (${OS},Windows_NT)
# nothing special for now
else
CPPFLAGS+=-fPIC
ifeq (${OS},Darwin)
# nothing special for now
else
ifeq (${OS},Ubuntu)
# sanitizer requires gold-linker on Ubuntu
LDFLAGS+=-fuse-ld=gold
else ifeq (${OS},Raspbian)
# some warnings may appear when mixing g++-6 and g++-7 on Raspbian
CXXFLAGS+=-Wno-psabi
else
# nothing special for now
endif
endif
endif
#~~~~ adjust platform-specific features (Posix/Windows/Emscripten...) ~~~~
ifeq (${OS},Windows_NT)
LIB_PREFIX=
LIB_SUFFIX=.dll
EXE_SUFFIX=.exe
SKIP_LINE=echo.
REMOVE=del /q
else
LIB_PREFIX=lib
ifeq (${OS},Darwin)
LIB_SUFFIX=.dylib
else
LIB_SUFFIX=.so
endif
EXE_SUFFIX=
SKIP_LINE=echo
REMOVE=rm -rf
endif
ifeq (${strip ${emcc}},1)
LIB_PREFIX:=lib
LIB_SUFFIX:=.bc
EXE_SUFFIX:=.html
endif
#~~~~ deduce file names ~~~~
ifneq (${strip ${LIB_TARGET}},)
LIB_TARGET:=${LIB_PREFIX}${strip ${LIB_TARGET}}${LIB_SUFFIX}
MAIN_C_FILES=
MAIN_CXX_FILES=
else
LIB_TARGET:=
MAIN_C_FILES=${wildcard ${strip ${EXE_PREFIX}}*.c}
MAIN_CXX_FILES=${wildcard ${strip ${EXE_PREFIX}}*.cpp}
endif
COMMON_C_FILES=${filter-out ${MAIN_C_FILES},${wildcard *.c}}
COMMON_CXX_FILES=${filter-out ${MAIN_CXX_FILES},${wildcard *.cpp}}
#
MAIN_OBJECT_FILES=${sort ${patsubst %.c,%.o,${MAIN_C_FILES}} \
${patsubst %.cpp,%.o,${MAIN_CXX_FILES}}}
COMMON_OBJECT_FILES=${sort ${patsubst %.c,%.o,${COMMON_C_FILES}} \
${patsubst %.cpp,%.o,${COMMON_CXX_FILES}}}
OBJECT_FILES=${MAIN_OBJECT_FILES} ${COMMON_OBJECT_FILES}
DEPEND_FILES=${patsubst %.o,%.d,${OBJECT_FILES}}
EXE_FILES=${sort ${patsubst %.c,%${EXE_SUFFIX},${MAIN_C_FILES}} \
${patsubst %.cpp,%${EXE_SUFFIX},${MAIN_CXX_FILES}}}
#
GENERATED_FILES=${DEPEND_FILES} ${OBJECT_FILES} ${LIB_TARGET} ${EXE_FILES}
ifeq (${OS},Darwin)
GENERATED_FILES+=${wildcard *.dSYM}
endif
ifeq (${strip ${emcc}},1)
GENERATED_FILES+=${patsubst %.html,%.js,${EXE_FILES}}
GENERATED_FILES+=${patsubst %.html,%.html.mem,${EXE_FILES}}
endif
GENERATED_FILES+=${wildcard output_* *~ core}
GENERATED_FILES+=${wildcard .[1-9]}
GENERATED_FILES+=${wildcard .[1-9][0-9]}
GENERATED_FILES+=${wildcard .[1-9][0-9][0-9]}
GENERATED_FILES+=${wildcard .[1-9][0-9][0-9][0-9]}
GENERATED_FILES+=${wildcard .[1-9][0-9][0-9][0-9][0-9]}
#~~~~ compiler/linker settings ~~~~
CPPFLAGS+=-pedantic -Wall -Wextra -Wconversion -MMD
CFLAGS+=-std=c99 -Wc++-compat -Wwrite-strings -Wold-style-definition
CXXFLAGS+=-std=c++1z
# sign-conversion is too restrictive on standard C++ library usage
CXXFLAGS+=-Wno-sign-conversion
# clang warns about missing double-braces on std::array
CXXFLAGS+=-Wno-missing-braces
LDFLAGS+=
ifeq (${strip ${emcc}},1)
CC=emcc
CXX=em++
else ifeq (${strip ${clang}},1)
CC=clang
CXX=clang++
else
CC=gcc
CXX=g++
endif
#
ifneq (${strip ${MAIN_CXX_FILES} ${COMMON_CXX_FILES}},)
# force c++ usage if there is at least one c++ source file
CC:=${CXX}
CFLAGS:=${CXXFLAGS}
endif
#
LD:=${CC}
#~~~~ debug/optimisation settings ~~~~
ifeq (${strip ${opt}},1)
CPPFLAGS+=-O3 -DNDEBUG -fomit-frame-pointer
CPPFLAGS+=-ffast-math
CPPFLAGS+=-march=native
# CPPFLAGS+=-fopt-info-vec-optimized
else
CPPFLAGS+=-g -O0 -UNDEBUG
ifeq (${strip ${emcc}},1)
# sanitizer is not available yet with Emscripten
else ifeq (${OS},Windows_NT)
# sanitizer is not available yet on Windows
else ifeq (${OS},WSL)
# sanitizer is not available yet on Windows-Subsystem-for-Linux
else ifeq (${OS},Darwin)
# sometimes sanitizer produces linker warnings on MacOSX
else
CPPFLAGS+=-fsanitize=address,undefined
ifeq (${OS},Raspbian)
# dynamic sanitizer libraries may not be found on Raspbian
CPPFLAGS+=-static-libasan -static-libubsan
endif
endif
endif
#~~~~ main target ~~~~
all : ${EXE_FILES} ${LIB_TARGET}
rebuild : clean all
.SUFFIXES:
.SECONDARY:
.PHONY: all clean rebuild
#~~~~ linker command to produce the library (if any) ~~~~
${LIB_TARGET} : ${COMMON_OBJECT_FILES}
@echo ==== linking $@ ====
${LD} -shared -o $@ $^ ${CPPFLAGS} ${LDFLAGS}
@${SKIP_LINE}
#~~~~ linker command to produce the executable files (if any) ~~~~
%${EXE_SUFFIX} : %.o ${COMMON_OBJECT_FILES}
@echo ==== linking $@ ====
${LD} -o $@ $^ ${CPPFLAGS} ${LDFLAGS}
@${SKIP_LINE}
#~~~~ compiler command for every source file ~~~~
%.o : %.c
@echo ==== compiling [opt=${opt}] $< ====
${CC} -o $@ $< -c ${CPPFLAGS} ${CFLAGS}
@${SKIP_LINE}
%.o : %.cpp
@echo ==== compiling [opt=${opt}] $< ====
${CXX} -o $@ $< -c ${CPPFLAGS} ${CXXFLAGS}
@${SKIP_LINE}
-include ${DEPEND_FILES}
#~~~~ remove generated files ~~~~
clean :
@echo ==== cleaning ====
${REMOVE} ${GENERATED_FILES}
@${SKIP_LINE}
#-----------------------------------------------------------------------------