-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathCMakeLists.txt
534 lines (489 loc) · 11.6 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
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
cmake_minimum_required(VERSION 3.19)
project(cx VERSION 0.1.0)
include(scripts/cmake-utils/cmake-fetch.cmake)
#Required defaults
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
#Explicitly disallow in-source builds
if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
message(
FATAL_ERROR
"In-source builds are not permitted."
)
endif()
#TODO Add support for clang-cl (and dpc++-cl?)
#Display error if compiler is not clang, gcc, icc/icx or msvc
list(
APPEND CX_SUPPORTED_COMPILERS
"Clang"
"AppleClang"
"GNU"
"Intel"
"IntelLLVM"
"MSVC"
)
set(_CX_SUPPORTED_COMPILER_DETECTED FALSE)
foreach(COMPILER ${CX_SUPPORTED_COMPILERS})
if(
CMAKE_C_COMPILER_ID STREQUAL COMPILER
AND CMAKE_CXX_COMPILER_ID STREQUAL COMPILER
)
set(_CX_SUPPORTED_COMPILER_DETECTED TRUE)
set(CX_DETECTED_COMPILER_ID "${COMPILER}")
endif()
endforeach()
if(NOT ${_CX_SUPPORTED_COMPILER_DETECTED})
message(
FATAL_ERROR
"You are using an unsupported compiler, please build with any of:\
${CX_SUPPORTED_COMPILERS}\
"
)
endif()
#List of supported clang-like compilers
list(
APPEND CX_CLANG_LIKE_COMPILERS
"Clang"
"AppleClang"
"IntelLLVM"
)
#TODO Handle passing arguments on different platforms (*nix, windows, etc)
#Sets the supplied argument for the current compiler
function(add_cc_or_ld_argument)
#Parse and check arguments
cmake_parse_arguments(
aca
"COMPILER;LINKER"
""
"${CX_SUPPORTED_COMPILERS}"
${ARGN}
)
#Sanitize `aca_COMPILER` and `aca_LINKER` flags
if((NOT aca_COMPILER AND NOT aca_LINKER) OR (aca_COMPILER AND aca_LINKER))
message(
FATAL_ERROR
"You must specifiy either `COMPILER` or `LINKER` for the arguments that you\
want to append\
"
)
endif()
#Set arguemnt target var
if(aca_COMPILER)
set(aca_TARGET_VAR "CX_COMPILE_FLAGS")
elseif(aca_LINKER)
set(aca_TARGET_VAR "CX_LINK_FLAGS")
endif()
#Add arguments for target compiler
foreach(argument ${aca_${CX_DETECTED_COMPILER_ID}})
list(
APPEND ${aca_TARGET_VAR}
"${argument}"
)
endforeach()
#Propagate changes outside function
set(${aca_TARGET_VAR} "${${aca_TARGET_VAR}}" PARENT_SCOPE)
endfunction()
#Add a source preprocessor define through the compiler cmdline
function(add_cc_src_flags)
foreach(flag ${ARGN})
add_cc_or_ld_argument(
COMPILER
Clang "-D${flag}"
AppleClang "-D${flag}"
GNU "-D${flag}"
#TODO Intel
IntelLLVM "-D${flag}"
MSVC "/D${flag}"
)
endforeach()
#Propagate `CX_COMPILE_FLAGS` changes outside function
set(CX_COMPILE_FLAGS "${CX_COMPILE_FLAGS}" PARENT_SCOPE)
endfunction()
#Determine whether or not this is the top-level project
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}")
set(CX_TOP_LEVEL TRUE)
else()
set(CX_TOP_LEVEL FALSE)
endif()
#All CX build flags
set(CX_DEBUG OFF CACHE BOOL "Enable CX debug building")
set(CX_QA OFF CACHE BOOL "Builds with sanitizers")
set(CX_HEADER_ONLY ON CACHE BOOL "Builds CX as a header-only library")
set(CX_UNIT_TESTS OFF CACHE BOOL "Builds CX unit tests")
set(CX_BENCHMARKS OFF CACHE BOOL "Builds CX benchmarks")
set(CX_COVERAGE OFF CACHE BOOL "Enable CX coverage profiling")
#Library support flags
set(CX_STL_SUPPORT OFF CACHE BOOL "Enable CX->stl integration")
set(CX_LIBC_SUPPORT ON CACHE BOOL "Enable CX->libc integration")
#Behavioural flags
set(CX_VARIANT_HARD_CLEAR OFF CACHE BOOL
"Enable clearing of variant cache before initialization and after destruction"
)
set(CX_VARARG_INTRENSICS OFF CACHE BOOL
"Enable definition of va_list function intrensics in 'cx/vararg.h', that\
would otherwise be defined by '<cstdarg>'\
"
)
set(CX_ERROR_TRACE OFF CACHE BOOL "Enable error tracing")
set(CX_ERROR_MSG OFF CACHE BOOL "Enable error messages")
set(CX_CONSTEXPR_SEMANTICS OFF CACHE BOOL
"Enables all constexpr functionality at the cost of space overhead"
)
#Sanitize error behaviour flags
if(NOT CX_STL_SUPPORT)
if(CX_ERROR_TRACE)
message(
FATAL_ERROR
"`CX_ERROR_TRACE` requires STL support"
)
endif()
endif()
#Sanitize coverage flag
if(
${CX_COVERAGE}
AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_ID STREQUAL "Clang"))
message(
FATAL_ERROR
"'CX_COVERAGE' can only be used when building with Clang"
)
endif()
#Sanitize header-only flag
if(NOT ${CX_HEADER_ONLY})
message(
FATAL_ERROR
"CX is currently a header-only library"
)
endif()
#Check for clang-like compiler
if(CX_DETECTED_COMPILER_ID IN_LIST CX_CLANG_LIKE_COMPILERS)
set(CX_COMPILER_CLANG_LIKE TRUE)
endif()
#Set default compiler flags and compiler id flags
add_cc_or_ld_argument(
COMPILER
Clang
-DCX_COMPILER_CLANG
-DCX_COMPILER_CLANG_LIKE
-Wall
-Wextra
-Werror
-pedantic
-ftemplate-backtrace-limit=0
-fno-common
-Wno-zero-length-array
AppleClang
-DCX_COMPILER_APPLE
-DCX_COMPILER_CLANG_LIKE
-Wall
-Wextra
-Werror
-pedantic
-ftemplate-backtrace-limit=0
-fno-common
-Wno-zero-length-array
GNU
-DCX_COMPILER_GCC
Intel
-DCX_COMPILER_INTEL
IntelLLVM
-DCX_COMPILER_INTEL_LLVM
-DCX_COMPILER_CLANG_LIKE
MSVC
/DCX_COMPILER_MSVC
/std:c++20
#TODO These flags are leaked to gtest when compiling against it
#and cause issues
#/Wall
#/WX
/D_CRT_NO_VA_START_VALIDATION
)
#Error on compilers pending official support
list(
APPEND CX_COMPILERS_AWAITING_SUPPORT
Intel
MSVC
)
if(CX_DETECTED_COMPILER_ID IN_LIST CX_COMPILERS_AWAITING_SUPPORT)
message(
FATAL_ERROR
"'${CX_DETECTED_COMPILER_ID}' is currently awaiting official support."
)
endif()
#Conditional compile flags
#Set the `CX_STL_SUPPORT` preprocessor flag or disable stl support
if(${CX_STL_SUPPORT})
#Add source flag for stl integration
add_cc_src_flags(CX_STL_SUPPORT)
else()
#Disable compiling / linking against stl lib
add_cc_or_ld_argument(
COMPILER
Clang
-nostdlib++
-fno-exceptions
AppleClang
-nostdlib++
-fno-exceptions
GNU
-nostdlib++
-fno-exceptions
#TODO Intel
MSVC
/EHsc
)
#Disable linking against stl libs (MSVC-specific)
add_cc_or_ld_argument(
LINKER
MSVC
/NODEFAULTLIB:libcpmt.lib
/NODEFAULTLIB:msvcprt.lib
/NODEFAULTLIB:libcpmtd.lib
/NODEFAULTLIB:msvcprtd.lib
)
endif()
#Set the `CX_LIBC_SUPPORT` preprocessor flag or disable libc support
if(${CX_LIBC_SUPPORT})
#Add source flag for libc integration
add_cc_src_flags(CX_LIBC_SUPPORT)
else()
#Disable linking against platform libc equivalent (uCRT on Windows)
add_cc_or_ld_argument(
COMPILER
Clang
-nostdlib
AppleClang
-nostdlib
GNU
-nostdlib
#TODO Intel
MSVC
/NODEFAULTLIB
/GS-
#/MT
/clr:nostdlib
/Zl
)
#Disable linking against any libc versions (MSVC specific)
add_cc_or_ld_argument(
LINKER
MSVC
/NODEFAULTLIB:libucrt.lib
/NODEFAULTLIB:libucrtd.lib
/NODEFAULTLIB:ucrt.lib
/NODEFAULTLIB:ucrtd.lib
/NODEFAULTLIB:libvcruntime.lib
/NODEFAULTLIB:libvcruntimed.lib
/NODEFAULTLIB:vcruntime.lib
/NODEFAULTLIB:vcruntimed.lib
/NODEFAULTLIB:libcmt.lib
/NODEFAULTLIB:libcmtd.lib
/NODEFAULTLIB:msvcrt.lib
/NODEFAULTLIB:msvcrtd.lib
/NODEFAULTLIB:msvcmrt.lib
/NODEFAULTLIB:msvcmrtd.lib
/NODEFAULTLIB:msvcurt.lib
/NODEFAULTLIB:msvcurtd.lib
)
endif()
#TODO remove since variant does not support this behaviour anymore
#Set the `CX_VARIANT_HARD_CLEAR` preprocessor flag
if(${CX_VARIANT_HARD_CLEAR})
add_cc_src_flags(CX_VARIANT_HARD_CLEAR)
endif()
#Set the `CX_VARARG_INTRENSICS` preprocessor flag
if(${CX_VARARG_INTRENSICS})
add_cc_src_flags(CX_VARARG_INTRENSICS)
endif()
#Set `CX_ERROR_TRACE` preprocessor flag
if(${CX_ERROR_TRACE})
add_cc_src_flags(CX_ERROR_TRACE)
endif()
#Set `CX_ERROR_MSG` preprocessor flag
if(${CX_ERROR_MSG})
add_cc_src_flags(CX_ERROR_MSG)
endif()
#Set the `CX_CONSTEXPR_SEMANTICS` preprocessor flag
if(${CX_CONSTEXPR_SEMANTICS})
add_cc_src_flags(CX_CONSTEXPR_SEMANTICS)
endif()
#Set the `CX_DEBUG` preprocessor flag and enable debug builds
if(${CX_DEBUG})
#Debug build flags
set(CMAKE_BUILD_TYPE Debug)
#Set preprocessor flag
add_cc_src_flags(CX_DEBUG)
#Set compiler debug args
add_cc_or_ld_argument(
COMPILER
Clang
-g
-O0
-fno-inline
-fno-inline-functions
-fno-omit-frame-pointer
-fno-lto
-fstandalone-debug
AppleClang
-g
-O0
-fno-inline
-fno-inline-functions
-fno-omit-frame-pointer
-fno-lto
-fstandalone-debug
GNU
-gdwarf-2
-O0
-fno-inline
-fno-inline-functions
-fno-omit-frame-pointer
-fno-lto
#TODO Intel
MSVC
/Z7
/DEBUG:FULL
/Od
)
else()
#Set compiler release flags
add_cc_or_ld_argument(
COMPILER
Clang
-O3
AppleClang
-O3
GNU
-O3
#TODO Intel
MSVC
/Ox
/Oy
/Oi
/Ob2
)
endif()
#Set the `CX_QA` preprocessor flag and enable a QA build
if(${CX_QA})
#Set preprocessor flag
add_cc_src_flags(CX_QA)
#Set compiler QA args
add_cc_or_ld_argument(
COMPILER
Clang
-fno-omit-frame-pointer
-fno-sanitize-recover=null
-fsanitize=address
-fsanitize=undefined
-fsanitize-address-use-after-scope
-fsanitize=bounds
-fsanitize=null
AppleClang
-fno-omit-frame-pointer
-fno-sanitize-recover=null
-fsanitize=address
-fsanitize=undefined
-fsanitize-address-use-after-scope
-fsanitize=bounds
-fsanitize=null
GNU
-fno-omit-frame-pointer
-fno-sanitize-recover=null
-fsanitize=address
-fsanitize=undefined
-fsanitize-address-use-after-scope
-fsanitize=bounds
-fsanitize=null
#TODO Intel
#Note: MSVC only supports ASAN
MSVC
/fsanitize=address
)
#Set linker QA args
add_cc_or_ld_argument(
LINKER
Clang
-fsanitize=address
-fsanitize=undefined
AppleClang
-fsanitize=address
-fsanitize=undefined
GNU
-fsanitize=address
-fsanitize=undefined
IntelLLVM
-fsanitize=address
-fsanitize=undefined
)
#Warn about incomplete `CX_QA` support on MSVC
if(CX_DETECTED_COMPILER_ID STREQUAL "MSVC")
message(
WARNING
"(CX_QA): MSVC only currently supports ASAN."
)
endif()
endif()
#Set the `CX_HEADER_ONLY` preprocessor flag
if(${CX_HEADER_ONLY})
#Add preprocessor flag
add_cc_src_flags(CX_HEADER_ONLY)
endif()
#Conditional library build type
if(${CX_HEADER_ONLY})
#Set up header-only build
add_library(cx INTERFACE)
target_include_directories(cx INTERFACE include)
target_compile_options(cx INTERFACE ${CX_COMPILE_FLAGS})
#Set up all preprocessor definitions
#Note: Platform-specific preprocessor define options are removed from flags
# prior to setting with `target_compile_definitions`
string(LENGTH "-D" CX_UNIX_DEFINE_PREFIX_LEN)
string(LENGTH "/D" CX_DOS_DEFINE_PREFIX_LEN)
foreach(flag CX_COMPILE_FLAGS)
if(flag MATCHES "^-D")
#Unix-style defines
string(SUBSTRING "${flag}" ${CX_UNIX_DEFINE_PREFIX_LEN} -1 flag)
target_compile_definitions(cx INTERFACE ${flag})
elseif(flag MATCHES "^\/D")
#DOS-style defines
string(SUBSTRING "${flag}" ${CX_DOS_DEFINE_PREFIX_LEN} -1 flag)
target_compile_definitions(cx INTERFACE ${flag})
endif()
endforeach()
else()
#Collect sources
file(
GLOB_RECURSE CX_SRC
"src/**.c"
"src/**.cpp"
)
#Set up shared library build
if(${CX_TOP_LEVEL})
set(CX_OPTION_SCOPE PUBLIC)
else()
set(CX_OPTION_SCOPE PRIVATE)
endif()
add_library(cx SHARED ${CX_SRC})
target_include_directories(cx PUBLIC include)
target_compile_options(cx ${CX_OPTION_SCOPE} ${CX_COMPILE_FLAGS})
target_link_options(cx ${CX_OPTION_SCOPE} ${CX_LINK_FLAGS})
#TODO Set up all preprocessor defines
endif()
#TODO Set up installation rules
#Testing
if(${CX_UNIT_TESTS} OR ${CX_BENCHMARKS})
add_subdirectory(test)
#TODO coverage for multiple platforms
if(${CX_COVERAGE})
message(FATAL_ERROR "Coverage runs are not yet implemented")
endif()
else()
#Warn if `CX_COVERAGE` is enabled but tests are not
if(${CX_COVERAGE})
message(
WARNING
"'CX_COVERAGE' is enabled but none of [CX_UNIT_TESTS CX_BENCHMARKS] are \
enabled, so no coverage runs will be performed.\
"
)
endif()
endif()