-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcommon_settings.mk
182 lines (166 loc) · 7.86 KB
/
common_settings.mk
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
# Validate that we have everything we need
ifeq "" "$(SRCS)"
$(error SRCS must be defined before including this file)
else ifeq "" "$(filter clean print-%,$(MAKECMDGOALS))"
ifeq "" "$(BOOST_DIR)"
$(error The BOOST_DIR variable must be set to where you cloned Boost)
else ifeq "" "$(GTEST_DIR)"
$(error The GTEST_DIR variable must be set to where you cloned Google \
Test and Google Mock)
else ifeq "" "$(HUNSPELL_DIR)"
$(error The HUNSPELL_DIR variable must be set to where you cloned \
Hunspell)
else ifeq "" "$(CRYPTOPP_DIR)"
$(error The CRYPTOPP_DIR variable must be set to where you cloned \
Crypto++)
else ifeq "" "$(OPENSSL_DIR)"
$(error The OPENSSL_DIR variable must be set to where you cloned \
OpenSSL)
endif
endif
# Standard settings
this_plugin := $(lastword $(MAKEFILE_LIST))
.DELETE_ON_ERROR :
CXX = g++
CPP_STANDARD = -std=c++17 -pthread
CPP_QUALITY_CHECKS = -pedantic -pedantic-errors -Wall -Wextra
CPP_OPTIMIZATIONS = -O3 -ffunction-sections -fdata-sections
CPPFLAGS = $(CPP_STANDARD) $(CPP_QUALITY_CHECKS) $(CPP_OPTIMIZATIONS)
CXXFLAGS := -isystem $(BOOST_DIR) \
-isystem $(GTEST_DIR)/googletest/include \
-isystem $(HUNSPELL_DIR)/src/hunspell \
-isystem $(CRYPTOPP_DIR) \
-isystem $(OPENSSL_DIR)/include
LIB_DIRS = $(if $(BOOST_LIBS),$(BOOST_DIR)/stage/lib) \
$(GTEST_DIR)/bazel-bin \
$(HUNSPELL_DIR)/src/hunspell/.libs \
$(CRYPTOPP_DIR) \
$(OPENSSL_DIR)
GNU_LD := $(shell ld -v 2>&1 || ld -V 2>&1)
LDFLAGS = -pthread -Wl,$(if $(filter GNU Solaris, \
$(GNU_LD)),--gc-sections,-dead_strip) \
$(foreach d,$(LIB_DIRS),-L$(d))
LIBS += gtest_main gtest
LDLIBS = $(foreach lib,$(BOOST_LIBS),-lboost_$(lib)) \
$(foreach lib,$(LIBS),-l$(lib))
# Adapt VPATH for out-of-source builds, i.e. "make -f .../path/to/GNUmakefile".
# Also allow only source files, not build products, to be directory-searched.
caller_makefile := $(lastword $(filter-out $(this_plugin),$(MAKEFILE_LIST)))
VPATH := $(addprefix $(dir $(caller_makefile)),$(VPATH) .)
vpath %.h $(VPATH)
vpath %.hpp $(VPATH)
vpath %.c $(VPATH)
vpath %.cc $(VPATH)
vpath %.cxx $(VPATH)
vpath %.cpp $(VPATH)
# This is so that a Challenge-specific makefile can "include" the directory of
# another Challenge using VPATH for both dependencies and C++ headers.
#
# Precondition: VPATH must be space-delimited, and not colon- or
# semicolon-delimited.
CXXFLAGS += $(addprefix -I,$(VPATH))
VPATH :=
# The built-in rule for linking object files uses the $(CC) variable, which
# expands to "cc". However, the "cc" program does not exist in a standard
# MinGW-w64 installation, so using $(CXX) instead as defined above.
CC = $(CXX)
PLATFORM := $(strip $(shell uname -s))
IS_WINDOWS_PLATFORM := $(filter CYGWIN_% MSYS_% MINGW% windows%,$(PLATFORM))
IS_MACOSX_PLATFORM := $(filter Darwin,$(PLATFORM))
IS_ANDROID_PLATFORM := $(filter Android,$(shell uname -o))
include $(dir $(this_plugin))dependency_cache.mk
, = ,
LDFLAGS += $(if $(IS_MACOSX_PLATFORM),-Wl$(,)-headerpad_max_install_names, \
$(foreach d,$(LIB_DIRS),-Wl,-rpath,$(d))) \
$(if $(and $(IS_ANDROID_PLATFORM),$(filter cryptopp,$(LIBS))), \
-lndk_compat)
ifeq "" "$(filter clean print-%,$(MAKECMDGOALS))"
$(SRCS:.cpp=.o) : $(this_plugin) $(dir $(this_plugin))dependency_cache.mk
# Git doesn't know how to ignore extension-less binaries, so we must teach
# it. No need to check this in, though -- it will be created each time.
EXECUTABLE_NAME := $(.DEFAULT_GOAL)
$(file >> .gitignore,.gitignore)
$(file >> .gitignore,$(EXECUTABLE_NAME))
define post_link_actions_for_windows =
# GCC creates executables with .exe file extension on Windows platforms.
# GNU Make's implicit rules, however, expect an extension-less program
# name. So each time we run Make on Windows, it can't find the final
# target and so re-runs the link recipe unnecessarily. To fix this we
# produce a hardlink of the .exe file as the extension-less file.
#
# NOTE: MSYS utilities can auto-check for <file>.exe when provided
# <file>, but not vice-versa. So we first rename the .exe to .sav,
# to prevent it from being considered at deletion or hardlink-time
# existence-check.
.PHONY : create_hardlink_without_exe_extension
create_hardlink_without_exe_extension : $(EXECUTABLE_NAME)
mv $(EXECUTABLE_NAME).exe $(EXECUTABLE_NAME).sav
rm -f $(EXECUTABLE_NAME)
mv $(EXECUTABLE_NAME).sav $(EXECUTABLE_NAME)
ln -f $(EXECUTABLE_NAME) $(EXECUTABLE_NAME).exe || true
# Windows's PE loader does not support a DLL search path embedded inside
# the EXE file, without running code like AddDllDirectory() or
# SetDefaultDllDirectories() beforehand. See
# https://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx for
# details.
#
# We work around this limitation by creating a hardlink of any DLLs from
# the library search path into the directory of the EXE file.
.PHONY : dll_hardlinks_to_simulate_rpath
dll_hardlinks_to_simulate_rpath : create_hardlink_without_exe_extension
rm -f ./*.dll || true
ln -f $(wildcard $(foreach d,$(LIB_DIRS),$(d)/*.dll)) .
echo *.dll >> .gitignore
.DEFAULT_GOAL = dll_hardlinks_to_simulate_rpath
endef
$(if $(IS_WINDOWS_PLATFORM), \
$(eval $(value post_link_actions_for_windows)) \
)
# https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/
CPPFLAGS += $(if $(IS_WINDOWS_PLATFORM),-D__USE_MINGW_ANSI_STDIO=1)
space := a
space := $(space:a= )
relpath = $(if $(filter-out /%,$(1)),$(1),$(strip \
$(subst $(space),/,$(patsubst %,..,$(subst /, ,$(CURDIR))))$(1)))
define post_link_actions_for_darwin =
# Darwin (macOS) has support for dynamic library (dylib) search path
# embedded inside the executable, but it takes effect only if the
# "install name" of the dylib starts with "@rpath". Prior to OSX 10.5 we
# can use only "@executable_path", though. The "install name" is copied
# over from the dylib when linking the executable, and typically doesn't
# contain these tokens. We fix it here.
#
# https://jorgen.tjer.no/post/2014/05/20/dt-rpath-ld-and-at-rpath-dyld/
# https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath
.PHONY : fix_relative_paths_to_dylibs
fix_relative_paths_to_dylibs : $(EXECUTABLE_NAME)
otool -L $(EXECUTABLE_NAME) \
| tail -n +2 \
| cut -d' ' -f1 \
| grep -F $(foreach lib,$(BOOST_LIBS),-e libboost_$(lib)) \
$(foreach lib,$(LIBS),-e lib$(lib)) \
| xargs -L1 -J% sh -c '\
install_name_tool \
-change "$$0" \
@executable_path/$$(\
ls $(foreach d,$(LIB_DIRS),$(call relpath,$(d))/` \
basename "$$0"`) 2>/dev/null) \
$(EXECUTABLE_NAME) </dev/null' %
.DEFAULT_GOAL = fix_relative_paths_to_dylibs
endef
$(if $(and $(BOOST_LIBS)$(LIBS),$(IS_MACOSX_PLATFORM)), \
$(eval $(value post_link_actions_for_darwin)) \
)
endif
# Standard cleanup target
.PHONY : clean
clean :
rm -f $(wildcard $(foreach s,$(SRCS),$(s:.cpp=.d) $(s:.cpp=.o)) \
$(.DEFAULT_GOAL) $(.DEFAULT_GOAL).exe *.dll)
grep -n "^.gitignore" .gitignore \
| cut -d: -f1 \
| head -n 1 \
| xargs -I "{}" head -n "{}" .gitignore \
> .gitignore.sav
mv .gitignore.sav .gitignore
$(if $(filter .gitignore,$(firstword $(file < .gitignore))),rm .gitignore)