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