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