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