1include(ExternalProject) 2include(CompilerRTUtils) 3 4function(set_target_output_directories target output_dir) 5 # For RUNTIME_OUTPUT_DIRECTORY variable, Multi-configuration generators 6 # append a per-configuration subdirectory to the specified directory. 7 # To avoid the appended folder, the configuration specific variable must be 8 # set 'RUNTIME_OUTPUT_DIRECTORY_${CONF}': 9 # RUNTIME_OUTPUT_DIRECTORY_DEBUG, RUNTIME_OUTPUT_DIRECTORY_RELEASE, ... 10 if(CMAKE_CONFIGURATION_TYPES) 11 foreach(build_mode ${CMAKE_CONFIGURATION_TYPES}) 12 string(TOUPPER "${build_mode}" CONFIG_SUFFIX) 13 set_target_properties("${target}" PROPERTIES 14 "ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir} 15 "LIBRARY_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir} 16 "RUNTIME_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir}) 17 endforeach() 18 else() 19 set_target_properties("${target}" PROPERTIES 20 ARCHIVE_OUTPUT_DIRECTORY ${output_dir} 21 LIBRARY_OUTPUT_DIRECTORY ${output_dir} 22 RUNTIME_OUTPUT_DIRECTORY ${output_dir}) 23 endif() 24endfunction() 25 26# Tries to add an "object library" target for a given list of OSs and/or 27# architectures with name "<name>.<arch>" for non-Darwin platforms if 28# architecture can be targeted, and "<name>.<os>" for Darwin platforms. 29# add_compiler_rt_object_libraries(<name> 30# OS <os names> 31# ARCHS <architectures> 32# SOURCES <source files> 33# CFLAGS <compile flags> 34# DEFS <compile definitions>) 35function(add_compiler_rt_object_libraries name) 36 cmake_parse_arguments(LIB "" "" "OS;ARCHS;SOURCES;CFLAGS;DEFS" ${ARGN}) 37 set(libnames) 38 if(APPLE) 39 foreach(os ${LIB_OS}) 40 set(libname "${name}.${os}") 41 set(libnames ${libnames} ${libname}) 42 set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS}) 43 list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) 44 endforeach() 45 else() 46 foreach(arch ${LIB_ARCHS}) 47 set(libname "${name}.${arch}") 48 set(libnames ${libnames} ${libname}) 49 set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS}) 50 if(NOT CAN_TARGET_${arch}) 51 message(FATAL_ERROR "Architecture ${arch} can't be targeted") 52 return() 53 endif() 54 endforeach() 55 endif() 56 57 foreach(libname ${libnames}) 58 add_library(${libname} OBJECT ${LIB_SOURCES}) 59 set_target_compile_flags(${libname} 60 ${CMAKE_CXX_FLAGS} ${extra_cflags_${libname}} ${LIB_CFLAGS}) 61 set_property(TARGET ${libname} APPEND PROPERTY 62 COMPILE_DEFINITIONS ${LIB_DEFS}) 63 set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Libraries") 64 if(APPLE) 65 set_target_properties(${libname} PROPERTIES 66 OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}") 67 endif() 68 endforeach() 69endfunction() 70 71# Takes a list of object library targets, and a suffix and appends the proper 72# TARGET_OBJECTS string to the output variable. 73# format_object_libs(<output> <suffix> ...) 74macro(format_object_libs output suffix) 75 foreach(lib ${ARGN}) 76 list(APPEND ${output} $<TARGET_OBJECTS:${lib}.${suffix}>) 77 endforeach() 78endmacro() 79 80function(add_compiler_rt_component name) 81 add_custom_target(${name}) 82 set_target_properties(${name} PROPERTIES FOLDER "Compiler-RT Misc") 83 if(COMMAND runtime_register_component) 84 runtime_register_component(${name}) 85 endif() 86 add_dependencies(compiler-rt ${name}) 87endfunction() 88 89# Adds static or shared runtime for a list of architectures and operating 90# systems and puts it in the proper directory in the build and install trees. 91# add_compiler_rt_runtime(<name> 92# {STATIC|SHARED} 93# ARCHS <architectures> 94# OS <os list> 95# SOURCES <source files> 96# CFLAGS <compile flags> 97# LINK_FLAGS <linker flags> 98# DEFS <compile definitions> 99# LINK_LIBS <linked libraries> (only for shared library) 100# OBJECT_LIBS <object libraries to use as sources> 101# PARENT_TARGET <convenience parent target>) 102function(add_compiler_rt_runtime name type) 103 if(NOT type MATCHES "^(STATIC|SHARED)$") 104 message(FATAL_ERROR "type argument must be STATIC or SHARED") 105 return() 106 endif() 107 cmake_parse_arguments(LIB 108 "" 109 "PARENT_TARGET" 110 "OS;ARCHS;SOURCES;CFLAGS;LINK_FLAGS;DEFS;LINK_LIBS;OBJECT_LIBS" 111 ${ARGN}) 112 set(libnames) 113 # Until we support this some other way, build compiler-rt runtime without LTO 114 # to allow non-LTO projects to link with it. 115 if(COMPILER_RT_HAS_FNO_LTO_FLAG) 116 set(NO_LTO_FLAGS "-fno-lto") 117 else() 118 set(NO_LTO_FLAGS "") 119 endif() 120 if(APPLE) 121 foreach(os ${LIB_OS}) 122 if(type STREQUAL "STATIC") 123 set(libname "${name}_${os}") 124 else() 125 set(libname "${name}_${os}_dynamic") 126 set(extra_link_flags_${libname} ${DARWIN_${os}_LINK_FLAGS} ${LIB_LINK_FLAGS}) 127 endif() 128 list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) 129 if(LIB_ARCHS_${libname}) 130 list(APPEND libnames ${libname}) 131 set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${NO_LTO_FLAGS} ${LIB_CFLAGS}) 132 set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX}) 133 set(sources_${libname} ${LIB_SOURCES}) 134 format_object_libs(sources_${libname} ${os} ${LIB_OBJECT_LIBS}) 135 endif() 136 endforeach() 137 else() 138 foreach(arch ${LIB_ARCHS}) 139 if(NOT CAN_TARGET_${arch}) 140 message(FATAL_ERROR "Architecture ${arch} can't be targeted") 141 return() 142 endif() 143 if(type STREQUAL "STATIC") 144 set(libname "${name}-${arch}") 145 set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX}) 146 else() 147 set(libname "${name}-dynamic-${arch}") 148 set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) 149 set(extra_link_flags_${libname} ${TARGET_${arch}_LINK_FLAGS} ${LIB_LINK_FLAGS}) 150 if(WIN32) 151 set(output_name_${libname} ${name}_dynamic-${arch}${COMPILER_RT_OS_SUFFIX}) 152 else() 153 set(output_name_${libname} ${name}-${arch}${COMPILER_RT_OS_SUFFIX}) 154 endif() 155 endif() 156 set(sources_${libname} ${LIB_SOURCES}) 157 format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS}) 158 set(libnames ${libnames} ${libname}) 159 set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${NO_LTO_FLAGS} ${LIB_CFLAGS}) 160 endforeach() 161 endif() 162 163 if(NOT libnames) 164 return() 165 endif() 166 167 if(LIB_PARENT_TARGET) 168 # If the parent targets aren't created we should create them 169 if(NOT TARGET ${LIB_PARENT_TARGET}) 170 add_custom_target(${LIB_PARENT_TARGET}) 171 endif() 172 if(NOT TARGET install-${LIB_PARENT_TARGET}) 173 # The parent install target specifies the parent component to scrape up 174 # anything not installed by the individual install targets, and to handle 175 # installation when running the multi-configuration generators. 176 add_custom_target(install-${LIB_PARENT_TARGET} 177 DEPENDS ${LIB_PARENT_TARGET} 178 COMMAND "${CMAKE_COMMAND}" 179 -DCMAKE_INSTALL_COMPONENT=${LIB_PARENT_TARGET} 180 -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") 181 set_target_properties(install-${LIB_PARENT_TARGET} PROPERTIES 182 FOLDER "Compiler-RT Misc") 183 add_dependencies(install-compiler-rt install-${LIB_PARENT_TARGET}) 184 endif() 185 endif() 186 187 foreach(libname ${libnames}) 188 # If you are using a multi-configuration generator we don't generate 189 # per-library install rules, so we fall back to the parent target COMPONENT 190 if(CMAKE_CONFIGURATION_TYPES AND LIB_PARENT_TARGET) 191 set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET}) 192 else() 193 set(COMPONENT_OPTION COMPONENT ${libname}) 194 endif() 195 196 add_library(${libname} ${type} ${sources_${libname}}) 197 set_target_compile_flags(${libname} ${extra_cflags_${libname}}) 198 set_target_link_flags(${libname} ${extra_link_flags_${libname}}) 199 set_property(TARGET ${libname} APPEND PROPERTY 200 COMPILE_DEFINITIONS ${LIB_DEFS}) 201 set_target_output_directories(${libname} ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) 202 set_target_properties(${libname} PROPERTIES 203 OUTPUT_NAME ${output_name_${libname}}) 204 set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Runtime") 205 if(${type} STREQUAL "SHARED") 206 if(LIB_LINK_LIBS) 207 target_link_libraries(${libname} ${LIB_LINK_LIBS}) 208 endif() 209 if(WIN32 AND NOT CYGWIN AND NOT MINGW) 210 set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") 211 set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib") 212 endif() 213 if(APPLE) 214 # Ad-hoc sign the dylibs 215 add_custom_command(TARGET ${libname} 216 POST_BUILD 217 COMMAND codesign --sign - $<TARGET_FILE:${libname}> 218 WORKING_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR} 219 ) 220 endif() 221 endif() 222 install(TARGETS ${libname} 223 ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} 224 ${COMPONENT_OPTION} 225 LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} 226 ${COMPONENT_OPTION} 227 RUNTIME DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} 228 ${COMPONENT_OPTION}) 229 230 # We only want to generate per-library install targets if you aren't using 231 # an IDE because the extra targets get cluttered in IDEs. 232 if(NOT CMAKE_CONFIGURATION_TYPES) 233 add_custom_target(install-${libname} 234 DEPENDS ${libname} 235 COMMAND "${CMAKE_COMMAND}" 236 -DCMAKE_INSTALL_COMPONENT=${libname} 237 -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") 238 # If you have a parent target specified, we bind the new install target 239 # to the parent install target. 240 if(LIB_PARENT_TARGET) 241 add_dependencies(install-${LIB_PARENT_TARGET} install-${libname}) 242 endif() 243 endif() 244 if(APPLE) 245 set_target_properties(${libname} PROPERTIES 246 OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}") 247 endif() 248 249 if(type STREQUAL "SHARED") 250 rt_externalize_debuginfo(${libname}) 251 endif() 252 endforeach() 253 if(LIB_PARENT_TARGET) 254 add_dependencies(${LIB_PARENT_TARGET} ${libnames}) 255 endif() 256endfunction() 257 258# when cross compiling, COMPILER_RT_TEST_COMPILER_CFLAGS help 259# in compilation and linking of unittests. 260string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}") 261set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS}) 262 263# Unittests support. 264set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest) 265set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc) 266set(COMPILER_RT_GTEST_CFLAGS 267 -DGTEST_NO_LLVM_RAW_OSTREAM=1 268 -DGTEST_HAS_RTTI=0 269 -I${COMPILER_RT_GTEST_PATH}/include 270 -I${COMPILER_RT_GTEST_PATH} 271) 272 273append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_UNITTEST_CFLAGS) 274append_list_if(COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG -Wno-covered-switch-default COMPILER_RT_UNITTEST_CFLAGS) 275 276if(MSVC) 277 # clang doesn't support exceptions on Windows yet. 278 list(APPEND COMPILER_RT_UNITTEST_CFLAGS -D_HAS_EXCEPTIONS=0) 279 280 # We should teach clang to understand "#pragma intrinsic", see PR19898. 281 list(APPEND COMPILER_RT_UNITTEST_CFLAGS -Wno-undefined-inline) 282 283 # Clang doesn't support SEH on Windows yet. 284 list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0) 285 286 # gtest use a lot of stuff marked as deprecated on Windows. 287 list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations) 288endif() 289 290# Link objects into a single executable with COMPILER_RT_TEST_COMPILER, 291# using specified link flags. Make executable a part of provided 292# test_suite. 293# add_compiler_rt_test(<test_suite> <test_name> 294# SUBDIR <subdirectory for binary> 295# OBJECTS <object files> 296# DEPS <deps (e.g. runtime libs)> 297# LINK_FLAGS <link flags>) 298macro(add_compiler_rt_test test_suite test_name) 299 cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN}) 300 set(output_bin ${CMAKE_CURRENT_BINARY_DIR}) 301 if(TEST_SUBDIR) 302 set(output_bin "${output_bin}/${TEST_SUBDIR}") 303 endif() 304 if(CMAKE_CONFIGURATION_TYPES) 305 set(output_bin "${output_bin}/${CMAKE_CFG_INTDIR}") 306 endif() 307 set(output_bin "${output_bin}/${test_name}") 308 if(MSVC) 309 set(output_bin "${output_bin}.exe") 310 endif() 311 312 # Use host compiler in a standalone build, and just-built Clang otherwise. 313 if(NOT COMPILER_RT_STANDALONE_BUILD) 314 list(APPEND TEST_DEPS clang) 315 endif() 316 # If we're not on MSVC, include the linker flags from CMAKE but override them 317 # with the provided link flags. This ensures that flags which are required to 318 # link programs at all are included, but the changes needed for the test 319 # trump. With MSVC we can't do that because CMake is set up to run link.exe 320 # when linking, not the compiler. Here, we hack it to use the compiler 321 # because we want to use -fsanitize flags. 322 if(NOT MSVC) 323 set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}") 324 separate_arguments(TEST_LINK_FLAGS) 325 endif() 326 add_custom_target(${test_name} 327 COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} 328 -o "${output_bin}" 329 ${TEST_LINK_FLAGS} 330 DEPENDS ${TEST_DEPS}) 331 set_target_properties(${test_name} PROPERTIES FOLDER "Compiler-RT Tests") 332 333 # Make the test suite depend on the binary. 334 add_dependencies(${test_suite} ${test_name}) 335endmacro() 336 337macro(add_compiler_rt_resource_file target_name file_name component) 338 set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}") 339 set(dst_file "${COMPILER_RT_OUTPUT_DIR}/${file_name}") 340 add_custom_command(OUTPUT ${dst_file} 341 DEPENDS ${src_file} 342 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file} 343 COMMENT "Copying ${file_name}...") 344 add_custom_target(${target_name} DEPENDS ${dst_file}) 345 # Install in Clang resource directory. 346 install(FILES ${file_name} 347 DESTINATION ${COMPILER_RT_INSTALL_PATH} 348 COMPONENT ${component}) 349 add_dependencies(${component} ${target_name}) 350 351 set_target_properties(${target_name} PROPERTIES FOLDER "Compiler-RT Misc") 352endmacro() 353 354macro(add_compiler_rt_script name) 355 set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name}) 356 set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name}) 357 add_custom_command(OUTPUT ${dst} 358 DEPENDS ${src} 359 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} 360 COMMENT "Copying ${name}...") 361 add_custom_target(${name} DEPENDS ${dst}) 362 install(FILES ${dst} 363 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 364 DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin) 365endmacro(add_compiler_rt_script src name) 366 367# Builds custom version of libc++ and installs it in <prefix>. 368# Can be used to build sanitized versions of libc++ for running unit tests. 369# add_custom_libcxx(<name> <prefix> 370# DEPS <list of build deps> 371# CFLAGS <list of compile flags>) 372macro(add_custom_libcxx name prefix) 373 if(NOT COMPILER_RT_HAS_LIBCXX_SOURCES) 374 message(FATAL_ERROR "libcxx not found!") 375 endif() 376 377 cmake_parse_arguments(LIBCXX "" "" "DEPS;CFLAGS" ${ARGN}) 378 foreach(flag ${LIBCXX_CFLAGS}) 379 set(flagstr "${flagstr} ${flag}") 380 endforeach() 381 set(LIBCXX_CFLAGS ${flagstr}) 382 383 if(NOT COMPILER_RT_STANDALONE_BUILD) 384 list(APPEND LIBCXX_DEPS clang) 385 endif() 386 387 ExternalProject_Add(${name} 388 PREFIX ${prefix} 389 SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH} 390 CMAKE_ARGS -DCMAKE_MAKE_PROGRAM:STRING=${CMAKE_MAKE_PROGRAM} 391 -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} 392 -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_CXX_COMPILER} 393 -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS} 394 -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS} 395 -DCMAKE_BUILD_TYPE=Release 396 -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 397 -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} 398 -DLIBCXX_STANDALONE_BUILD=On 399 LOG_BUILD 1 400 LOG_CONFIGURE 1 401 LOG_INSTALL 1 402 ) 403 set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE) 404 405 ExternalProject_Add_Step(${name} force-reconfigure 406 DEPENDERS configure 407 ALWAYS 1 408 ) 409 410 ExternalProject_Add_Step(${name} clobber 411 COMMAND ${CMAKE_COMMAND} -E remove_directory <BINARY_DIR> 412 COMMAND ${CMAKE_COMMAND} -E make_directory <BINARY_DIR> 413 COMMENT "Clobberring ${name} build directory..." 414 DEPENDERS configure 415 DEPENDS ${LIBCXX_DEPS} 416 ) 417endmacro() 418 419function(rt_externalize_debuginfo name) 420 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO) 421 return() 422 endif() 423 424 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO_SKIP_STRIP) 425 set(strip_command COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>) 426 endif() 427 428 if(APPLE) 429 if(CMAKE_CXX_FLAGS MATCHES "-flto" 430 OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto") 431 432 set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o) 433 set_property(TARGET ${name} APPEND_STRING PROPERTY 434 LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}") 435 endif() 436 add_custom_command(TARGET ${name} POST_BUILD 437 COMMAND xcrun dsymutil $<TARGET_FILE:${name}> 438 ${strip_command}) 439 else() 440 message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!") 441 endif() 442endfunction() 443