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 if(APPLE) 114 foreach(os ${LIB_OS}) 115 if(type STREQUAL "STATIC") 116 set(libname "${name}_${os}") 117 else() 118 set(libname "${name}_${os}_dynamic") 119 set(extra_link_flags_${libname} ${DARWIN_${os}_LINK_FLAGS} ${LIB_LINK_FLAGS}) 120 endif() 121 list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) 122 if(LIB_ARCHS_${libname}) 123 list(APPEND libnames ${libname}) 124 set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${LIB_CFLAGS}) 125 set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX}) 126 set(sources_${libname} ${LIB_SOURCES}) 127 format_object_libs(sources_${libname} ${os} ${LIB_OBJECT_LIBS}) 128 endif() 129 endforeach() 130 else() 131 foreach(arch ${LIB_ARCHS}) 132 if(NOT CAN_TARGET_${arch}) 133 message(FATAL_ERROR "Architecture ${arch} can't be targeted") 134 return() 135 endif() 136 if(type STREQUAL "STATIC") 137 set(libname "${name}-${arch}") 138 set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX}) 139 else() 140 set(libname "${name}-dynamic-${arch}") 141 set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) 142 set(extra_link_flags_${libname} ${TARGET_${arch}_LINK_FLAGS} ${LIB_LINK_FLAGS}) 143 if(WIN32) 144 set(output_name_${libname} ${name}_dynamic-${arch}${COMPILER_RT_OS_SUFFIX}) 145 else() 146 set(output_name_${libname} ${name}-${arch}${COMPILER_RT_OS_SUFFIX}) 147 endif() 148 endif() 149 set(sources_${libname} ${LIB_SOURCES}) 150 format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS}) 151 set(libnames ${libnames} ${libname}) 152 set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) 153 endforeach() 154 endif() 155 156 if(NOT libnames) 157 return() 158 endif() 159 160 if(LIB_PARENT_TARGET) 161 # If the parent targets aren't created we should create them 162 if(NOT TARGET ${LIB_PARENT_TARGET}) 163 add_custom_target(${LIB_PARENT_TARGET}) 164 endif() 165 if(NOT TARGET install-${LIB_PARENT_TARGET}) 166 # The parent install target specifies the parent component to scrape up 167 # anything not installed by the individual install targets, and to handle 168 # installation when running the multi-configuration generators. 169 add_custom_target(install-${LIB_PARENT_TARGET} 170 DEPENDS ${LIB_PARENT_TARGET} 171 COMMAND "${CMAKE_COMMAND}" 172 -DCMAKE_INSTALL_COMPONENT=${LIB_PARENT_TARGET} 173 -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") 174 set_target_properties(install-${LIB_PARENT_TARGET} PROPERTIES 175 FOLDER "Compiler-RT Misc") 176 add_dependencies(install-compiler-rt install-${LIB_PARENT_TARGET}) 177 endif() 178 endif() 179 180 foreach(libname ${libnames}) 181 # If you are using a multi-configuration generator we don't generate 182 # per-library install rules, so we fall back to the parent target COMPONENT 183 if(CMAKE_CONFIGURATION_TYPES AND LIB_PARENT_TARGET) 184 set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET}) 185 else() 186 set(COMPONENT_OPTION COMPONENT ${libname}) 187 endif() 188 189 add_library(${libname} ${type} ${sources_${libname}}) 190 set_target_compile_flags(${libname} ${extra_cflags_${libname}}) 191 set_target_link_flags(${libname} ${extra_link_flags_${libname}}) 192 set_property(TARGET ${libname} APPEND PROPERTY 193 COMPILE_DEFINITIONS ${LIB_DEFS}) 194 set_target_output_directories(${libname} ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) 195 set_target_properties(${libname} PROPERTIES 196 OUTPUT_NAME ${output_name_${libname}}) 197 set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Runtime") 198 if(${type} STREQUAL "SHARED") 199 if(LIB_LINK_LIBS) 200 target_link_libraries(${libname} ${LIB_LINK_LIBS}) 201 endif() 202 if(WIN32 AND NOT CYGWIN AND NOT MINGW) 203 set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") 204 set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib") 205 endif() 206 endif() 207 install(TARGETS ${libname} 208 ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} 209 ${COMPONENT_OPTION} 210 LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} 211 ${COMPONENT_OPTION} 212 RUNTIME DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} 213 ${COMPONENT_OPTION}) 214 215 # We only want to generate per-library install targets if you aren't using 216 # an IDE because the extra targets get cluttered in IDEs. 217 if(NOT CMAKE_CONFIGURATION_TYPES) 218 add_custom_target(install-${libname} 219 DEPENDS ${libname} 220 COMMAND "${CMAKE_COMMAND}" 221 -DCMAKE_INSTALL_COMPONENT=${libname} 222 -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") 223 # If you have a parent target specified, we bind the new install target 224 # to the parent install target. 225 if(LIB_PARENT_TARGET) 226 add_dependencies(install-${LIB_PARENT_TARGET} install-${libname}) 227 endif() 228 endif() 229 if(APPLE) 230 set_target_properties(${libname} PROPERTIES 231 OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}") 232 endif() 233 234 if(type STREQUAL "SHARED") 235 rt_externalize_debuginfo(${libname}) 236 endif() 237 endforeach() 238 if(LIB_PARENT_TARGET) 239 add_dependencies(${LIB_PARENT_TARGET} ${libnames}) 240 endif() 241endfunction() 242 243# when cross compiling, COMPILER_RT_TEST_COMPILER_CFLAGS help 244# in compilation and linking of unittests. 245string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}") 246set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS}) 247 248# Unittests support. 249set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest) 250set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc) 251set(COMPILER_RT_GTEST_CFLAGS 252 -DGTEST_NO_LLVM_RAW_OSTREAM=1 253 -DGTEST_HAS_RTTI=0 254 -I${COMPILER_RT_GTEST_PATH}/include 255 -I${COMPILER_RT_GTEST_PATH} 256) 257 258append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_UNITTEST_CFLAGS) 259append_list_if(COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG -Wno-covered-switch-default COMPILER_RT_UNITTEST_CFLAGS) 260 261if(MSVC) 262 # clang doesn't support exceptions on Windows yet. 263 list(APPEND COMPILER_RT_UNITTEST_CFLAGS -D_HAS_EXCEPTIONS=0) 264 265 # We should teach clang to understand "#pragma intrinsic", see PR19898. 266 list(APPEND COMPILER_RT_UNITTEST_CFLAGS -Wno-undefined-inline) 267 268 # Clang doesn't support SEH on Windows yet. 269 list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0) 270 271 # gtest use a lot of stuff marked as deprecated on Windows. 272 list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations) 273endif() 274 275# Link objects into a single executable with COMPILER_RT_TEST_COMPILER, 276# using specified link flags. Make executable a part of provided 277# test_suite. 278# add_compiler_rt_test(<test_suite> <test_name> 279# SUBDIR <subdirectory for binary> 280# OBJECTS <object files> 281# DEPS <deps (e.g. runtime libs)> 282# LINK_FLAGS <link flags>) 283macro(add_compiler_rt_test test_suite test_name) 284 cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN}) 285 set(output_bin ${CMAKE_CURRENT_BINARY_DIR}) 286 if(TEST_SUBDIR) 287 set(output_bin "${output_bin}/${TEST_SUBDIR}") 288 endif() 289 if(CMAKE_CONFIGURATION_TYPES) 290 set(output_bin "${output_bin}/${CMAKE_CFG_INTDIR}") 291 endif() 292 set(output_bin "${output_bin}/${test_name}") 293 if(MSVC) 294 set(output_bin "${output_bin}.exe") 295 endif() 296 297 # Use host compiler in a standalone build, and just-built Clang otherwise. 298 if(NOT COMPILER_RT_STANDALONE_BUILD) 299 list(APPEND TEST_DEPS clang) 300 endif() 301 # If we're not on MSVC, include the linker flags from CMAKE but override them 302 # with the provided link flags. This ensures that flags which are required to 303 # link programs at all are included, but the changes needed for the test 304 # trump. With MSVC we can't do that because CMake is set up to run link.exe 305 # when linking, not the compiler. Here, we hack it to use the compiler 306 # because we want to use -fsanitize flags. 307 if(NOT MSVC) 308 set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}") 309 separate_arguments(TEST_LINK_FLAGS) 310 endif() 311 add_custom_target(${test_name} 312 COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} 313 -o "${output_bin}" 314 ${TEST_LINK_FLAGS} 315 DEPENDS ${TEST_DEPS}) 316 set_target_properties(${test_name} PROPERTIES FOLDER "Compiler-RT Tests") 317 318 # Make the test suite depend on the binary. 319 add_dependencies(${test_suite} ${test_name}) 320endmacro() 321 322macro(add_compiler_rt_resource_file target_name file_name component) 323 set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}") 324 set(dst_file "${COMPILER_RT_OUTPUT_DIR}/${file_name}") 325 add_custom_command(OUTPUT ${dst_file} 326 DEPENDS ${src_file} 327 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file} 328 COMMENT "Copying ${file_name}...") 329 add_custom_target(${target_name} DEPENDS ${dst_file}) 330 # Install in Clang resource directory. 331 install(FILES ${file_name} 332 DESTINATION ${COMPILER_RT_INSTALL_PATH} 333 COMPONENT ${component}) 334 add_dependencies(${component} ${target_name}) 335 336 set_target_properties(${target_name} PROPERTIES FOLDER "Compiler-RT Misc") 337endmacro() 338 339macro(add_compiler_rt_script name) 340 set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name}) 341 set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name}) 342 add_custom_command(OUTPUT ${dst} 343 DEPENDS ${src} 344 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} 345 COMMENT "Copying ${name}...") 346 add_custom_target(${name} DEPENDS ${dst}) 347 install(FILES ${dst} 348 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 349 DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin) 350endmacro(add_compiler_rt_script src name) 351 352# Builds custom version of libc++ and installs it in <prefix>. 353# Can be used to build sanitized versions of libc++ for running unit tests. 354# add_custom_libcxx(<name> <prefix> 355# DEPS <list of build deps> 356# CFLAGS <list of compile flags>) 357macro(add_custom_libcxx name prefix) 358 if(NOT COMPILER_RT_HAS_LIBCXX_SOURCES) 359 message(FATAL_ERROR "libcxx not found!") 360 endif() 361 362 cmake_parse_arguments(LIBCXX "" "" "DEPS;CFLAGS" ${ARGN}) 363 foreach(flag ${LIBCXX_CFLAGS}) 364 set(flagstr "${flagstr} ${flag}") 365 endforeach() 366 set(LIBCXX_CFLAGS ${flagstr}) 367 368 if(NOT COMPILER_RT_STANDALONE_BUILD) 369 list(APPEND LIBCXX_DEPS clang) 370 endif() 371 372 ExternalProject_Add(${name} 373 PREFIX ${prefix} 374 SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH} 375 CMAKE_ARGS -DCMAKE_MAKE_PROGRAM:STRING=${CMAKE_MAKE_PROGRAM} 376 -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} 377 -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_CXX_COMPILER} 378 -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS} 379 -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS} 380 -DCMAKE_BUILD_TYPE=Release 381 -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 382 -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} 383 LOG_BUILD 1 384 LOG_CONFIGURE 1 385 LOG_INSTALL 1 386 ) 387 set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE) 388 389 ExternalProject_Add_Step(${name} force-reconfigure 390 DEPENDERS configure 391 ALWAYS 1 392 ) 393 394 ExternalProject_Add_Step(${name} clobber 395 COMMAND ${CMAKE_COMMAND} -E remove_directory <BINARY_DIR> 396 COMMAND ${CMAKE_COMMAND} -E make_directory <BINARY_DIR> 397 COMMENT "Clobberring ${name} build directory..." 398 DEPENDERS configure 399 DEPENDS ${LIBCXX_DEPS} 400 ) 401endmacro() 402 403function(rt_externalize_debuginfo name) 404 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO) 405 return() 406 endif() 407 408 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO_SKIP_STRIP) 409 set(strip_command COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>) 410 endif() 411 412 if(APPLE) 413 if(CMAKE_CXX_FLAGS MATCHES "-flto" 414 OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto") 415 416 set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o) 417 set_property(TARGET ${name} APPEND_STRING PROPERTY 418 LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}") 419 endif() 420 add_custom_command(TARGET ${name} POST_BUILD 421 COMMAND xcrun dsymutil $<TARGET_FILE:${name}> 422 ${strip_command}) 423 else() 424 message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!") 425 endif() 426endfunction() 427