-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
189 lines (160 loc) · 6.62 KB
/
CMakeLists.txt
File metadata and controls
189 lines (160 loc) · 6.62 KB
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
cmake_minimum_required(VERSION 3.13)
project(randompp
VERSION 1.0.0
LANGUAGES CXX
)
# Detect whether randompp is the top-level project or being consumed via
# add_subdirectory()/FetchContent. PROJECT_IS_TOP_LEVEL is 3.21+, so compute
# it manually.
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(RANDOMPP_IS_TOP_LEVEL ON)
else()
set(RANDOMPP_IS_TOP_LEVEL OFF)
endif()
if(RANDOMPP_IS_TOP_LEVEL AND NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
# ---------------------------------------------------------------------------
# Hardening flags (PRIVATE — never leak to consumers)
# ---------------------------------------------------------------------------
function(randompp_apply_hardening target)
target_compile_options(${target} PRIVATE
$<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:
-fstack-protector-strong
-Wformat
-Wformat-security
>
$<$<CXX_COMPILER_ID:GNU>:
-fstack-clash-protection
-fcf-protection
>
$<$<CXX_COMPILER_ID:MSVC>:
/GS
/guard:cf
>
)
# _FORTIFY_SOURCE requires optimisation; skip in Debug to avoid warnings.
# Undef first to avoid -Wmacro-redefined on toolchains that set it by default.
target_compile_options(${target} PRIVATE
$<$<AND:$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>,$<NOT:$<CONFIG:Debug>>>:
-U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=2
>
)
set_target_properties(${target} PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_options(${target} PRIVATE
$<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:
-Wl,-z,relro,-z,now
-Wl,-z,noexecstack
>
)
endif()
endfunction()
# ---------------------------------------------------------------------------
# randompp_enable_sanitizers_if_requested(<target>)
#
# When RANDOMPP_ENABLE_SANITIZERS=ON, apply -fsanitize=address,undefined to
# the target's compile AND link flags (PRIVATE — the randompp library itself
# is never instrumented this way, so downstream consumers never inherit
# sanitizer flags). Callers gate this behind RANDOMPP_BUILD_TESTS /
# RANDOMPP_BUILD_FUZZERS so only test and fuzz binaries get instrumented.
#
# No-op on:
# - MSVC: /fsanitize=address + /MD CRT mismatch requires a custom path we
# don't want to bake in blindly (see the abandoned MSVC ASan attempt in
# session history).
# - AppleClang: ships ASan but not libFuzzer, and our nightly fuzz runs
# on Linux Clang anyway.
# - MinGW: libasan runtime packaging is inconsistent across mingw-w64
# distributions. The Linux cell is the authoritative sanitizer run.
# ---------------------------------------------------------------------------
option(RANDOMPP_ENABLE_SANITIZERS "Enable -fsanitize=address,undefined on randompp test/fuzz binaries" OFF)
function(randompp_enable_sanitizers_if_requested target)
if(NOT RANDOMPP_ENABLE_SANITIZERS)
return()
endif()
if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
message(STATUS "RANDOMPP_ENABLE_SANITIZERS requested but ignored for ${target} (compiler=${CMAKE_CXX_COMPILER_ID})")
return()
endif()
if(MINGW OR APPLE)
return()
endif()
target_compile_options(${target} PRIVATE
-fsanitize=address
-fsanitize=undefined
-fno-omit-frame-pointer
)
target_link_options(${target} PRIVATE
-fsanitize=address
-fsanitize=undefined
)
endfunction()
add_library(${PROJECT_NAME} STATIC src/randompp.cpp)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
SYSTEM INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE bcrypt)
endif()
randompp_apply_hardening(${PROJECT_NAME})
# ---------------------------------------------------------------------------
# Tests (opt-in via -DRANDOMPP_BUILD_TESTS=ON; only when top-level)
# ---------------------------------------------------------------------------
option(RANDOMPP_BUILD_TESTS "Build randompp unit tests" OFF)
if(RANDOMPP_IS_TOP_LEVEL AND RANDOMPP_BUILD_TESTS)
enable_testing()
foreach(test_name test_random_bytes test_secure_erase test_random_bytes_extended test_secure_erase_extended)
add_executable(${test_name} tests/${test_name}.cpp)
target_link_libraries(${test_name} PRIVATE ${PROJECT_NAME})
set_target_properties(${test_name} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
randompp_apply_hardening(${test_name})
randompp_enable_sanitizers_if_requested(${test_name})
add_test(NAME ${test_name} COMMAND ${test_name})
endforeach()
endif()
# ---------------------------------------------------------------------------
# Fuzz targets (opt-in via -DRANDOMPP_BUILD_FUZZERS=ON, requires Clang; only when top-level)
# ---------------------------------------------------------------------------
option(RANDOMPP_BUILD_FUZZERS "Build randompp libFuzzer fuzz targets (Clang only)" OFF)
if(RANDOMPP_IS_TOP_LEVEL AND RANDOMPP_BUILD_FUZZERS)
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(FATAL_ERROR "RANDOMPP_BUILD_FUZZERS requires Clang (libFuzzer).")
endif()
# libFuzzer + ASan + UBSan on Windows/Clang trips lld-link's
# /failifmismatch RuntimeLibrary check — the sanitizer runtimes expect
# the static CRT while CMake defaults to the dynamic one. Rather than
# ship a half-broken build path, refuse cleanly on Windows.
if(WIN32)
message(FATAL_ERROR "RANDOMPP_BUILD_FUZZERS is not supported on Windows (use Linux/macOS Clang).")
endif()
foreach(fuzz_name fuzz_random_bytes fuzz_secure_erase)
add_executable(${fuzz_name} tests/${fuzz_name}.cpp)
target_link_libraries(${fuzz_name} PRIVATE ${PROJECT_NAME})
set_target_properties(${fuzz_name} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
target_compile_options(${fuzz_name} PRIVATE
-fsanitize=fuzzer,address,undefined
-fno-omit-frame-pointer
)
target_link_options(${fuzz_name} PRIVATE
-fsanitize=fuzzer,address,undefined
)
randompp_apply_hardening(${fuzz_name})
endforeach()
endif()