forked from systerel/S2OPC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCommonDefs.cmake
581 lines (496 loc) · 26.3 KB
/
CommonDefs.cmake
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
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
## ##
# S2OPC libraries common definitions #
## ##
set(S2OPC_COMMON_DEFS_SET TRUE)
### Define root path and CMake module path for external libraries ###
set(S2OPC_ROOT_PATH ${CMAKE_CURRENT_LIST_DIR})
set(CMAKE_MODULE_PATH "${S2OPC_ROOT_PATH}/CMake;${CMAKE_MODULE_PATH}")
### Output directories ###
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Manage paths that includes the multi-config name (Debug, Release, etc.) in output directory path such as MSVC:
# => We do not want to have the config subdirectory (Debug, etc.) to run the tests
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
### Common dependencies ###
## Manage static/shared property of external libraries
# Make CMake use static version of all dependencies by default
option(USE_STATIC_EXT_LIBS "S2OPC libraries and binaries depend on static version of external libraries" ON)
option(BUILD_SHARED_LIBS "Build dynamic libraries for S2OPC instead of static libraries" OFF)
if(USE_STATIC_EXT_LIBS)
set(USE_STATIC_MBEDTLS_LIB ${USE_STATIC_EXT_LIBS})
set(USE_STATIC_CYCLONE_CRYPTO_LIB ${USE_STATIC_EXT_LIBS})
set(USE_STATIC_EXPAT_LIB ${USE_STATIC_EXT_LIBS})
if(BUILD_SHARED_LIBS)
message(WARNING "Both BUILD_SHARED_LIBS and USE_STATIC_EXT_LIBS are active: external libraries will still be linked statically (if available)")
endif()
# else: USE_STATIC_<LIBNAME>_LIB can be set in a custom way, otherwise default CMake behavior is kept
endif()
## Expat dependency management
# redefine CMake behavior for find_package(expat ...) calling find_library(...) if needed
if (USE_STATIC_EXPAT_LIB)
set(_expat_orig_lib_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(WIN32)
list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a)
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
endif()
#########################
# Detect endianness
# After Version 3.2, CMAKE_C_BYTE_ORDER is defined by CMake
if(${CMAKE_VERSION} VERSION_LESS "3.20")
include(TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
set(CMAKE_C_BYTE_ORDER BIG_ENDIAN)
else()
set(CMAKE_C_BYTE_ORDER LITTLE_ENDIAN)
endif()
endif()
if (${CMAKE_C_BYTE_ORDER} STREQUAL BIG_ENDIAN)
add_definitions(-DSOPC_IS_LITTLE_ENDIAN=0)
elif (${CMAKE_C_BYTE_ORDER} STREQUAL LITTLE_ENDIAN)
add_definitions(-DSOPC_IS_LITTLE_ENDIAN=1)
endif()
#########################
# Choose crypto option
option(S2OPC_CRYPTO_MBEDTLS "Use MbedTLS" ON)
option(S2OPC_CRYPTO_CYCLONE "Use CycloneCRYPTO" OFF)
set(S2OPC_CRYPTO_LIB "nocrypto")
if(S2OPC_CRYPTO_CYCLONE)
set(S2OPC_CRYPTO_LIB "cyclone")
elseif(S2OPC_CRYPTO_MBEDTLS)
set(S2OPC_CRYPTO_LIB "mbedtls")
endif()
# Final check on crypto options
message("-- Using '${S2OPC_CRYPTO_LIB}' as crypto library")
# Check S2OPC_CRYPTO_LIB parameters
if(NOT DEFINED S2OPC_CRYPTO_LIB)
message(FATAL_ERROR "'S2OPC_CRYPTO_LIB' is not defined!")
endif()
option(S2OPC_CLIENTSERVER_ONLY "Only build the common library and client server libraries, tests, and samples (effectively excludes pubsub)." OFF)
option(S2OPC_PUBSUB_ONLY "Only build the common library and the pubsub library, tests, and samples (effectively excludes clientserver)." OFF)
if(S2OPC_CLIENTSERVER_ONLY AND NOT WITH_PYS2OPC)
find_package(expat CONFIG) # if not found XML loaders will not be compiled
else()
find_package(expat REQUIRED CONFIG)
endif()
if(NOT S2OPC_CLIENTSERVER_ONLY)
# Paho library is used if available to add MQTT transport to the PubSub module
find_package(eclipse-paho-mqtt-c CONFIG)
endif()
# Detect limitation on PubSub
if(WIN32 AND NOT S2OPC_CLIENTSERVER_ONLY)
message(FATAL_ERROR "PubSub module requires platform dependent code not implemented yet on windows (see issue #747). Please set S2OPC_CLIENTSERVER_ONLY to exclude PubSub module.")
endif()
# Expat have specific requirements for static library and MSCV: XML_STATIC shall be defined by application using it
if(expat_FOUND)
if(WIN32 AND NOT MINGW)
if (USE_STATIC_EXPAT_LIB)
target_compile_definitions(expat::expat INTERFACE "XML_STATIC")
endif()
endif()
endif()
# redefine CMake behavior for find_library(*)
if (USE_STATIC_EXPAT_LIB)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_expat_orig_lib_suffixes})
endif()
### Define default S2OPC compilation flags for several compilers ###
# Define variables to store S2OPC specific definitions, compiler and linker flags
set(S2OPC_DEFINITIONS)
set(S2OPC_COMPILER_FLAGS)
set(S2OPC_LINKER_FLAGS)
set(S2OPC_LINK_LIBRARIES)
# Identify compiler: variable set only on expected compiler
set(IS_GNU $<C_COMPILER_ID:GNU>)
set(IS_CLANG $<C_COMPILER_ID:Clang>)
set(IS_MSVC $<C_COMPILER_ID:MSVC>)
set(IS_MINGW $<BOOL:${MINGW}>) # MINGW set by cmake
# make the warnings as errors a default behavior
option(WARNINGS_AS_ERRORS "Treat warnings as errors when building" ON)
set(IS_WARNINGS_AS_ERRORS $<STREQUAL:${WARNINGS_AS_ERRORS},ON>)
# Set GNU compiler flags
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:-std=c99 -pedantic -Wall -Wextra>)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:$<${IS_WARNINGS_AS_ERRORS}:-Werror>>)
# Specific flags for CERT rules
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:-Wimplicit -Wreturn-type -Wsequence-point -Wcast-qual -Wuninitialized -Wcast-align -Wstrict-prototypes -Wchar-subscripts -Wformat=2 -Wconversion -Wshadow -Wmissing-prototypes -Wdate-time -Wfloat-equal -Winit-self -Wjump-misses-init -Wlogical-op -Wnested-externs -Wnormalized -Wold-style-definition -Wpointer-arith -Wswitch-default -Wtrampolines >)
# Make optional some flags not supported with GCC < 6
list(APPEND S2OPC_COMPILER_FLAGS $<$<AND:${IS_GNU},$<VERSION_GREATER:${CMAKE_C_COMPILER_VERSION},6>>:-Wduplicated-cond -Wnull-dereference >)
# Make optional some flags not supported with GCC < 13
list(APPEND S2OPC_COMPILER_FLAGS $<$<AND:${IS_GNU},$<VERSION_GREATER:${CMAKE_C_COMPILER_VERSION},13>>:-Wenum-int-mismatch -Wbidi-chars=any -Warray-compare>)
# Add security hardening compilation options
option(SECURITY_HARDENING "Harden compilation options" OFF)
if (SECURITY_HARDENING)
list(APPEND S2OPC_COMPILER_FLAGS $<$<AND:${IS_GNU},$<NOT:${IS_MINGW}>>:-Wimplicit-fallthrough -Wl,-z,nodlopen -Wl,-z,noexecstack -fcf-protection=full -fstack-clash-protection -fstack-protector-strong -Wl,-z,relro -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions>)
# Add some security hardening flags not supported with GCC < 13
list(APPEND S2OPC_COMPILER_FLAGS $<$<AND:${IS_GNU},$<VERSION_GREATER:${CMAKE_C_COMPILER_VERSION},13>>:-fharden-compares -fharden-conditional-branches -fstrict-flex-arrays=3 -ftrivial-auto-var-init=zero>)
# Set GNU definitions for security hardening
if (DEFINED IS_GNU AND ${CMAKE_C_COMPILER_VERSION} VERSION_GREATER "13")
# Set GNU definitions for security hardening not supported with GCC < 13
list(APPEND S2OPC_DEFINITIONS $<${IS_GNU}:_FORTIFY_SOURCE=3 _GLIBCXX_ASSERTIONS>)
else()
list(APPEND S2OPC_DEFINITIONS $<${IS_GNU}:_FORTIFY_SOURCE=2 _GLIBCXX_ASSERTIONS>)
endif()
# Force symbol stripping (only available for GNU compatible compilers)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:-s>)
list(APPEND S2OPC_LINKER_FLAGS $<${IS_GNU}:-s>)
set(CMAKE_SKIP_RPATH TRUE)
endif()
# Set GNU linker flags
list(APPEND S2OPC_LINKER_FLAGS $<$<AND:${IS_GNU},$<NOT:${IS_MINGW}>>:-Wl,-z,relro,-z,now>)
# If PIE explicitly requested, activate it for binaries linking
option(POSITION_INDEPENDENT_EXECUTABLE "Build position independent executable (-pie) which is a security good practice, but requires dependencies to be compiled with position independent code (-fPIC)" OFF)
if (POSITION_INDEPENDENT_EXECUTABLE)
if(${CMAKE_VERSION} VERSION_LESS "3.14")
# necessary to build binaries as PIE (see CMake CMP0083 / CMake issue #14983)
if (DEFINED IS_GNU AND NOT DEFINED MINGW)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
endif()
else()
cmake_policy(SET CMP0083 NEW)
include(CheckPIESupported)
check_pie_supported()
# it will then be automatically activated due to POSITION_INDEPENDENT_CODE property which is set for S2OPC common library
endif()
endif()
# Set Clang compiler flags
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_CLANG}:-std=c99 -pedantic -fstack-protector -Wall -Wextra -Wunreachable-code -fexceptions>)
# Add security hardening compilation options
if (SECURITY_HARDENING)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_CLANG}:-mspeculative-load-hardening>)
# Set Clang definitions
list(APPEND S2OPC_DEFINITIONS $<${IS_CLANG}:_FORTIFY_SOURCE=2>)
endif()
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_CLANG}:$<${IS_WARNINGS_AS_ERRORS}:-Werror>>)
# Specific flags for CERT rules
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_CLANG}:-Wunicode -Wimplicit-int -Wreserved-id-macro -Wsometimes-uninitialized -Wunsequenced -Wincompatible-pointer-types-discards-qualifiers -Wunevaluated-expression -Wparentheses -Wint-conversion -Wint-to-pointer-cast -Wincompatible-pointer-types -Wvla -Wconversion>)
# Special compilation flag (for GCC + Clang) for CycloneCRYPTO
if(S2OPC_CRYPTO_CYCLONE)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:-D__error_t_defined>)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_CLANG}:-D__error_t_defined>)
endif()
# Set MSVC compiler flags
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_MSVC}:/W3 /Zi /sdl>)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_MSVC}:$<${IS_WARNINGS_AS_ERRORS}:/WX>>)
# Set MSVC definitions (lean_and_mean avoid issue on order of import of Windows.h and Winsock2.h)
# TODO: nor COMPILE_FLAGS, COMPILE_DEFINITIONS or use of ${IS_MSCV} works, to be investigated
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
add_definitions(/DWIN32_LEAN_AND_MEAN)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
endif()
# Add flags when MINGW compiler (IS_GNU is also valid for MINGW)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_MINGW}: -Wno-pedantic-ms-format>)
# Always link MINGW libc statically (even in case of shared library): avoid dependency on external libgcc library
list(APPEND S2OPC_LINKER_FLAGS $<${IS_MINGW}:-static-libgcc>)
# Add -fno-omit-frame-pointer when build type is RelWithDebInfo or Debug
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:$<$<STREQUAL:"${CMAKE_BUILD_TYPE}","RelWithDebInfo">:-fno-omit-frame-pointer>>)
list(APPEND S2OPC_COMPILER_FLAGS $<${IS_GNU}:$<$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">:-fno-omit-frame-pointer>>)
# TODO: avoid modifying CMAKE_CFLAGS_* variables ? create new CMAKE_CONFIGURATION_TYPES equivalent to the 2 following but without DNDEBUG ?
# Re-enable asserts for Release and RelWithDebInfo builds
string(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
string(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO})
### Manage options for S2OPC compilation ###
# compilation options for S2OPC library code analysis purpose (mutually exclusive options)
option(WITH_ASAN "build with ASAN/LSAN" OFF) # address sanitizer / leak sanitizer
option(WITH_TSAN "build with TSAN" OFF) # thread sanitizer
option(WITH_UBSAN "build with UBSAN" OFF) # undefined behavior sanitizer
option(WITH_COVERAGE "build with COVERAGE" OFF) # code coverage
option(WITH_COVERITY "set this flag when built with coverity" OFF) # indicates build for coverity: no incompatible with others WITH_* options
option(WITH_GPERF_PROFILER "link against the gperftool profiler") # activates link against gperf
option(WITH_CLANG_SOURCE_COVERAGE "build with Clang source coverage" OFF)
# S2OPC library extension option (also mutually exclusive with above options)
option(WITH_OSS_FUZZ "Add the fuzzers target when building for OSS-Fuzz" OFF)
option(WITH_PYS2OPC "Also builds PyS2OPC" OFF)
# S2OPC client/server library scope option
option(S2OPC_NANO_PROFILE "Use Nano profile only (limited scope of OPC UA services)" OFF)
option(S2OPC_NODE_MANAGEMENT "Make NodeManagement service set available to clients" OFF)
option(S2OPC_EVENT_MANAGEMENT "Make OPC UA Events available" OFF)
# option to load static security data for embedded systems without filesystems
option(WITH_STATIC_SECURITY_DATA "Use static security data" OFF)
# option to put non-writeable data in const part of the memory
option(WITH_CONST_ADDSPACE "Generate an address space where non writeable attributes are const" OFF)
option(WITH_NO_ASSERT "Disable asserts" OFF)
option(WITH_USER_ASSERT "Enable user-defined failed assertion event" OFF)
option(WITH_MINIMAL_FOOTPRINT "Limit software footprint" OFF)
# option to enable GCC static analyser. The value from 1 to 5 corresponds to the verbosity level.
option(WITH_GCC_STATIC_ANALYSIS "activate GCC static analysis during compilation" OFF)
# Check project and option(s) are compatible
# Function to check only one option (option name provided) is activated for all calls to this function
function(check_mutually_exclusive_options options_names)
foreach(option_name IN LISTS options_names)
if(${${option_name}}) # Check variable of the option_name is defined
message("-- ${option_name} S2OPC option set")
set(OPTIONS_SET TRUE)
endif()
endforeach()
if(${OPTIONS_SET})
if(NOT WITH_OPTION_MUTUALLY_EXCLUSIVE) # Check no other option was recorded before
set(WITH_OPTION_MUTUALLY_EXCLUSIVE ${options_names} PARENT_SCOPE)
else()
message(FATAL_ERROR "${options_names} option(s) set with mutually exclusive option ${WITH_OPTION_MUTUALLY_EXCLUSIVE}")
endif()
endif()
endfunction()
# Function to check no mutually exclusive option is set if given option is active
function(check_no_compilation_option option_name)
if(${${option_name}}) # Check variable of the option_name is defined
if(NOT WITH_OPTION_MUTUALLY_EXCLUSIVE) # Check no compilation option was recorded before
message("-- ${option_name} S2OPC option set")
else()
message(FATAL_ERROR "${option_name} option set with incompatible compilation option ${WITH_OPTION_MUTUALLY_EXCLUSIVE}")
endif()
endif()
endfunction()
# Function to check given option is not active
function(check_not_activated_option option_name reason)
if(${${option_name}}) # Check variable of the option_name is defined
message(FATAL_ERROR "${option_name} incompatible option set: ${reason}")
endif()
endfunction()
# Function to check build mode is debug
function(check_debug_build_type option_name reason)
if(${${option_name}})
if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo" AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(FATAL_ERROR "${option_name} requires Debug or RelWithDebInfo build type (found: '${CMAKE_BUILD_TYPE}'): ${reason}")
endif()
endif()
endfunction()
function(print_if_activated option_name)
if(${${option_name}})
message("-- ${option_name} S2OPC option set")
endif()
endfunction()
# Check for incompatible options activated
check_mutually_exclusive_options("WITH_ASAN;WITH_UBSAN")
check_mutually_exclusive_options("WITH_TSAN")
check_mutually_exclusive_options("WITH_COVERAGE")
check_mutually_exclusive_options("WITH_COVERITY")
check_mutually_exclusive_options("WITH_GPERF_PROFILER")
check_mutually_exclusive_options("WITH_CLANG_SOURCE_COVERAGE")
check_no_compilation_option("WITH_OSS_FUZZ")
check_no_compilation_option("WITH_PYS2OPC")
if(NOT UNIX)
check_not_activated_option("WITH_ASAN" "not a unix system")
check_not_activated_option("WITH_TSAN" "not a unix system")
check_not_activated_option("WITH_UBSAN" "not a unix system")
check_not_activated_option("WITH_COVERAGE" "not a unix system")
check_not_activated_option("WITH_COVERITY" "not a unix system")
check_not_activated_option("WITH_GPERF_PROFILER" "not a unix system")
check_not_activated_option("WITH_CLANG_SOURCE_COVERAGE" "not a unix system")
check_not_activated_option("WITH_GCC_STATIC_ANALYSIS" "not a unix system")
endif()
check_debug_build_type("WITH_ASAN" "to set compilation flag '-fno-omit-frame-pointer'")
check_debug_build_type("WITH_TSAN" "to set compilation flag '-fno-omit-frame-pointer'")
check_debug_build_type("WITH_UBSAN" "to set compilation flag '-fno-omit-frame-pointer'")
# print options with no incompatibility
print_if_activated("S2OPC_NANO_PROFILE")
print_if_activated("S2OPC_NODE_MANAGEMENT")
print_if_activated("S2OPC_EVENT_MANAGEMENT")
print_if_activated("WITH_CONST_ADDSPACE")
print_if_activated("WITH_STATIC_SECURITY_DATA")
print_if_activated("SECURITY_HARDENING")
# Check specific options constraints and set necessary compilation flags
# check assertion redirection
print_if_activated("WITH_NO_ASSERT")
print_if_activated("WITH_USER_ASSERT")
print_if_activated("WITH_MINIMAL_FOOTPRINT")
if(WITH_NO_ASSERT)
if (WITH_USER_ASSERT)
message(FATAL_ERROR "WITH_USER_ASSERT incompatible option along with WITH_NO_ASSERT")
endif()
list(APPEND S2OPC_COMPILER_FLAGS -DWITH_NO_ASSERT)
elseif(WITH_USER_ASSERT)
list(APPEND S2OPC_COMPILER_FLAGS -DWITH_USER_ASSERT)
endif()
if(WITH_MINIMAL_FOOTPRINT)
list(APPEND S2OPC_COMPILER_FLAGS -DWITH_MINIMAL_FOOTPRINT)
endif()
# Display remaining configuration flags
print_if_activated("PUBSUB_STATIC_CONFIG")
# check if compiler support new sanitization options
include(CheckCCompilerFlag)
set(CMAKE_REQUIRED_LIBRARIES "-fsanitize=address")
CHECK_C_COMPILER_FLAG("-fsanitize=address -fsanitize=pointer-compare" COMPILER_SUPPORTS_SAN_PC)
CHECK_C_COMPILER_FLAG("-fsanitize=address -fsanitize=pointer-subtract" COMPILER_SUPPORTS_SAN_PS)
unset(CMAKE_REQUIRED_LIBRARIES)
if(WITH_ASAN)
list(APPEND S2OPC_COMPILER_FLAGS -fsanitize=address)
list(APPEND S2OPC_LINKER_FLAGS -fsanitize=address)
list(APPEND S2OPC_LINKER_FLAGS -fsanitize=leak)
list(APPEND S2OPC_LINKER_FLAGS $<${IS_GNU}:-static-libasan>)
if(COMPILER_SUPPORTS_SAN_PC)
list(APPEND S2OPC_COMPILER_FLAGS -fsanitize=pointer-compare)
list(APPEND S2OPC_LINKER_FLAGS -fsanitize=pointer-compare)
endif()
if(COMPILER_SUPPORTS_SAN_PS)
list(APPEND S2OPC_COMPILER_FLAGS -fsanitize=pointer-subtract)
list(APPEND S2OPC_LINKER_FLAGS -fsanitize=pointer-subtract)
endif()
endif()
if(WITH_TSAN)
list(APPEND S2OPC_COMPILER_FLAGS -fsanitize=thread)
list(APPEND S2OPC_LINKER_FLAGS -fsanitize=thread -pie)
list(APPEND S2OPC_LINKER_FLAGS $<${IS_GNU}:-static-libtsan>)
endif()
if(WITH_UBSAN)
list(APPEND S2OPC_DEFINITIONS ROCKSDB_UBSAN_RUN)
list(APPEND S2OPC_COMPILER_FLAGS -fsanitize=undefined)
list(APPEND S2OPC_LINKER_FLAGS -fsanitize=undefined)
list(APPEND S2OPC_LINKER_FLAGS $<${IS_GNU}:-static-libubsan>)
endif()
if(WITH_COVERAGE)
list(APPEND S2OPC_COMPILER_FLAGS --coverage)
list(APPEND S2OPC_LINK_LIBRARIES gcov)
endif()
if(WITH_GPERF_PROFILER)
find_library(GPERF_PROFILER profiler)
if (NOT GPERF_PROFILER)
message(FATAL_ERROR "Could not find libprofiler")
endif()
list(APPPEND S2OPC_LINK_LIBRARIES profiler)
endif()
if(WITH_CLANG_SOURCE_COVERAGE)
if (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
message(FATAL_ERROR "Clang compiler is required to enable Clang source coverage")
endif()
list(APPEND S2OPC_COMPILER_FLAGS -fprofile-instr-generate -fcoverage-mapping)
list(APPEND S2OPC_LINKER_FLAGS -fprofile-instr-generate -fcoverage-mapping)
endif()
if(WITH_GCC_STATIC_ANALYSIS)
if (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
message(FATAL_ERROR "GCC compiler is required to enable GCC Static Analysis")
endif()
message("-- GCC Static Analysis activated")
list(APPEND S2OPC_COMPILER_FLAGS -fanalyzer -fanalyzer-verbosity=${WITH_GCC_STATIC_ANALYSIS})
endif()
# Add S2OPC_NANO_PROFILE to compilation definition if option activated
# Note: definition is necessary to build PyS2OPC
list(APPEND S2OPC_DEFINITIONS $<$<BOOL:${S2OPC_NANO_PROFILE}>:S2OPC_NANO_PROFILE>)
# Add S2OPC_NODE_MANAGEMENT to compilation definition if option activated
list(APPEND S2OPC_DEFINITIONS $<$<BOOL:${S2OPC_NODE_MANAGEMENT}>:S2OPC_NODE_MANAGEMENT>)
# Add S2OPC_EVENT_MANAGEMENT to compilation definition if option activated
list(APPEND S2OPC_DEFINITIONS $<$<BOOL:${S2OPC_EVENT_MANAGEMENT}>:S2OPC_EVENT_MANAGEMENT>)
### Define common functions ###
# Function to generate build info C structure and function
function(s2opc_gen_build_info c_model_source_path c_file_target_path)
if(CMAKE_HOST_UNIX)
add_custom_command(OUTPUT ${c_file_target_path}
COMMAND ${CMAKE_COMMAND} -E copy ${c_model_source_path} ${c_file_target_path}
COMMAND ${S2OPC_ROOT_PATH}/scripts/gen_build_info_file.sh ${c_file_target_path}
WORKING_DIRECTORY ${S2OPC_ROOT_PATH})
else()
add_custom_command(OUTPUT ${c_file_target_path}
COMMAND ${CMAKE_COMMAND} -E copy ${c_model_source_path} ${c_file_target_path}
WORKING_DIRECTORY ${S2OPC_ROOT_PATH})
endif()
set_source_files_properties(${c_file_target_path} PROPERTIES GENERATED TRUE)
endfunction()
if ((NOT S2OPC_CRYPTO_CYCLONE) AND (NOT S2OPC_CRYPTO_MBEDTLS))
list(APPEND S2OPC_DEFINITIONS "WITH_NO_CRYPTO")
endif()
# Function to generate a C structure address space from an XML UA nodeset file to be loaded by embedded loader
function(s2opc_embed_address_space c_file_name xml_uanodeset_path)
if(WITH_CONST_ADDSPACE)
set(const_addspace "--const_addspace")
endif()
add_custom_command(
OUTPUT ${c_file_name}
DEPENDS ${xml_uanodeset_path}
COMMAND ${PYTHON_EXECUTABLE} ${S2OPC_ROOT_PATH}/scripts/generate-s2opc-address-space.py ${xml_uanodeset_path} ${c_file_name} ${const_addspace}
COMMENT "Generating address space ${c_file_name}"
VERBATIM
)
set_source_files_properties(${c_file_name} PROPERTIES GENERATED TRUE)
if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
set_source_files_properties(${c_file_name} PROPERTIES COMPILE_FLAGS -Wno-missing-field-initializers)
endif()
endfunction()
# Function that generates the expanded include required by CFFI to compile PyS2OPC
function(s2opc_expand_header h_input context_targets h_expanded)
# Note: this function may seem overkill, as there are only a few PyS2OPC headers.
# It was the basis of tests to avoid manual maintenance of the PyS2OPC's headers, required by CFFI.
# CFFI is based on pycparser, and their combined purposes make this clearly and intentionally unfeasible.
# pycparser does not do preprocessing work and does not support all tweaks that may reside in the standard library headers.
# It results that it can parse C with tweaks, such as using fake stdlib headers.
# However CFFI uses pycparser to obtain real types and generate some C afterwards with them.
# This makes it clear that we cannot fake types of the stdlib
# (otherwise, there are be conflicting types definitions at compile time).
# To conclude, we shall only use CFFI on headers that don't rely on the libc,
# except for the types it already knows: [u]int(8|16|32|64)_t.
# (Even bool is not supported and its support in our headers should be platform-dependent)
# Evaluate properties of target to get the ;-list, and produce the '-I;'-list,
# that will be expanded as MULTIPLE ARGUMENTS thanks to the COMMAND_EXPAND_LISTS
foreach(_context_target IN LISTS context_targets)
set(_expand_eval_includes "$<TARGET_PROPERTY:${_context_target},INCLUDE_DIRECTORIES>")
list(APPEND _expand_includes "$<$<BOOL:${_expand_eval_includes}>:-I$<JOIN:${_expand_eval_includes},\;-I>>")
# Same for defines
set(_expand_eval_defines "$<TARGET_PROPERTY:${_context_target},COMPILE_DEFINITIONS>")
list(APPEND _expand_defines "$<$<BOOL:${_expand_eval_defines}>:-D$<JOIN:${_expand_eval_defines},\;-D>>")
list(APPEND _expand_defines_flags "${_expand_eval_defines}")
endforeach(_context_target)
# Note: the $<BOOL> evaluation never returns FALSE when variable is empty which lead to empty flag issue (-D ).
# Add an additional definition to avoid this possible case.
list(APPEND _expand_defines_flags "S2OPC_NON_EMPTY_DEF")
set(_expand_defines_flags "$<$<BOOL:${_expand_defines_flags}>:-D$<JOIN:${_expand_defines_flags}, -D>>")
# On Windows '-o' is deprecated, use equivalent option.
if(WIN32 AND NOT MINGW)
set(_output_switches /P /Fi${h_expanded})
else()
set(_output_switches -o ${h_expanded})
endif()
add_custom_command(DEPENDS ${h_input}
OUTPUT ${h_expanded}
COMMAND ${CMAKE_C_COMPILER} ${_expand_includes}
"${_expand_defines_flags}"
-DS2OPC_PYEXPANSION
-E ${h_input} ${_output_switches}
COMMENT "Expending header file to ${h_expanded}"
VERBATIM
COMMAND_EXPAND_LISTS
)
endfunction()
## S2OPC fuzzing tests: to be run manually ##
# options with impact on the dependencies
option(ENABLE_FUZZING "Build the S2OPC fuzzers" OFF)
# Enable fuzzing if WITH_OSS_FUZZ is ON
if(WITH_OSS_FUZZ AND NOT ENABLE_FUZZING)
message(FATAL_ERROR "'WITH_OSS_FUZZ' needs 'ENABLE_FUZZING'. Check that you have enabled it, or remove 'WITH_OSS_FUZZ'")
endif()
if(ENABLE_FUZZING)
if (NOT WITH_OSS_FUZZ)
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
if (${CMAKE_C_COMPILER_VERSION} VERSION_LESS "6.0.0")
# We need at least CLang 6 to get LibFuzzer
message(FATAL_ERROR "Your version of Clang (${CMAKE_C_COMPILER_VERSION}) is not recent enough to have LibFuzzer. You need at leats 6.0.0")
else()
# Local fuzzing
function(s2opc_fuzzer fuzz_target_name src_file library includes)
add_executable(${fuzz_target_name} "${src_file}")
set_target_properties(${fuzz_target_name} PROPERTIES COMPILE_FLAGS "-fsanitize=fuzzer")
set_target_properties(${fuzz_target_name} PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
target_link_libraries(${fuzz_target_name} ${library})
target_include_directories(${fuzz_target_name} PRIVATE ${includes})
add_dependencies(fuzzers ${fuzz_target_name})
endfunction()
endif()
else()
# Clang is needed to get LibFuzzer
message(FATAL_ERROR "Clang is needed to have LibFuzzer. You have ${CMAKE_C_COMPILER_ID}.")
endif()
else()
# OSS Fuzzing
function(s2opc_fuzzer fuzz_target_name src_file library includes)
add_executable(${fuzz_target_name} "${src_file}")
target_link_libraries(${fuzz_target_name} "${library}" $ENV{LIB_FUZZING_ENGINE})
target_include_directories(${fuzz_target_name} PRIVATE ${includes})
add_dependencies(fuzzers ${fuzz_target_name})
endfunction()
endif()
add_custom_target(fuzzers)
endif(ENABLE_FUZZING)