1# CMake build for CompilerRT.
2#
3# An important constraint of the build is that it only produces libraries
4# based on the ability of the host toolchain to target various platforms.
5
6cmake_minimum_required(VERSION 3.13.4)
7
8# Check if compiler-rt is built as a standalone project.
9if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR COMPILER_RT_STANDALONE_BUILD)
10  project(CompilerRT C CXX ASM)
11  set(COMPILER_RT_STANDALONE_BUILD TRUE)
12  set_property(GLOBAL PROPERTY USE_FOLDERS ON)
13endif()
14
15set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
16
17# Add path for custom compiler-rt modules.
18list(INSERT CMAKE_MODULE_PATH 0
19  "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
20  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
21  "${LLVM_COMMON_CMAKE_UTILS}"
22  "${LLVM_COMMON_CMAKE_UTILS}/Modules"
23  )
24
25if(CMAKE_CONFIGURATION_TYPES)
26  set(CMAKE_CFG_RESOLVED_INTDIR "${CMAKE_CFG_INTDIR}/")
27else()
28  set(CMAKE_CFG_RESOLVED_INTDIR "")
29endif()
30
31include(SetPlatformToolchainTools)
32include(base-config-ix)
33include(CompilerRTUtils)
34include(CMakeDependentOption)
35
36option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON)
37mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)
38option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON)
39mark_as_advanced(COMPILER_RT_BUILD_CRT)
40option(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY "Use eh_frame in crtbegin.o/crtend.o" ON)
41mark_as_advanced(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY)
42option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON)
43mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS)
44option(COMPILER_RT_BUILD_XRAY "Build xray" ON)
45mark_as_advanced(COMPILER_RT_BUILD_XRAY)
46option(COMPILER_RT_BUILD_LIBFUZZER "Build libFuzzer" ON)
47mark_as_advanced(COMPILER_RT_BUILD_LIBFUZZER)
48option(COMPILER_RT_BUILD_PROFILE "Build profile runtime" ON)
49mark_as_advanced(COMPILER_RT_BUILD_PROFILE)
50option(COMPILER_RT_BUILD_MEMPROF "Build memory profiling runtime" ON)
51mark_as_advanced(COMPILER_RT_BUILD_MEMPROF)
52option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" OFF)
53mark_as_advanced(COMPILER_RT_BUILD_XRAY_NO_PREINIT)
54option(COMPILER_RT_BUILD_ORC "Build ORC runtime" ON)
55mark_as_advanced(COMPILER_RT_BUILD_ORC)
56option(COMPILER_RT_BUILD_GWP_ASAN "Build GWP-ASan, and link it into SCUDO" ON)
57mark_as_advanced(COMPILER_RT_BUILD_GWP_ASAN)
58option(COMPILER_RT_ENABLE_CET "Build Compiler RT with CET enabled" OFF)
59
60if(FUCHSIA)
61  set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS_DEFAULT OFF)
62else()
63  set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS_DEFAULT ON)
64endif()
65set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS ${COMPILER_RT_HWASAN_WITH_INTERCEPTORS_DEFAULT} CACHE BOOL "Enable libc interceptors in HWASan (testing mode)")
66
67set(COMPILER_RT_BAREMETAL_BUILD OFF CACHE BOOL
68  "Build for a bare-metal target.")
69
70if (COMPILER_RT_STANDALONE_BUILD)
71  load_llvm_config()
72  if (TARGET intrinsics_gen)
73    # Loading the llvm config causes this target to be imported so place it
74    # under the appropriate folder in an IDE.
75    set_target_properties(intrinsics_gen PROPERTIES FOLDER "Compiler-RT Misc")
76  endif()
77
78  find_package(Python3 COMPONENTS Interpreter)
79  if(NOT Python3_Interpreter_FOUND)
80    message(WARNING "Python3 not found, using python2 as a fallback")
81    find_package(Python2 COMPONENTS Interpreter REQUIRED)
82    if(Python2_VERSION VERSION_LESS 2.7)
83      message(SEND_ERROR "Python 2.7 or newer is required")
84    endif()
85
86    # Treat python2 as python3
87    add_executable(Python3::Interpreter IMPORTED)
88    set_target_properties(Python3::Interpreter PROPERTIES
89      IMPORTED_LOCATION ${Python2_EXECUTABLE})
90    set(Python3_EXECUTABLE ${Python2_EXECUTABLE})
91  endif()
92
93  # Ensure that fat libraries are built correctly on Darwin
94  if(APPLE)
95    include(UseLibtool)
96  endif()
97
98  # Define default arguments to lit.
99  set(LIT_ARGS_DEFAULT "-sv")
100  if (MSVC OR XCODE)
101    set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
102  endif()
103  set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
104  set(LLVM_LIT_OUTPUT_DIR "${COMPILER_RT_EXEC_OUTPUT_DIR}")
105endif()
106
107construct_compiler_rt_default_triple()
108if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*hf$")
109  if (${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "^arm")
110    set(COMPILER_RT_DEFAULT_TARGET_ARCH "armhf")
111    CHECK_SYMBOL_EXISTS (__thumb__ "" COMPILER_RT_ARM_THUMB)
112  endif()
113endif()
114if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*")
115  set(ANDROID 1)
116  string(REGEX MATCH "-target(=| +)[^ ]+android[a-z]*([0-9]+)" ANDROID_API_LEVEL "${CMAKE_C_FLAGS}")
117  set(ANDROID_API_LEVEL ${CMAKE_MATCH_2})
118endif()
119pythonize_bool(ANDROID)
120
121set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
122set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
123
124pythonize_bool(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
125
126# We support running instrumented tests when we're not cross compiling
127# and target a UNIX-like system or Windows.
128# We can run tests on Android even when we are cross-compiling.
129if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID
130   OR COMPILER_RT_EMULATOR)
131  option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON)
132else()
133  option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF)
134endif()
135
136option(COMPILER_RT_DEBUG "Build runtimes with full debug info" OFF)
137option(COMPILER_RT_EXTERNALIZE_DEBUGINFO
138  "Generate dSYM files and strip executables and libraries (Darwin Only)" OFF)
139# COMPILER_RT_DEBUG_PYBOOL is used by lit.common.configured.in.
140pythonize_bool(COMPILER_RT_DEBUG)
141
142option(COMPILER_RT_INTERCEPT_LIBDISPATCH
143  "Support interception of libdispatch (GCD). Requires '-fblocks'" OFF)
144option(COMPILER_RT_LIBDISPATCH_INSTALL_PATH
145  "Specify if libdispatch is installed in a custom location" "")
146if (COMPILER_RT_INTERCEPT_LIBDISPATCH AND NOT APPLE)
147  set(COMPILER_RT_LIBDISPATCH_CFLAGS -fblocks)
148  set(COMPILER_RT_TEST_LIBDISPATCH_CFLAGS)
149  if (COMPILER_RT_LIBDISPATCH_INSTALL_PATH)
150    list(APPEND COMPILER_RT_TEST_LIBDISPATCH_CFLAGS
151        -I${COMPILER_RT_LIBDISPATCH_INSTALL_PATH}/include
152        -L${COMPILER_RT_LIBDISPATCH_INSTALL_PATH}/lib
153        -Wl,-rpath=${COMPILER_RT_LIBDISPATCH_INSTALL_PATH}/lib)
154  endif()
155  list(APPEND COMPILER_RT_TEST_LIBDISPATCH_CFLAGS -lBlocksRuntime -ldispatch)
156endif()
157if (APPLE) # Always enable on Apple platforms.
158  set(COMPILER_RT_INTERCEPT_LIBDISPATCH ON)
159endif()
160pythonize_bool(COMPILER_RT_INTERCEPT_LIBDISPATCH)
161
162if(APPLE AND SANITIZER_MIN_OSX_VERSION AND SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.9")
163  # Mac OS X prior to 10.9 had problems with exporting symbols from
164  # libc++/libc++abi.
165  set(cxxabi_supported OFF)
166else()
167  set(cxxabi_supported ON)
168endif()
169
170option(SANITIZER_ALLOW_CXXABI "Allow use of C++ ABI details in ubsan" ON)
171
172set(SANITIZER_CAN_USE_CXXABI OFF)
173if (cxxabi_supported AND SANITIZER_ALLOW_CXXABI)
174  set(SANITIZER_CAN_USE_CXXABI ON)
175endif()
176pythonize_bool(SANITIZER_CAN_USE_CXXABI)
177
178macro(handle_default_cxx_lib var)
179  # Specifying -stdlib= in CMAKE_CXX_FLAGS overrides the defaults.
180  if (CMAKE_CXX_FLAGS MATCHES "-stdlib=([a-zA-Z+]*)")
181    set(${var}_LIBNAME "${CMAKE_MATCH_1}")
182    set(${var}_SYSTEM 1)
183  elseif (${var} STREQUAL "default")
184    if (APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
185      set(${var}_LIBNAME "libc++")
186      set(${var}_SYSTEM 1)
187    elseif (FUCHSIA)
188      set(${var}_LIBNAME "libc++")
189      set(${var}_INTREE 1)
190    else()
191      set(${var}_LIBNAME "libstdc++")
192      set(${var}_SYSTEM 1)
193    endif()
194  else()
195    set(${var}_LIBNAME "${${var}}")
196    set(${var}_SYSTEM 1)
197  endif()
198endmacro()
199
200# This is either directly the C++ ABI library or the full C++ library
201# which pulls in the ABI transitively.
202# TODO: Mark this as internal flag, most users should use COMPILER_RT_CXX_LIBRARY.
203set(SANITIZER_CXX_ABI "default" CACHE STRING
204    "Specify C++ ABI library to use.")
205set(CXXABIS none default libstdc++ libc++ libcxxabi)
206set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS})
207handle_default_cxx_lib(SANITIZER_CXX_ABI)
208
209# This needs to be a full C++ library for linking gtest and unit tests.
210# TODO: Mark this as internal flag, most users should use COMPILER_RT_CXX_LIBRARY.
211set(SANITIZER_TEST_CXX "default" CACHE STRING
212    "Specify C++ library to use for tests.")
213set(CXXLIBS none default libstdc++ libc++)
214set_property(CACHE SANITIZER_TEST_CXX PROPERTY STRINGS ;${CXXLIBS})
215handle_default_cxx_lib(SANITIZER_TEST_CXX)
216
217option(COMPILER_RT_USE_LLVM_UNWINDER "Use the LLVM unwinder." OFF)
218cmake_dependent_option(COMPILER_RT_ENABLE_STATIC_UNWINDER
219  "Statically link the LLVM unwinder." OFF
220  "COMPILER_RT_USE_LLVM_UNWINDER" OFF)
221
222set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER OFF)
223if (FUCHSIA)
224  set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER ON)
225elseif (DEFINED LIBUNWIND_ENABLE_SHARED AND NOT LIBUNWIND_ENABLE_SHARED)
226  set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER ON)
227endif()
228
229option(SANITIZER_USE_STATIC_LLVM_UNWINDER
230  "Use static LLVM unwinder." ${DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER})
231pythonize_bool(SANITIZER_USE_STATIC_LLVM_UNWINDER)
232
233set(DEFAULT_SANITIZER_USE_STATIC_CXX_ABI OFF)
234if (DEFINED LIBCXXABI_ENABLE_SHARED AND NOT LIBCXXABI_ENABLE_SHARED)
235  set(DEFAULT_SANITIZER_USE_STATIC_CXX_ABI ON)
236endif()
237
238option(SANITIZER_USE_STATIC_CXX_ABI
239  "Use static libc++abi." ${DEFAULT_SANITIZER_USE_STATIC_CXX_ABI})
240pythonize_bool(SANITIZER_USE_STATIC_CXX_ABI)
241
242set(DEFAULT_SANITIZER_USE_STATIC_TEST_CXX OFF)
243if (DEFINED LIBCXX_ENABLE_SHARED AND NOT LIBCXX_ENABLE_SHARED)
244  set(DEFAULT_SANITIZER_USE_STATIC_TEST_CXX ON)
245endif()
246
247option(SANITIZER_USE_STATIC_TEST_CXX
248  "Use static libc++ for tests." ${DEFAULT_SANITIZER_USE_STATIC_TEST_CXX})
249pythonize_bool(SANITIZER_USE_STATIC_TEST_CXX)
250
251set(COMPILER_RT_SUPPORTED_CXX_LIBRARIES none default libcxx)
252set(COMPILER_RT_CXX_LIBRARY "default" CACHE STRING "Specify C++ library to use. Supported values are ${COMPILER_RT_SUPPORTED_CXX_LIBRARIES}.")
253if (NOT "${COMPILER_RT_CXX_LIBRARY}" IN_LIST COMPILER_RT_SUPPORTED_CXX_LIBRARIES)
254  message(FATAL_ERROR "Unsupported C++ library: '${COMPILER_RT_CXX_LIBRARY}'. Supported values are ${COMPILER_RT_SUPPORTED_CXX_LIBRARIES}.")
255endif()
256cmake_dependent_option(COMPILER_RT_STATIC_CXX_LIBRARY
257  "Statically link the C++ library." OFF
258  "COMPILER_RT_CXX_LIBRARY" OFF)
259
260set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF)
261if (FUCHSIA)
262  set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY ON)
263endif()
264
265option(COMPILER_RT_USE_BUILTINS_LIBRARY
266  "Use compiler-rt builtins instead of libgcc" ${DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY})
267
268include(config-ix)
269
270#================================
271# Setup Compiler Flags
272#================================
273
274# fcf-protection is a gcc/clang option for CET support on Linux platforms.
275# We need to handle MSVC CET option on Windows platforms.
276if (NOT MSVC)
277  if (COMPILER_RT_ENABLE_CET AND NOT COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
278    message(FATAL_ERROR "Compiler used to build compiler-rt doesn't support CET!")
279  endif()
280endif()
281
282if(MSVC)
283  # Override any existing /W flags with /W4. This is what LLVM does.  Failing to
284  # remove other /W[0-4] flags will result in a warning about overriding a
285  # previous flag.
286  if (COMPILER_RT_HAS_W4_FLAG)
287    string(REGEX REPLACE " /W[0-4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
288    string(REGEX REPLACE " /W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
289    append_string_if(COMPILER_RT_HAS_W4_FLAG /W4 CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
290  endif()
291else()
292  append_string_if(COMPILER_RT_HAS_WALL_FLAG -Wall CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
293endif()
294if(COMPILER_RT_ENABLE_WERROR)
295  append_string_if(COMPILER_RT_HAS_WERROR_FLAG -Werror CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
296  append_string_if(COMPILER_RT_HAS_WX_FLAG /WX CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
297endif()
298
299append_string_if(COMPILER_RT_HAS_STD_CXX14_FLAG -std=c++14 CMAKE_CXX_FLAGS)
300
301# Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP.
302if(NOT COMPILER_RT_HAS_FUNC_SYMBOL)
303  add_definitions(-D__func__=__FUNCTION__)
304endif()
305
306# Provide some common commandline flags for Sanitizer runtimes.
307if("${ANDROID_API_LEVEL}" GREATER_EQUAL 29)
308  list(APPEND SANITIZER_COMMON_CFLAGS -fno-emulated-tls)
309  string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " -fno-emulated-tls")
310endif()
311if(NOT WIN32)
312  append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC SANITIZER_COMMON_CFLAGS)
313endif()
314append_list_if(COMPILER_RT_HAS_FNO_BUILTIN_FLAG -fno-builtin SANITIZER_COMMON_CFLAGS)
315append_list_if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG -fno-exceptions SANITIZER_COMMON_CFLAGS)
316if(NOT COMPILER_RT_DEBUG AND NOT APPLE)
317  append_list_if(COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG -fomit-frame-pointer SANITIZER_COMMON_CFLAGS)
318endif()
319append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COMMON_CFLAGS)
320append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
321append_list_if(COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG -fno-sanitize=safe-stack SANITIZER_COMMON_CFLAGS)
322append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
323if(NOT COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
324  append_list_if(COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG -fvisibility-inlines-hidden SANITIZER_COMMON_CFLAGS)
325endif()
326append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
327
328# By default do not instrument or use profdata for compiler-rt.
329if(NOT COMPILER_RT_ENABLE_PGO)
330  if(LLVM_PROFDATA_FILE AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG)
331    list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-instr-use")
332  endif()
333  if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
334    list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-generate")
335  elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
336    list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-instr-generate")
337    if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG)
338      list(APPEND SANITIZER_COMMON_CFLAGS "-fno-coverage-mapping")
339    endif()
340  endif()
341endif()
342
343# The following is a workaround for powerpc64le. This is the only architecture
344# that requires -fno-function-sections to work properly. If lacking, the ASan
345# Linux test function-sections-are-bad.cpp fails with the following error:
346# 'undefined symbol: __sanitizer_unaligned_load32'.
347if(DEFINED TARGET_powerpc64le_CFLAGS)
348  if(CMAKE_CXX_COMPILER_ID MATCHES "XL")
349    append("-qnofuncsect" TARGET_powerpc64le_CFLAGS)
350  else()
351    append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections TARGET_powerpc64le_CFLAGS)
352  endif()
353endif()
354
355# The following is a workaround for s390x.  This avoids creation of "partial
356# inline" function fragments when building the asan libraries with certain
357# GCC versions.  The presence of those fragments, in particular for the
358# interceptors, changes backtraces seen in asan error cases, which causes
359# testsuite failures.
360if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x")
361  append_list_if(COMPILER_RT_HAS_FNO_PARTIAL_INLINING_FLAG -fno-partial-inlining SANITIZER_COMMON_CFLAGS)
362endif()
363
364if(MSVC)
365  # Replace the /M[DT][d] flags with /MT, and strip any definitions of _DEBUG,
366  # which cause definition mismatches at link time.
367  # FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214.
368  if(COMPILER_RT_HAS_MT_FLAG)
369    foreach(flag_var
370      CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
371      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
372      CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
373      CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
374      string(REGEX REPLACE "/M[DT]d" "/MT" ${flag_var} "${${flag_var}}")
375      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
376      string(REGEX REPLACE "/D_DEBUG" "" ${flag_var} "${${flag_var}}")
377    endforeach()
378  endif()
379  append_list_if(COMPILER_RT_HAS_Oy_FLAG /Oy- SANITIZER_COMMON_CFLAGS)
380  append_list_if(COMPILER_RT_HAS_GS_FLAG /GS- SANITIZER_COMMON_CFLAGS)
381
382  # Disable thread safe initialization for static locals. ASan shouldn't need
383  # it. Thread safe initialization assumes that the CRT has already been
384  # initialized, but ASan initializes before the CRT.
385  list(APPEND SANITIZER_COMMON_CFLAGS /Zc:threadSafeInit-)
386endif()
387
388append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 SANITIZER_COMMON_CFLAGS)
389
390if(CMAKE_CXX_COMPILER_ID MATCHES Clang)
391  list(APPEND THREAD_SAFETY_FLAGS
392      "-Wthread-safety"
393      "-Wthread-safety-reference"
394      "-Wthread-safety-beta"
395  )
396  list(APPEND SANITIZER_COMMON_CFLAGS ${THREAD_SAFETY_FLAGS})
397  string(REPLACE ";" " " thread_safety_flags_space_sep "${THREAD_SAFETY_FLAGS}")
398  string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${thread_safety_flags_space_sep}")
399endif()
400
401# If we're using MSVC,
402# always respect the optimization flags set by CMAKE_BUILD_TYPE instead.
403if (NOT MSVC)
404
405  # Build with optimization, unless we're in debug mode.
406  if(COMPILER_RT_DEBUG)
407    list(APPEND SANITIZER_COMMON_CFLAGS -O1)
408  else()
409    list(APPEND SANITIZER_COMMON_CFLAGS -O3)
410  endif()
411endif()
412
413# Determine if we should restrict stack frame sizes.
414# Stack frames on PowerPC, Mips, SystemZ and in debug build can be much larger than
415# anticipated.
416# FIXME: Fix all sanitizers and add -Wframe-larger-than to
417# SANITIZER_COMMON_FLAGS
418if(COMPILER_RT_HAS_WFRAME_LARGER_THAN_FLAG AND NOT COMPILER_RT_DEBUG
419   AND NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "powerpc|mips|s390x")
420  set(SANITIZER_LIMIT_FRAME_SIZE TRUE)
421else()
422  set(SANITIZER_LIMIT_FRAME_SIZE FALSE)
423endif()
424
425if(FUCHSIA OR UNIX)
426  set(SANITIZER_USE_SYMBOLS TRUE)
427else()
428  set(SANITIZER_USE_SYMBOLS FALSE)
429endif()
430
431# Build sanitizer runtimes with debug info.
432if(MSVC)
433  # Use /Z7 instead of /Zi for the asan runtime. This avoids the LNK4099
434  # warning from the MS linker complaining that it can't find the 'vc140.pdb'
435  # file used by our object library compilations.
436  list(APPEND SANITIZER_COMMON_CFLAGS /Z7)
437  foreach(var_to_update
438    CMAKE_CXX_FLAGS
439    CMAKE_CXX_FLAGS_DEBUG
440    CMAKE_CXX_FLAGS_RELWITHDEBINFO)
441    string(REGEX REPLACE "(^| )/Z[i7I]($| )" " /Z7 "
442           "${var_to_update}" "${${var_to_update}}")
443  endforeach()
444elseif(APPLE)
445  # On Apple platforms use full debug info (i.e. not `-gline-tables-only`)
446  # for all build types so that the runtime can be debugged.
447  if(NOT COMPILER_RT_HAS_G_FLAG)
448    message(FATAL_ERROR "-g is not supported by host compiler")
449  endif()
450  list(APPEND SANITIZER_COMMON_CFLAGS -g)
451elseif(COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG AND NOT COMPILER_RT_DEBUG)
452  list(APPEND SANITIZER_COMMON_CFLAGS -gline-tables-only)
453elseif(COMPILER_RT_HAS_G_FLAG)
454  list(APPEND SANITIZER_COMMON_CFLAGS -g)
455endif()
456
457if(LLVM_ENABLE_MODULES)
458  # Sanitizers cannot be built with -fmodules. The interceptors intentionally
459  # don't include system headers, which is incompatible with modules.
460  list(APPEND SANITIZER_COMMON_CFLAGS -fno-modules)
461endif()
462
463# Turn off several warnings.
464append_list_if(COMPILER_RT_HAS_WGNU_FLAG -Wno-gnu SANITIZER_COMMON_CFLAGS)
465append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros SANITIZER_COMMON_CFLAGS)
466append_list_if(COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG -Wno-c99-extensions SANITIZER_COMMON_CFLAGS)
467# format-pedantic warns about passing T* for %p, which is not useful.
468append_list_if(COMPILER_RT_HAS_WD4146_FLAG /wd4146 SANITIZER_COMMON_CFLAGS)
469append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS)
470append_list_if(COMPILER_RT_HAS_WD4391_FLAG /wd4391 SANITIZER_COMMON_CFLAGS)
471append_list_if(COMPILER_RT_HAS_WD4722_FLAG /wd4722 SANITIZER_COMMON_CFLAGS)
472append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS)
473
474append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS)
475
476# Set common link flags.
477# TODO: We should consider using the same model as libc++, that is use either
478# -nostdlib++ and --unwindlib=none if supported, or -nodefaultlibs otherwise.
479append_list_if(C_SUPPORTS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS)
480append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS)
481
482if (COMPILER_RT_USE_BUILTINS_LIBRARY)
483  string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
484else()
485  if (ANDROID)
486    append_list_if(COMPILER_RT_HAS_GCC_LIB gcc SANITIZER_COMMON_LINK_LIBS)
487  else()
488    append_list_if(COMPILER_RT_HAS_GCC_S_LIB gcc_s SANITIZER_COMMON_LINK_LIBS)
489  endif()
490endif()
491
492append_list_if(COMPILER_RT_HAS_LIBC c SANITIZER_COMMON_LINK_LIBS)
493if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
494  list(APPEND SANITIZER_COMMON_LINK_LIBS zircon)
495endif()
496
497if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
498  set(SANITIZER_NO_UNDEFINED_SYMBOLS_DEFAULT ON)
499else()
500  set(SANITIZER_NO_UNDEFINED_SYMBOLS_DEFAULT OFF)
501endif()
502option(SANITIZER_NO_UNDEFINED_SYMBOLS "Report error on unresolved symbol references" ${SANITIZER_NO_UNDEFINED_SYMBOLS_DEFAULT})
503if (SANITIZER_NO_UNDEFINED_SYMBOLS)
504  list(APPEND SANITIZER_COMMON_LINK_FLAGS -Wl,-z,defs)
505endif()
506
507# TODO: COMPILER_RT_COMMON_CFLAGS and COMPILER_RT_COMMON_LINK_FLAGS are
508# intended for use in non-sanitizer runtimes such as libFuzzer, profile or XRay,
509# move these higher to include common flags, then derive SANITIZER_COMMON_CFLAGS
510# and SANITIZER_COMMON_LINK_FLAGS from those and append sanitizer-specific flags.
511set(COMPILER_RT_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS})
512set(COMPILER_RT_COMMON_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS})
513
514# We don't use the C++ standard library, so avoid including it by mistake.
515append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ SANITIZER_COMMON_CFLAGS)
516append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ SANITIZER_COMMON_LINK_FLAGS)
517
518# Remove -stdlib= which is unused when passing -nostdinc++...
519string(REGEX MATCHALL "-stdlib=[a-zA-Z+]*" stdlib_flag "${CMAKE_CXX_FLAGS}")
520string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
521
522# ...we need it to build some runtimes and tests so readd it where appropriate.
523list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag})
524list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag})
525
526# TODO: There's a lot of duplication across lib/*/tests/CMakeLists.txt files,
527# move some of the common flags to COMPILER_RT_UNITTEST_CFLAGS.
528
529# Unittests need access to C++ standard library.
530string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${stdlib_flag}")
531
532# When cross-compiling, COMPILER_RT_TEST_COMPILER_CFLAGS help in compilation
533# and linking of unittests.
534string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}")
535set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS})
536
537if(COMPILER_RT_USE_LLVM_UNWINDER)
538  # We're linking directly against the libunwind that we're building so don't
539  # try to link in the toolchain's default libunwind which may be missing.
540  append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none COMPILER_RT_COMMON_LINK_FLAGS)
541  append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none COMPILER_RT_UNITTEST_LINK_FLAGS)
542  if (COMPILER_RT_ENABLE_STATIC_UNWINDER)
543    list(APPEND COMPILER_RT_UNWINDER_LINK_LIBS "$<TARGET_LINKER_FILE:unwind_static>")
544  else()
545    list(APPEND COMPILER_RT_UNWINDER_LINK_LIBS "$<TARGET_LINKER_FILE:$<IF:$<TARGET_EXISTS:unwind_shared>,unwind_shared,unwind_static>>")
546  endif()
547endif()
548
549if (COMPILER_RT_CXX_LIBRARY STREQUAL "libcxx")
550  # We are using the in-tree libc++ so avoid including the default one.
551  append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_COMMON_CFLAGS)
552  append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_COMMON_LINK_FLAGS)
553  # Use the in-tree libc++ through explicit include and library paths.
554  set(COMPILER_RT_CXX_CFLAGS "$<$<TARGET_EXISTS:cxx-headers>:-isystem$<JOIN:$<TARGET_PROPERTY:cxx-headers,INTERFACE_INCLUDE_DIRECTORIES>,$<SEMICOLON>-isystem>>")
555  if (COMPILER_RT_STATIC_CXX_LIBRARY)
556    set(COMPILER_RT_CXX_LINK_LIBS "$<TARGET_LINKER_FILE:cxx_static>")
557  else()
558    set(COMPILER_RT_CXX_LINK_LIBS "$<TARGET_LINKER_FILE:$<IF:$<TARGET_EXISTS:cxx_shared>,cxx_shared,cxx_static>>")
559  endif()
560elseif (COMPILER_RT_CXX_LIBRARY STREQUAL "none")
561  # We aren't using any C++ standard library so avoid including the default one.
562  append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_COMMON_CFLAGS)
563  append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_COMMON_LINK_FLAGS)
564else()
565  # Nothing to be done for `default`.
566endif()
567
568macro(append_libcxx_libs var)
569  if (${var}_INTREE)
570    # TODO: We don't need to add --unwindlib=none to SANITIZER_COMMON_LINK_FLAGS
571    # because we added -nodefaultlibs there earlier, and adding would result in
572    # a warning, but if we switch to -nostdlib++, we would need to add it here.
573    # append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none SANITIZER_COMMON_LINK_FLAGS)
574
575    if (SANITIZER_USE_STATIC_LLVM_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND))
576      list(APPEND ${var}_LIBRARIES unwind_static)
577    elseif (TARGET unwind_shared OR HAVE_LIBUNWIND)
578      list(APPEND ${var}_LIBRARIES unwind_shared)
579    endif()
580
581    if (SANITIZER_USE_STATIC_CXX_ABI AND (TARGET cxxabi_static OR HAVE_LIBCXXABI))
582      list(APPEND ${var}_LIBRARIES cxxabi_static)
583    elseif (TARGET cxxabi_shared OR HAVE_LIBCXXABI)
584      list(APPEND ${var}_LIBRARIES cxxabi_shared)
585    endif()
586  else()
587    append_list_if(COMPILER_RT_HAS_LIBCXX c++ ${var}_LIBRARIES)
588  endif()
589endmacro()
590
591if (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libc++")
592  append_libcxx_libs(SANITIZER_CXX_ABI)
593elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libcxxabi")
594  list(APPEND SANITIZER_CXX_ABI_LIBRARIES "c++abi")
595elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++")
596  append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_CXX_ABI_LIBRARIES)
597endif()
598
599if (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libc++")
600  if (SANITIZER_TEST_CXX_INTREE)
601    list(APPEND SANITIZER_TEST_CXX_CFLAGS "$<$<TARGET_EXISTS:cxx-headers>:-isystem$<JOIN:$<TARGET_PROPERTY:cxx-headers,INTERFACE_INCLUDE_DIRECTORIES>,$<SEMICOLON>-isystem>>")
602    if (SANITIZER_USE_STATIC_TEST_CXX)
603      list(APPEND SANITIZER_TEST_CXX_LIBRARIES "$<TARGET_LINKER_FILE:cxx_static>")
604    else()
605      list(APPEND SANITIZER_TEST_CXX_LIBRARIES "$<TARGET_LINKER_FILE:$<IF:$<TARGET_EXISTS:cxx_shared>,cxx_shared,cxx_static>>")
606    endif()
607    # We are using the in tree libc++ so avoid including the default one.
608    append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_UNITTEST_CFLAGS)
609    append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_UNITTEST_LINK_FLAGS)
610  else()
611    append_list_if(COMPILER_RT_HAS_LIBCXX -lc++ SANITIZER_TEST_CXX_LIBRARIES)
612  endif()
613elseif (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libstdc++")
614  append_list_if(COMPILER_RT_HAS_LIBSTDCXX -lstdc++ SANITIZER_TEST_CXX_LIBRARIES)
615endif()
616
617# Unittests support.
618set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest)
619set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc)
620set(COMPILER_RT_GTEST_CFLAGS
621  -DGTEST_NO_LLVM_SUPPORT=1
622  -DGTEST_HAS_RTTI=0
623  -I${COMPILER_RT_GTEST_PATH}/include
624  -I${COMPILER_RT_GTEST_PATH}
625)
626
627# Mocking support.
628set(COMPILER_RT_GMOCK_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock)
629set(COMPILER_RT_GMOCK_SOURCE ${COMPILER_RT_GMOCK_PATH}/src/gmock-all.cc)
630set(COMPILER_RT_GMOCK_CFLAGS
631  -DGTEST_NO_LLVM_SUPPORT=1
632  -DGTEST_HAS_RTTI=0
633  -I${COMPILER_RT_GMOCK_PATH}/include
634  -I${COMPILER_RT_GMOCK_PATH}
635)
636
637if(COMPILER_RT_HAS_G_FLAG)
638  list(APPEND COMPILER_RT_UNITTEST_CFLAGS -g)
639endif()
640append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_UNITTEST_CFLAGS)
641append_list_if(COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG -Wno-covered-switch-default COMPILER_RT_UNITTEST_CFLAGS)
642append_list_if(COMPILER_RT_HAS_WSUGGEST_OVERRIDE_FLAG -Wno-suggest-override COMPILER_RT_UNITTEST_CFLAGS)
643
644if(MSVC)
645  # gtest use a lot of stuff marked as deprecated on Windows.
646  list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations)
647endif()
648
649# Warnings to turn off for all libraries, not just sanitizers.
650append_string_if(COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG -Wno-unused-parameter CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
651
652if (CMAKE_LINKER MATCHES "link.exe$")
653  # Silence MSVC linker warnings caused by empty object files. The
654  # sanitizer libraries intentionally use ifdefs that result in empty
655  # files, rather than skipping these files in the build system.
656  # Ideally, we would pass this flag only for the libraries that need
657  # it, but CMake doesn't seem to have a way to set linker flags for
658  # individual static libraries, so we enable the suppression flag for
659  # the whole compiler-rt project.
660  set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221")
661endif()
662
663add_subdirectory(include)
664
665option(COMPILER_RT_USE_LIBCXX
666  "Enable compiler-rt to use libc++ from the source tree" ON)
667if(COMPILER_RT_USE_LIBCXX)
668  if(LLVM_ENABLE_PROJECTS_USED)
669    # Don't use libcxx if LLVM_ENABLE_PROJECTS does not enable it.
670    set(COMPILER_RT_LIBCXX_PATH ${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR})
671    set(COMPILER_RT_LIBCXXABI_PATH ${LLVM_EXTERNAL_LIBCXXABI_SOURCE_DIR})
672  else()
673    foreach(path IN ITEMS ${LLVM_MAIN_SRC_DIR}/projects/libcxx
674                          ${LLVM_MAIN_SRC_DIR}/runtimes/libcxx
675                          ${LLVM_MAIN_SRC_DIR}/../libcxx
676                          ${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR})
677      if(IS_DIRECTORY ${path})
678        set(COMPILER_RT_LIBCXX_PATH ${path})
679        break()
680      endif()
681    endforeach()
682    foreach(path IN ITEMS ${LLVM_MAIN_SRC_DIR}/projects/libcxxabi
683                          ${LLVM_MAIN_SRC_DIR}/runtimes/libcxxabi
684                          ${LLVM_MAIN_SRC_DIR}/../libcxxabi
685                          ${LLVM_EXTERNAL_LIBCXXABI_SOURCE_DIR})
686      if(IS_DIRECTORY ${path})
687        set(COMPILER_RT_LIBCXXABI_PATH ${path})
688        break()
689      endif()
690    endforeach()
691  endif()
692endif()
693
694set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/tools/lld)
695if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD)
696  set(COMPILER_RT_HAS_LLD TRUE)
697else()
698  set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/../lld)
699  if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD)
700    set(COMPILER_RT_HAS_LLD TRUE)
701  endif()
702endif()
703
704if(ANDROID)
705  set(COMPILER_RT_HAS_LLD TRUE)
706  set(COMPILER_RT_TEST_USE_LLD TRUE)
707  append_list_if(COMPILER_RT_HAS_FUSE_LD_LLD_FLAG -fuse-ld=lld SANITIZER_COMMON_LINK_FLAGS)
708  append_list_if(COMPILER_RT_HAS_LLD -fuse-ld=lld COMPILER_RT_UNITTEST_LINK_FLAGS)
709endif()
710pythonize_bool(COMPILER_RT_HAS_LLD)
711pythonize_bool(COMPILER_RT_TEST_USE_LLD)
712
713add_subdirectory(lib)
714
715if(COMPILER_RT_INCLUDE_TESTS)
716  add_subdirectory(unittests)
717  add_subdirectory(test)
718  # Don't build llvm-lit for runtimes-build, it will clean up map_config.
719  if (COMPILER_RT_STANDALONE_BUILD AND NOT LLVM_RUNTIMES_BUILD)
720    # If we have a valid source tree, generate llvm-lit into the bin directory.
721    # The user can still choose to have the check targets *use* a different lit
722    # by specifying -DLLVM_EXTERNAL_LIT, but we generate it regardless.
723    if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/llvm-lit)
724      # Needed for lit support in standalone builds.
725      include(AddLLVM)
726      add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/llvm-lit ${CMAKE_CURRENT_BINARY_DIR}/llvm-lit)
727    elseif(NOT EXISTS ${LLVM_EXTERNAL_LIT})
728      message(WARNING "Could not find LLVM source directory and LLVM_EXTERNAL_LIT does not"
729                       "point to a valid file.  You will not be able to run tests.")
730    endif()
731  endif()
732endif()
733
734add_subdirectory(tools)
735