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# LINKFLAGS <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;LINKFLAGS;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_linkflags_${libname} ${DARWIN_${os}_LINKFLAGS} ${LIB_LINKFLAGS}) 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_linkflags_${libname} ${TARGET_${arch}_LINKFLAGS} ${LIB_LINKFLAGS}) 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_linkflags_${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_LINKFLAGS ${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) 259 260if(MSVC) 261 # clang doesn't support exceptions on Windows yet. 262 list(APPEND COMPILER_RT_UNITTEST_CFLAGS -D_HAS_EXCEPTIONS=0) 263 264 # We should teach clang to understand "#pragma intrinsic", see PR19898. 265 list(APPEND COMPILER_RT_UNITTEST_CFLAGS -Wno-undefined-inline) 266 267 # Clang doesn't support SEH on Windows yet. 268 list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0) 269 270 # gtest use a lot of stuff marked as deprecated on Windows. 271 list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations) 272 273 # Visual Studio 2012 only supports up to 8 template parameters in 274 # std::tr1::tuple by default, but gtest requires 10 275 if(MSVC_VERSION EQUAL 1700) 276 list(APPEND COMPILER_RT_GTEST_CFLAGS -D_VARIADIC_MAX=10) 277 endif() 278endif() 279 280# Link objects into a single executable with COMPILER_RT_TEST_COMPILER, 281# using specified link flags. Make executable a part of provided 282# test_suite. 283# add_compiler_rt_test(<test_suite> <test_name> 284# SUBDIR <subdirectory for binary> 285# OBJECTS <object files> 286# DEPS <deps (e.g. runtime libs)> 287# LINK_FLAGS <link flags>) 288macro(add_compiler_rt_test test_suite test_name) 289 cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN}) 290 set(output_bin ${CMAKE_CURRENT_BINARY_DIR}) 291 if(TEST_SUBDIR) 292 set(output_bin "${output_bin}/${TEST_SUBDIR}") 293 endif() 294 if(CMAKE_CONFIGURATION_TYPES) 295 set(output_bin "${output_bin}/${CMAKE_CFG_INTDIR}") 296 endif() 297 set(output_bin "${output_bin}/${test_name}") 298 if(MSVC) 299 set(output_bin "${output_bin}.exe") 300 endif() 301 302 # Use host compiler in a standalone build, and just-built Clang otherwise. 303 if(NOT COMPILER_RT_STANDALONE_BUILD) 304 list(APPEND TEST_DEPS clang) 305 endif() 306 # If we're not on MSVC, include the linker flags from CMAKE but override them 307 # with the provided link flags. This ensures that flags which are required to 308 # link programs at all are included, but the changes needed for the test 309 # trump. With MSVC we can't do that because CMake is set up to run link.exe 310 # when linking, not the compiler. Here, we hack it to use the compiler 311 # because we want to use -fsanitize flags. 312 if(NOT MSVC) 313 set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}") 314 separate_arguments(TEST_LINK_FLAGS) 315 endif() 316 add_custom_target(${test_name} 317 COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} 318 -o "${output_bin}" 319 ${TEST_LINK_FLAGS} 320 DEPENDS ${TEST_DEPS}) 321 set_target_properties(${test_name} PROPERTIES FOLDER "Compiler-RT Tests") 322 323 # Make the test suite depend on the binary. 324 add_dependencies(${test_suite} ${test_name}) 325endmacro() 326 327macro(add_compiler_rt_resource_file target_name file_name component) 328 set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}") 329 set(dst_file "${COMPILER_RT_OUTPUT_DIR}/${file_name}") 330 add_custom_command(OUTPUT ${dst_file} 331 DEPENDS ${src_file} 332 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file} 333 COMMENT "Copying ${file_name}...") 334 add_custom_target(${target_name} DEPENDS ${dst_file}) 335 # Install in Clang resource directory. 336 install(FILES ${file_name} 337 DESTINATION ${COMPILER_RT_INSTALL_PATH} 338 COMPONENT ${component}) 339 add_dependencies(${component} ${target_name}) 340 341 set_target_properties(${target_name} PROPERTIES FOLDER "Compiler-RT Misc") 342endmacro() 343 344macro(add_compiler_rt_script name) 345 set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name}) 346 set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name}) 347 add_custom_command(OUTPUT ${dst} 348 DEPENDS ${src} 349 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} 350 COMMENT "Copying ${name}...") 351 add_custom_target(${name} DEPENDS ${dst}) 352 install(FILES ${dst} 353 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 354 DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin) 355endmacro(add_compiler_rt_script src name) 356 357# Builds custom version of libc++ and installs it in <prefix>. 358# Can be used to build sanitized versions of libc++ for running unit tests. 359# add_custom_libcxx(<name> <prefix> 360# DEPS <list of build deps> 361# CFLAGS <list of compile flags>) 362macro(add_custom_libcxx name prefix) 363 if(NOT COMPILER_RT_HAS_LIBCXX_SOURCES) 364 message(FATAL_ERROR "libcxx not found!") 365 endif() 366 367 cmake_parse_arguments(LIBCXX "" "" "DEPS;CFLAGS" ${ARGN}) 368 foreach(flag ${LIBCXX_CFLAGS}) 369 set(flagstr "${flagstr} ${flag}") 370 endforeach() 371 set(LIBCXX_CFLAGS ${flagstr}) 372 373 if(NOT COMPILER_RT_STANDALONE_BUILD) 374 list(APPEND LIBCXX_DEPS clang) 375 endif() 376 377 ExternalProject_Add(${name} 378 PREFIX ${prefix} 379 SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH} 380 CMAKE_ARGS -DCMAKE_MAKE_PROGRAM:STRING=${CMAKE_MAKE_PROGRAM} 381 -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} 382 -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_CXX_COMPILER} 383 -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS} 384 -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS} 385 -DCMAKE_BUILD_TYPE=Release 386 -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 387 -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} 388 LOG_BUILD 1 389 LOG_CONFIGURE 1 390 LOG_INSTALL 1 391 ) 392 set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE) 393 394 ExternalProject_Add_Step(${name} force-reconfigure 395 DEPENDERS configure 396 ALWAYS 1 397 ) 398 399 ExternalProject_Add_Step(${name} clobber 400 COMMAND ${CMAKE_COMMAND} -E remove_directory <BINARY_DIR> 401 COMMAND ${CMAKE_COMMAND} -E make_directory <BINARY_DIR> 402 COMMENT "Clobberring ${name} build directory..." 403 DEPENDERS configure 404 DEPENDS ${LIBCXX_DEPS} 405 ) 406endmacro() 407 408function(rt_externalize_debuginfo name) 409 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO) 410 return() 411 endif() 412 413 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO_SKIP_STRIP) 414 set(strip_command COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>) 415 endif() 416 417 if(APPLE) 418 if(CMAKE_CXX_FLAGS MATCHES "-flto" 419 OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto") 420 421 set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o) 422 set_property(TARGET ${name} APPEND_STRING PROPERTY 423 LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}") 424 endif() 425 add_custom_command(TARGET ${name} POST_BUILD 426 COMMAND xcrun dsymutil $<TARGET_FILE:${name}> 427 ${strip_command}) 428 else() 429 message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!") 430 endif() 431endfunction() 432