1 include(AddLLVM) 2 include(ExternalProject) 3 include(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>) 14 function(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() 47 endfunction() 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> ...) 52 macro(format_object_libs output suffix) 53 foreach(lib ${ARGN}) 54 list(APPEND ${output} $<TARGET_OBJECTS:${lib}.${suffix}>) 55 endforeach() 56 endmacro() 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>) 71 function(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() 166 endfunction() 167 168 set(COMPILER_RT_TEST_CFLAGS) 169 170 # Unittests support. 171 set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest) 172 set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc) 173 set(COMPILER_RT_GTEST_CFLAGS 174 -DGTEST_NO_LLVM_RAW_OSTREAM=1 175 -DGTEST_HAS_RTTI=0 176 -I${COMPILER_RT_GTEST_PATH}/include 177 -I${COMPILER_RT_GTEST_PATH} 178 ) 179 180 append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_TEST_CFLAGS) 181 182 if(MSVC) 183 # clang doesn't support exceptions on Windows yet. 184 list(APPEND COMPILER_RT_TEST_CFLAGS -D_HAS_EXCEPTIONS=0) 185 186 # We should teach clang to understand "#pragma intrinsic", see PR19898. 187 list(APPEND COMPILER_RT_TEST_CFLAGS -Wno-undefined-inline) 188 189 # Clang doesn't support SEH on Windows yet. 190 list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0) 191 192 # gtest use a lot of stuff marked as deprecated on Windows. 193 list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations) 194 195 # Visual Studio 2012 only supports up to 8 template parameters in 196 # std::tr1::tuple by default, but gtest requires 10 197 if(MSVC_VERSION EQUAL 1700) 198 list(APPEND COMPILER_RT_GTEST_CFLAGS -D_VARIADIC_MAX=10) 199 endif() 200 endif() 201 202 # Link objects into a single executable with COMPILER_RT_TEST_COMPILER, 203 # using specified link flags. Make executable a part of provided 204 # test_suite. 205 # add_compiler_rt_test(<test_suite> <test_name> 206 # SUBDIR <subdirectory for binary> 207 # OBJECTS <object files> 208 # DEPS <deps (e.g. runtime libs)> 209 # LINK_FLAGS <link flags>) 210 macro(add_compiler_rt_test test_suite test_name) 211 cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN}) 212 if(TEST_SUBDIR) 213 set(output_bin "${CMAKE_CURRENT_BINARY_DIR}/${TEST_SUBDIR}/${test_name}") 214 else() 215 set(output_bin "${CMAKE_CURRENT_BINARY_DIR}/${test_name}") 216 endif() 217 if(MSVC) 218 set(output_bin "${output_bin}.exe") 219 endif() 220 # Use host compiler in a standalone build, and just-built Clang otherwise. 221 if(NOT COMPILER_RT_STANDALONE_BUILD) 222 list(APPEND TEST_DEPS clang) 223 endif() 224 # If we're not on MSVC, include the linker flags from CMAKE but override them 225 # with the provided link flags. This ensures that flags which are required to 226 # link programs at all are included, but the changes needed for the test 227 # trump. With MSVC we can't do that because CMake is set up to run link.exe 228 # when linking, not the compiler. Here, we hack it to use the compiler 229 # because we want to use -fsanitize flags. 230 if(NOT MSVC) 231 set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}") 232 separate_arguments(TEST_LINK_FLAGS) 233 endif() 234 add_custom_target(${test_name} 235 COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} 236 -o "${output_bin}" 237 ${TEST_LINK_FLAGS} 238 DEPENDS ${TEST_DEPS}) 239 # Make the test suite depend on the binary. 240 add_dependencies(${test_suite} ${test_name}) 241 endmacro() 242 243 macro(add_compiler_rt_resource_file target_name file_name) 244 set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}") 245 set(dst_file "${COMPILER_RT_OUTPUT_DIR}/${file_name}") 246 add_custom_command(OUTPUT ${dst_file} 247 DEPENDS ${src_file} 248 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file} 249 COMMENT "Copying ${file_name}...") 250 add_custom_target(${target_name} DEPENDS ${dst_file}) 251 # Install in Clang resource directory. 252 install(FILES ${file_name} DESTINATION ${COMPILER_RT_INSTALL_PATH}) 253 endmacro() 254 255 macro(add_compiler_rt_script name) 256 set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name}) 257 set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name}) 258 add_custom_command(OUTPUT ${dst} 259 DEPENDS ${src} 260 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} 261 COMMENT "Copying ${name}...") 262 add_custom_target(${name} DEPENDS ${dst}) 263 install(FILES ${dst} 264 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 265 DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin) 266 endmacro(add_compiler_rt_script src name) 267 268 # Builds custom version of libc++ and installs it in <prefix>. 269 # Can be used to build sanitized versions of libc++ for running unit tests. 270 # add_custom_libcxx(<name> <prefix> 271 # DEPS <list of build deps> 272 # CFLAGS <list of compile flags>) 273 macro(add_custom_libcxx name prefix) 274 if(NOT COMPILER_RT_HAS_LIBCXX_SOURCES) 275 message(FATAL_ERROR "libcxx not found!") 276 endif() 277 278 cmake_parse_arguments(LIBCXX "" "" "DEPS;CFLAGS" ${ARGN}) 279 foreach(flag ${LIBCXX_CFLAGS}) 280 set(flagstr "${flagstr} ${flag}") 281 endforeach() 282 set(LIBCXX_CFLAGS ${flagstr}) 283 284 if(NOT COMPILER_RT_STANDALONE_BUILD) 285 list(APPEND LIBCXX_DEPS clang) 286 endif() 287 288 ExternalProject_Add(${name} 289 PREFIX ${prefix} 290 SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH} 291 CMAKE_ARGS -DCMAKE_MAKE_PROGRAM:STRING=${CMAKE_MAKE_PROGRAM} 292 -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} 293 -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_COMPILER} 294 -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS} 295 -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS} 296 -DCMAKE_BUILD_TYPE=Release 297 -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> 298 LOG_BUILD 1 299 LOG_CONFIGURE 1 300 LOG_INSTALL 1 301 ) 302 set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE) 303 304 ExternalProject_Add_Step(${name} force-reconfigure 305 DEPENDERS configure 306 ALWAYS 1 307 ) 308 309 ExternalProject_Add_Step(${name} clobber 310 COMMAND ${CMAKE_COMMAND} -E remove_directory <BINARY_DIR> 311 COMMAND ${CMAKE_COMMAND} -E make_directory <BINARY_DIR> 312 COMMENT "Clobberring ${name} build directory..." 313 DEPENDERS configure 314 DEPENDS ${LIBCXX_DEPS} 315 ) 316 endmacro() 317 318 function(rt_externalize_debuginfo name) 319 if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO) 320 return() 321 endif() 322 323 if(APPLE) 324 if(CMAKE_CXX_FLAGS MATCHES "-flto" 325 OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto") 326 327 set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o) 328 set_property(TARGET ${name} APPEND_STRING PROPERTY 329 LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}") 330 endif() 331 add_custom_command(TARGET ${name} POST_BUILD 332 COMMAND xcrun dsymutil $<TARGET_FILE:${name}> 333 COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>) 334 else() 335 message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!") 336 endif() 337 endfunction() 338