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