forked from monero-project/kovri
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
425 lines (371 loc) · 15.8 KB
/
CMakeLists.txt
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(kovri CXX)
set(KOVRI_PROJECT "The Kovri I2P Router Project")
# Versioning
set(KOVRI_VERSION "0.1.0-alpha")
set(KOVRI_CODENAME "Les préludes")
# Get git revision
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
find_package(Git)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD # use short hash for now
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE "KOVRI_GIT_REVISION"
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
set(KOVRI_GIT_REVISION " ")
endif()
endif()
message(STATUS "")
message(STATUS "${KOVRI_PROJECT}")
message(STATUS "${KOVRI_VERSION}-${KOVRI_GIT_REVISION} \"${KOVRI_CODENAME}\"")
message(STATUS "")
# I2NP/NetDb RI properties (used internally)
set(I2P_VERSION "0.9.35")
set(I2P_NETWORK_ID "2") # "1" is reserved for I2P version less than 0.6.1.10
# Produce version definitions, output to build directory
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.h.in" "${CMAKE_BINARY_DIR}/version.h" @ONLY)
# The interface target for internal usage requirements
add_library(kovri-private INTERFACE)
# Include build directory so we need to git-ignore version file output
target_include_directories(kovri-private INTERFACE ${CMAKE_BINARY_DIR})
# Configurable options
option(KOVRI_DATA_PATH "The path to the kovri data folder")
option(WITH_BINARY "Build kovri binary" ON)
option(WITH_KOVRI_UTIL "Build kovri utility binary" OFF)
option(WITH_COVERAGE "Build with coverage" OFF)
option(WITH_CRYPTOPP "Build with Crypto++" ON) # Default ON unless we switch libraries
option(BUILD_CRYPTOPP "Build Crypto++ inside cmake" OFF)
option(WITH_CPPNETLIB "Build with cpp-netlib" ON)
option(WITH_DOXYGEN "Enable support for Doxygen" OFF)
option(WITH_HARDENING "Use hardening compiler flags" OFF)
option(WITH_OPTIMIZE "Optimization flags" OFF)
option(WITH_PYTHON "Build wrappers which require Boost.Python" OFF)
option(WITH_STATIC "Static build" OFF)
option(WITH_STATIC_DEPS "Static build with static dependencies" OFF)
option(WITH_SHARED_DEPS "Dynamic build with partial in-tree shared dependencies" OFF)
option(WITH_TESTS "Build unit tests" OFF)
option(WITH_FUZZ_TESTS "Build fuzz tests" OFF)
option(WITH_COTIRE "Enable cotire (compile time reducer) - precompiled header and single compilation unit builds" ${MSVC})
# Verbosity enabled by default, but can be disabled from cli by adding -DCMAKE_VERBOSE_MAKEFILE=OFF
# https://github.com/monero-project/kovri/pull/867#discussion_r184359361
option(CMAKE_VERBOSE_MAKEFILE "Enable verbose build output" ON)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cotire/CMake)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7420
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Release>:NDEBUG>)
# Exceptions *should* substitute assertions in tests
if (WITH_TESTS)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS NDEBUG)
endif()
# The kovri shared object used for boost.python will need build rpath
if (NOT WITH_PYTHON AND NOT WITH_SHARED_DEPS)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
endif()
# Default build is Debug
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# Check whether we're on a 32-bit or 64-bit system
if(CMAKE_SIZEOF_VOID_P EQUAL "8")
set(ARCH_WIDTH "64")
else()
set(ARCH_WIDTH "32")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LINUX TRUE)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(FREEBSD TRUE)
endif()
# TODO(anonimal): continue with systems as needed
### TODO(unassigned): improve detection and use-case
# Minimal processor detection (needed for ARM build)
set(CPU "${CMAKE_SYSTEM_PROCESSOR}")
string(SUBSTRING "${CPU}" 0 3 PARSE_ARM)
if (CPU STREQUAL "aarch64" OR PARSE_ARM STREQUAL "arm")
set(ARM TRUE)
endif()
# Detect minimum compiler version
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.2)
message(FATAL_ERROR "GCC 4.9.2 or higher is required")
endif()
set(GNU TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
message(FATAL_ERROR "Clang 3.5 or higher is required")
endif()
set(CLANG TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0.0)
message(FATAL_ERROR "AppleClang 8.0.0 or higher is required")
endif()
set(CLANG TRUE)
endif()
# TODO(unassigned): an absolute hack to work around a clang (CMake?) bug that does not like our Release build type.
# Strangely, we don't do anything out of the ordinary with our Release build type, nor do our deps.
# The issue is not reproducible with Debug build type. See #993.
# Absolutely resolve this hack when are out of out Alpha, or no later than Beta.
if (CLANG)
# Remove aggressive optimizations from release builds. Referencing #993
string(REPLACE "-O3" "-O1" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
endif()
# Require C++14 support (minimum version compilers guarantee this)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
### TODO(unassigned): review, cleanup, improve
# Compiler flags (by vendor)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch")
if( (NOT ARM) AND (NOT ANDROID) )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
endif()
# TOOD(unassigned): we actually don't need this and it's quite annoying
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
# TODO(unassigned): we currently are not developing for OpenWRT
# TODO(unassgiend): review if the following is incompatible with static build and enabled hardening for OpenWRT
# Multiple definitions of __stack_chk_fail (libssp & libc)
#set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections")
# -flto is added from above
#set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections")
# https://developers.redhat.com/blog/2018/03/21/compiler-and-linker-flags-gcc/
if(WITH_HARDENING)
# Run-time buffer overflow detection
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS _FORTIFY_SOURCE=2)
# Reject potentially unsafe format string arguents
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security -Werror=format-security")
# Stack smashing protector
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4")
# Full ASLR for executables
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if(GNU AND NOT MINGW)
# Read-only segments after relocation and Disable lazy binding
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -z relro -z now")
endif()
endif()
if(ANDROID)
#From Android 5: "only position independent executables (PIE) are supported"
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
if(WITH_OPTIMIZE AND NOT WITH_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
if(WITH_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
endif()
endif()
if(NOT WIN32 AND NOT WITH_STATIC)
# TODO: Consider separate compilation for COMMON_SRC for library.
# No need in -fPIC overhead for binary if not interested in library
# HINT: revert c266cff CMakeLists.txt: compilation speed up
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
set(Boost_USE_MULTITHREADED ON)
if(WITH_STATIC_DEPS AND MSVC)
foreach(flag_var IN ITEMS
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif()
endforeach()
set(Boost_USE_STATIC_RUNTIME ON)
endif()
if(WITH_STATIC)
set(Boost_USE_STATIC_LIBS ON)
# Apple does not support statically linked binaries on Mac OS X
# https://developer.apple.com/library/content/qa/qa1118/_index.html
if (NOT MSVC AND NOT APPLE)
set(Boost_USE_STATIC_RUNTIME ON)
endif()
set(BUILD_SHARED_LIBS OFF)
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_THREAD_LIBS_INIT
"gcc_eh -Wl,-u,pthread_create,-u,pthread_once,-u,pthread_mutex_lock,-u,pthread_mutex_unlock,-u,pthread_join,-u,pthread_equal,-u,pthread_detach,-u,pthread_cond_wait,-u,pthread_cond_signal,-u,pthread_cond_destroy,-u,pthread_cond_broadcast,-u,pthread_cancel")
endif()
endif()
# Speed up MSVC build
# https://blogs.msdn.microsoft.com/vcblog/2016/10/26/recommendations-to-speed-c-builds-in-visual-studio/
if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG:fastlink")
if (NOT WITH_COTIRE AND MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
endif()
endif()
if(WITH_COTIRE)
set(COTIRE_PCH_MEMORY_SCALING_FACTOR "300")
include(cotire OPTIONAL)
endif()
# Get uname output
function(Uname output pattern)
execute_process(
COMMAND sh -c "uname -a 2>&1"
COMMAND grep "${pattern}"
OUTPUT_VARIABLE ${output}
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(${output} "${${output}}" PARENT_SCOPE)
endfunction(Uname)
# TODO(unassigned): extend Boost.Python cross-platform build support
set(additional_components)
if (WITH_PYTHON)
Uname(ARCH_LINUX "ARCH")
Uname(UBUNTU "Ubuntu")
if (APPLE OR ARCH_LINUX)
set(additional_components python3)
elseif (UBUNTU)
set(additional_components python-py35)
else()
message(FATAL_ERROR
"Boost.Python package not yet supported for your system. See TODO in root CMake recipe or open a feature request")
endif()
endif()
find_package(Boost 1.58 REQUIRED COMPONENTS filesystem log program_options ${additional_components})
if (NOT Boost_FOUND)
message(FATAL_ERROR "Boost not found or requirement not satisfied. See building instructions.")
endif()
# Fix OpenBSD build failure due to missing Boost::log_setup target
if (NOT TARGET Boost::log_setup)
get_property(BoostLogDependencies TARGET Boost::log PROPERTY INTERFACE_LINK_LIBRARIES)
list(REMOVE_ITEM BoostLogDependencies "Boost::log_setup")
set_property(TARGET Boost::log PROPERTY INTERFACE_LINK_LIBRARIES "${BoostLogDependencies}")
endif()
if(NOT WITH_STATIC)
target_compile_definitions(kovri-private INTERFACE BOOST_ALL_DYN_LINK)
endif()
# Libraries
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(WITH_CRYPTOPP)
if (BUILD_CRYPTOPP)
include(BuildCryptoPP)
else()
find_package(CryptoPP REQUIRED)
endif()
if(NOT TARGET CryptoPP::CryptoPP)
message(FATAL_ERROR "Could not find Crypto++. See building instructions.")
else()
target_link_libraries(kovri-private INTERFACE CryptoPP::CryptoPP)
target_compile_definitions(kovri-private INTERFACE WITH_CRYPTOPP)
endif()
endif()
# Despite only cpp-netlib requiring openssl, OSX and ANDROID apparently needs this as well
if (APPLE OR ANDROID)
# If we're on OS X check for Homebrew's copy of OpenSSL instead of Apple's
if (APPLE AND NOT OpenSSL_DIR)
execute_process (COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if (WITH_STATIC)
set(OPENSSL_USE_STATIC_LIBS TRUE)
endif()
find_package(OpenSSL REQUIRED)
if(NOT OPENSSL_FOUND)
message(FATAL_ERROR "Could not find OpenSSL. Please download and install it first!")
else()
target_link_libraries(kovri-private INTERFACE OpenSSL::SSL)
endif()
endif()
add_subdirectory(deps)
# Note: we're actually building off branch 0.13-release - not 0.12.0.
if(WITH_CPPNETLIB)
set(CPP-NETLIB_BUILD_SHARED_LIBS ${WITH_SHARED_DEPS} CACHE BOOL "Build cpp-netlib as shared libraries.")
set(CPP-NETLIB_BUILD_TESTS OFF CACHE BOOL "Build the cpp-netlib project tests.")
set(CPP-NETLIB_BUILD_EXAMPLES OFF CACHE BOOL "Build the cpp-netlib project examples.")
set(CPP-NETLIB_ENABLE_HTTPS ON CACHE BOOL "Build cpp-netlib with support for https if OpenSSL is found.")
set(CPP-NETLIB_STATIC_OPENSSL ${WITH_STATIC_DEPS} CACHE BOOL "Build cpp-netlib using static OpenSSL")
set(CPP-NETLIB_STATIC_BOOST ${WITH_STATIC} CACHE BOOL "Build cpp-netlib using static Boost")
add_subdirectory(deps/cpp-netlib)
endif()
if(WITH_FUZZ_TESTS)
if(NOT CLANG)
message(FATAL_ERROR "clang is required for fuzz tests. See building instructions.")
endif()
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
message(FATAL_ERROR "Clang version 5 or higher is required")
endif()
find_package(Fuzzer REQUIRED)
if(NOT Fuzzer_FOUND)
message(FATAL_ERROR "Could not find Fuzzer. See building instructions.")
else()
message(STATUS "Found Fuzzer: ${Fuzzer_INCLUDE_DIR}, ${Fuzzer_LIBRARIES}")
target_include_directories(kovri-private INTERFACE ${Fuzzer_INCLUDE_DIR})
target_compile_definitions(kovri-private INTERFACE WITH_FUZZ_TESTS)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-coverage=trace-pc-guard -fsanitize=address")
endif()
# Doxygen support
if(WITH_DOXYGEN)
include(UseDoxygen)
endif()
# For Boost.Python wrapping
if (WITH_PYTHON)
find_package(PythonLibs REQUIRED)
if (NOT PythonLibs_FOUND)
message(FATAL_ERROR "Python not found or requirement not satisfied. See building instructions.")
else()
message(STATUS "Found Python: ${PYTHON_INCLUDE_DIR}, ${PYTHON_LIBRARIES}")
target_include_directories(kovri-private INTERFACE ${PYTHON_INCLUDE_DIRS})
endif()
endif()
# Solve issue with as.exe fatal error - Object file has too many sections
# http://stackoverflow.com/a/28372660
# This error appear for cotired build
if (MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
# TODO(unassigned): remove once a better solution is found (we don't want to force optimization)
# Referencing https://github.com/monero-project/meta/issues/238
if (WITH_STATIC AND ARCH_WIDTH EQUAL "64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
endif()
endif()
# Directly link IPHLPAPI.lib instead of using `#pragma comment()`
if (WIN32)
target_link_libraries(kovri-private INTERFACE "IPHLPAPI.lib")
endif()
# Load remaining includes
target_include_directories(kovri-private INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
# Use data-path set in Makefile. Code must call upon this definition.
if(KOVRI_DATA_PATH)
target_include_directories(kovri-private INTERFACE KOVRI_CUSTOM_DATA_PATH="${KOVRI_DATA_PATH}")
endif()
# Show summary
message(STATUS "---------------------------------------")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
message(STATUS "Compiler vendor : ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "Compiler version : ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "Compiler path : ${CMAKE_CXX_COMPILER}")
message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}")
message(STATUS "Kovri data directory: ${KOVRI_DATA_DIR}")
message(STATUS "Options:")
message(STATUS " BINARY : ${WITH_BINARY}")
message(STATUS " KOVRI UTIL : ${WITH_KOVRI_UTIL}")
message(STATUS " COVERAGE : ${WITH_COVERAGE}")
message(STATUS " CRYPTOPP : ${WITH_CRYPTOPP}")
message(STATUS " BUILD CRYPTOPP : ${BUILD_CRYPTOPP}")
message(STATUS " DOXYGEN : ${WITH_DOXYGEN}")
message(STATUS " HARDENING : ${WITH_HARDENING}")
message(STATUS " OPTIMIZATION : ${WITH_OPTIMIZE}")
message(STATUS " PYTHON : ${WITH_PYTHON}")
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
message(STATUS " STATIC DEPS BUILD: ${WITH_STATIC_DEPS}")
message(STATUS " SHARED DEPS BUILD: ${WITH_SHARED_DEPS}")
message(STATUS " TESTS : ${WITH_TESTS}")
message(STATUS " FUZZ TESTS : ${WITH_FUZZ_TESTS}")
message(STATUS " Cotire : ${WITH_COTIRE}")
message(STATUS "---------------------------------------")
# Handle paths nicely
include(GNUInstallDirs)
add_subdirectory(src)
if (WITH_TESTS)
enable_testing()
add_subdirectory(tests/unit_tests)
endif()
if (WITH_PYTHON)
add_subdirectory(contrib/python)
endif()