-
Notifications
You must be signed in to change notification settings - Fork 768
/
Copy pathhelpers.cmake
262 lines (229 loc) · 9.47 KB
/
helpers.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
# Copyright (C) 2023-2024 Intel Corporation
# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
# See LICENSE.TXT
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# helpers.cmake -- helper functions for top-level CMakeLists.txt
#
# Sets ${ret} to version of program specified by ${name} in major.minor format
function(get_program_version_major_minor name ret)
execute_process(COMMAND ${name} --version
OUTPUT_VARIABLE cmd_ret
ERROR_QUIET)
STRING(REGEX MATCH "([0-9]+)\.([0-9]+)" VERSION "${cmd_ret}")
SET(${ret} ${VERSION} PARENT_SCOPE)
endfunction()
# Generates cppformat-$name targets and attaches them
# as dependencies of global "cppformat" target.
# Arguments are used as files to be checked.
# ${name} must be unique.
function(add_cppformat name)
if(NOT CLANG_FORMAT OR NOT (CLANG_FORMAT_VERSION VERSION_EQUAL CLANG_FORMAT_REQUIRED))
return()
endif()
if(${ARGC} EQUAL 0)
return()
else()
# Split args into 2 parts (in Windows the list is probably too long)
list(SUBLIST ARGN 0 250 selected_files_1)
list(SUBLIST ARGN 250 -1 selected_files_2)
add_custom_target(cppformat-${name}
COMMAND ${CLANG_FORMAT} --style=file --i ${selected_files_1}
COMMAND ${CLANG_FORMAT} --style=file --i ${selected_files_2}
COMMENT "Format CXX source files"
)
endif()
add_dependencies(cppformat cppformat-${name})
endfunction()
include(CheckCXXCompilerFlag)
macro(add_sanitizer_flag flag)
set(SAVED_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} -fsanitize=${flag}")
check_cxx_compiler_flag("-fsanitize=${flag}" CXX_HAS_SANITIZER)
if(CXX_HAS_SANITIZER)
add_compile_options(-fsanitize=${flag})
add_link_options(-fsanitize=${flag})
else()
message("${flag} sanitizer not supported")
endif()
set(CMAKE_REQUIRED_LIBRARIES ${SAVED_CMAKE_REQUIRED_LIBRARIES})
endmacro()
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
check_cxx_compiler_flag("-fcf-protection=full" CXX_HAS_FCF_PROTECTION_FULL)
check_cxx_compiler_flag("-fstack-clash-protection" CXX_HAS_FSTACK_CLASH_PROTECTION)
endif()
if (UR_USE_CFI AND UR_USE_ASAN)
message(WARNING "Both UR_USE_CFI and UR_USE_ASAN are ON. "
"Due to build errors, this is unsupported; CFI checks will be disabled")
set(UR_USE_CFI OFF)
endif()
if (UR_USE_CFI)
set(SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-flto -fvisibility=hidden")
check_cxx_compiler_flag("-fsanitize=cfi" CXX_HAS_CFI_SANITIZE)
set(CMAKE_REQUIRED_FLAGS ${SAVED_CMAKE_REQUIRED_FLAGS})
else()
# If CFI checking is disabled, pretend we don't support it
set(CXX_HAS_CFI_SANITIZE OFF)
endif()
set(CFI_FLAGS "")
if (CXX_HAS_CFI_SANITIZE)
# cfi-icall requires called functions in shared libraries to also be built with cfi-icall, which we can't
# guarantee. -fsanitize=cfi depends on -flto
set(CFI_FLAGS "-flto;-fsanitize=cfi;-fno-sanitize=cfi-icall;-fsanitize-ignorelist=${PROJECT_SOURCE_DIR}/sanitizer-ignorelist.txt")
endif()
function(add_ur_target_compile_options name)
if(NOT MSVC)
target_compile_definitions(${name} PRIVATE -D_FORTIFY_SOURCE=2)
target_compile_options(${name} PRIVATE
# Warning options
-Wall
-Wpedantic
-Wempty-body
-Wformat
-Wformat-security
-Wunused-parameter
# Hardening options
-fstack-protector-strong
-fvisibility=hidden
${CFI_FLAGS}
$<$<BOOL:${CXX_HAS_FCF_PROTECTION_FULL}>:-fcf-protection=full>
$<$<BOOL:${CXX_HAS_FSTACK_CLASH_PROTECTION}>:-fstack-clash-protection>
# Colored output
$<$<CXX_COMPILER_ID:GNU>:-fdiagnostics-color=always>
$<$<CXX_COMPILER_ID:Clang,AppleClang>:-fcolor-diagnostics>
)
if (UR_DEVELOPER_MODE)
target_compile_options(${name} PRIVATE -Werror -Wextra)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_options(${name} PRIVATE -fvisibility=hidden)
endif()
elseif(MSVC)
target_compile_options(${name} PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/MP> # clang-cl.exe does not support /MP
/MD$<$<CONFIG:Debug>:d>
/W3
/GS # Enable: Buffer security check
/Gy # Enable: Function-level linking
$<$<CONFIG:Release>:/sdl> # Enable: Additional SDL checks
$<$<CXX_COMPILER_ID:MSVC>:/Qspectre> # Enable: Mitigate Spectre variant 1 vulnerabilities
/wd4267 # Disable: 'var' : conversion from 'size_t' to 'type', possible loss of data
/wd6244 # Disable: local declaration of 'variable' hides previous declaration
/wd6246 # Disable: local declaration of 'variable' hides declaration of same name in outer scope
)
target_compile_definitions(${name} PRIVATE
WIN32_LEAN_AND_MEAN NOMINMAX # Cajole Windows.h to define fewer symbols
_CRT_SECURE_NO_WARNINGS # Slience warnings about getenv
)
if(UR_DEVELOPER_MODE)
target_compile_options(${name} PRIVATE
/WX # Enable: Treat all warnings as errors
)
endif()
endif()
endfunction()
function(add_ur_target_link_options name)
if(NOT MSVC)
if (NOT APPLE)
target_link_options(${name} PRIVATE
${CFI_FLAGS}
"LINKER:-z,relro,-z,now,-z,noexecstack"
)
if (UR_DEVELOPER_MODE)
target_link_options(${name} PRIVATE -Werror -Wextra)
endif()
endif()
elseif(MSVC)
target_link_options(${name} PRIVATE
LINKER:/DYNAMICBASE # Enable: Modify header to indicate ASLR should be use
LINKER:/HIGHENTROPYVA # Enable: High-entropy address space layout randomization (ASLR)
$<$<CONFIG:Release>:
LINKER:/NXCOMPAT # Enable: Data Execution Prevention
LINKER:/LTCG # Enable: Link-time code generation
>
)
endif()
endfunction()
function(add_ur_target_exec_options name)
if(MSVC)
target_link_options(${name} PRIVATE
LINKER:/ALLOWISOLATION
)
endif()
endfunction()
function(add_ur_executable name)
add_executable(${name} ${ARGN})
add_ur_target_compile_options(${name})
add_ur_target_exec_options(${name})
add_ur_target_link_options(${name})
if(UR_EXTERNAL_DEPENDENCIES)
add_dependencies(${name} ${UR_EXTERNAL_DEPENDENCIES})
endif()
endfunction()
function(add_ur_library name)
add_library(${name} ${ARGN})
add_ur_target_compile_options(${name})
add_ur_target_link_options(${name})
if(MSVC)
target_link_options(${name} PRIVATE
$<$<STREQUAL:$<TARGET_LINKER_FILE_NAME:${name}>,link.exe>:LINKER:/DEPENDENTLOADFLAG:0x2000>
)
endif()
if(UR_USE_DEBUG_POSTFIX)
set_target_properties(${name} PROPERTIES DEBUG_POSTFIX d)
endif()
if(UR_EXTERNAL_DEPENDENCIES)
add_dependencies(${name} ${UR_EXTERNAL_DEPENDENCIES})
endif()
add_dependencies(unified-runtime-libraries ${name})
endfunction()
if(NOT TARGET unified-runtime-libraries)
add_custom_target(unified-runtime-libraries)
endif()
function(install_ur_library name)
install(TARGETS ${name}
COMPONENT unified-runtime
EXPORT ${PROJECT_NAME}-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endfunction()
if(NOT TARGET install-unified-runtime-libraries)
add_custom_target(install-unified-runtime-libraries
COMMAND ${CMAKE_COMMAND}
-DCOMPONENT=unified-runtime
-P ${CMAKE_BINARY_DIR}/cmake_install.cmake
# TODO: Also install debug UMF runtime libraries component
DEPENDS unified-runtime-libraries
# TODO: Add dependency on building debug UMF libraries
)
endif()
include(FetchContent)
function(FetchSource GIT_REPOSITORY GIT_TAG GIT_DIR DEST)
message(STATUS "Fetching sparse source ${GIT_DIR} from ${GIT_REPOSITORY} ${GIT_TAG}")
IF(NOT EXISTS ${DEST})
file(MAKE_DIRECTORY ${DEST})
execute_process(COMMAND git init
WORKING_DIRECTORY ${DEST})
execute_process(COMMAND git checkout -b main
WORKING_DIRECTORY ${DEST})
execute_process(COMMAND git remote add origin ${GIT_REPOSITORY}
WORKING_DIRECTORY ${DEST})
execute_process(COMMAND git config core.sparsecheckout true
WORKING_DIRECTORY ${DEST})
file(APPEND ${DEST}/.git/info/sparse-checkout ${GIT_DIR}/)
endif()
execute_process(COMMAND git fetch --depth=1 origin refs/tags/${GIT_TAG}:refs/tags/${GIT_TAG}
WORKING_DIRECTORY ${DEST})
execute_process(COMMAND git checkout --quiet ${GIT_TAG}
WORKING_DIRECTORY ${DEST})
endfunction()
# A wrapper around FetchContent_Declare that supports git sparse checkout.
# This is useful for including subprojects from large repositories.
function(FetchContentSparse_Declare name GIT_REPOSITORY GIT_TAG GIT_DIR)
set(content-build-dir ${CMAKE_BINARY_DIR}/content-${name})
FetchSource(${GIT_REPOSITORY} ${GIT_TAG} ${GIT_DIR} ${content-build-dir})
FetchContent_Declare(${name} SOURCE_DIR ${content-build-dir}/${GIT_DIR})
endfunction()