1# On OS X SDKs can be installed anywhere on the base system and xcode-select can 2# set the default Xcode to use. This function finds the SDKs that are present in 3# the current Xcode. 4function(find_darwin_sdk_dir var sdk_name) 5 # Let's first try the internal SDK, otherwise use the public SDK. 6 execute_process( 7 COMMAND xcodebuild -version -sdk ${sdk_name}.internal Path 8 OUTPUT_VARIABLE var_internal 9 OUTPUT_STRIP_TRAILING_WHITESPACE 10 ERROR_FILE /dev/null 11 ) 12 if("" STREQUAL "${var_internal}") 13 execute_process( 14 COMMAND xcodebuild -version -sdk ${sdk_name} Path 15 OUTPUT_VARIABLE var_internal 16 OUTPUT_STRIP_TRAILING_WHITESPACE 17 ERROR_FILE /dev/null 18 ) 19 endif() 20 set(${var} ${var_internal} PARENT_SCOPE) 21endfunction() 22 23# There isn't a clear mapping of what architectures are supported with a given 24# target platform, but ld's version output does list the architectures it can 25# link for. 26function(darwin_get_toolchain_supported_archs output_var) 27 execute_process( 28 COMMAND ld -v 29 ERROR_VARIABLE LINKER_VERSION) 30 31 string(REGEX MATCH "configured to support archs: ([^\n]+)" 32 ARCHES_MATCHED "${LINKER_VERSION}") 33 if(ARCHES_MATCHED) 34 set(ARCHES "${CMAKE_MATCH_1}") 35 message(STATUS "Got ld supported ARCHES: ${ARCHES}") 36 string(REPLACE " " ";" ARCHES ${ARCHES}) 37 else() 38 # If auto-detecting fails, fall back to a default set 39 message(WARNING "Detecting supported architectures from 'ld -v' failed. Returning default set.") 40 set(ARCHES "i386;x86_64;armv7;armv7s;arm64") 41 endif() 42 43 set(${output_var} ${ARCHES} PARENT_SCOPE) 44endfunction() 45 46# This function takes an OS and a list of architectures and identifies the 47# subset of the architectures list that the installed toolchain can target. 48function(darwin_test_archs os valid_archs) 49 set(archs ${ARGN}) 50 message(STATUS "Finding valid architectures for ${os}...") 51 set(SIMPLE_CPP ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.cpp) 52 file(WRITE ${SIMPLE_CPP} "#include <iostream>\nint main() { std::cout << std::endl; return 0; }\n") 53 54 set(os_linker_flags) 55 foreach(flag ${DARWIN_${os}_LINKFLAGS}) 56 set(os_linker_flags "${os_linker_flags} ${flag}") 57 endforeach() 58 59 # The simple program will build for x86_64h on the simulator because it is 60 # compatible with x86_64 libraries (mostly), but since x86_64h isn't actually 61 # a valid or useful architecture for the iOS simulator we should drop it. 62 if(${os} STREQUAL "iossim") 63 list(REMOVE_ITEM archs "x86_64h") 64 endif() 65 66 set(working_archs) 67 foreach(arch ${archs}) 68 69 set(arch_linker_flags "-arch ${arch} ${os_linker_flags}") 70 try_compile(CAN_TARGET_${os}_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_CPP} 71 COMPILE_DEFINITIONS "-v -arch ${arch}" ${DARWIN_${os}_CFLAGS} 72 CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=${arch_linker_flags}" 73 OUTPUT_VARIABLE TEST_OUTPUT) 74 if(${CAN_TARGET_${os}_${arch}}) 75 list(APPEND working_archs ${arch}) 76 endif() 77 endforeach() 78 set(${valid_archs} ${working_archs} PARENT_SCOPE) 79endfunction() 80 81# This function checks the host cpusubtype to see if it is post-haswell. Haswell 82# and later machines can run x86_64h binaries. Haswell is cpusubtype 8. 83function(darwin_filter_host_archs input output) 84 list_union(tmp_var DARWIN_osx_ARCHS ${input}) 85 execute_process( 86 COMMAND sysctl hw.cpusubtype 87 OUTPUT_VARIABLE SUBTYPE) 88 89 string(REGEX MATCH "hw.cpusubtype: ([0-9]*)" 90 SUBTYPE_MATCHED "${SUBTYPE}") 91 set(HASWELL_SUPPORTED Off) 92 if(SUBTYPE_MATCHED) 93 if(${CMAKE_MATCH_1} GREATER 7) 94 set(HASWELL_SUPPORTED On) 95 endif() 96 endif() 97 if(NOT HASWELL_SUPPORTED) 98 list(REMOVE_ITEM tmp_var x86_64h) 99 endif() 100 set(${output} ${tmp_var} PARENT_SCOPE) 101endfunction() 102 103# Read and process the exclude file into a list of symbols 104function(darwin_read_list_from_file output_var file) 105 if(EXISTS ${file}) 106 file(READ ${file} EXCLUDES) 107 string(REPLACE "\n" ";" EXCLUDES ${EXCLUDES}) 108 set(${output_var} ${EXCLUDES} PARENT_SCOPE) 109 endif() 110endfunction() 111 112# this function takes an OS, architecture and minimum version and provides a 113# list of builtin functions to exclude 114function(darwin_find_excluded_builtins_list output_var) 115 cmake_parse_arguments(LIB 116 "" 117 "OS;ARCH;MIN_VERSION" 118 "" 119 ${ARGN}) 120 121 if(NOT LIB_OS OR NOT LIB_ARCH) 122 message(FATAL_ERROR "Must specify OS and ARCH to darwin_find_excluded_builtins_list!") 123 endif() 124 125 darwin_read_list_from_file(${LIB_OS}_BUILTINS 126 ${DARWIN_EXCLUDE_DIR}/${LIB_OS}.txt) 127 darwin_read_list_from_file(${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS 128 ${DARWIN_EXCLUDE_DIR}/${LIB_OS}-${LIB_ARCH}.txt) 129 130 if(LIB_MIN_VERSION) 131 file(GLOB builtin_lists ${DARWIN_EXCLUDE_DIR}/${LIB_OS}*-${LIB_ARCH}.txt) 132 foreach(builtin_list ${builtin_lists}) 133 string(REGEX MATCH "${LIB_OS}([0-9\\.]*)-${LIB_ARCH}.txt" VERSION_MATCHED "${builtin_list}") 134 if (VERSION_MATCHED AND NOT CMAKE_MATCH_1 VERSION_LESS LIB_MIN_VERSION) 135 if(NOT smallest_version) 136 set(smallest_version ${CMAKE_MATCH_1}) 137 elseif(CMAKE_MATCH_1 VERSION_LESS smallest_version) 138 set(smallest_version ${CMAKE_MATCH_1}) 139 endif() 140 endif() 141 endforeach() 142 143 if(smallest_version) 144 darwin_read_list_from_file(${LIB_ARCH}_${LIB_OS}_BUILTINS 145 ${DARWIN_EXCLUDE_DIR}/${LIB_OS}${smallest_version}-${LIB_ARCH}.txt) 146 endif() 147 endif() 148 149 set(${output_var} 150 ${${LIB_ARCH}_${LIB_OS}_BUILTINS} 151 ${${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS} 152 ${${LIB_OS}_BUILTINS} PARENT_SCOPE) 153endfunction() 154 155# adds a single builtin library for a single OS & ARCH 156macro(darwin_add_builtin_library name suffix) 157 cmake_parse_arguments(LIB 158 "" 159 "PARENT_TARGET;OS;ARCH" 160 "SOURCES;CFLAGS;DEFS" 161 ${ARGN}) 162 set(libname "${name}.${suffix}_${LIB_ARCH}_${LIB_OS}") 163 add_library(${libname} STATIC ${LIB_SOURCES}) 164 set_target_compile_flags(${libname} 165 -isysroot ${DARWIN_${LIB_OS}_SYSROOT} 166 ${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG} 167 ${LIB_CFLAGS}) 168 set_property(TARGET ${libname} APPEND PROPERTY 169 COMPILE_DEFINITIONS ${LIB_DEFS}) 170 set_target_properties(${libname} PROPERTIES 171 OUTPUT_NAME ${libname}${COMPILER_RT_OS_SUFFIX}) 172 set_target_properties(${libname} PROPERTIES 173 OSX_ARCHITECTURES ${LIB_ARCH}) 174 175 if(LIB_PARENT_TARGET) 176 add_dependencies(${LIB_PARENT_TARGET} ${libname}) 177 endif() 178 179 list(APPEND ${LIB_OS}_${suffix}_libs ${libname}) 180 list(APPEND ${LIB_OS}_${suffix}_lipo_flags -arch ${arch} $<TARGET_FILE:${libname}>) 181endmacro() 182 183function(darwin_lipo_libs name) 184 cmake_parse_arguments(LIB 185 "" 186 "PARENT_TARGET;OUTPUT_DIR;INSTALL_DIR" 187 "LIPO_FLAGS;DEPENDS" 188 ${ARGN}) 189 add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a 190 COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR} 191 COMMAND lipo -output 192 ${LIB_OUTPUT_DIR}/lib${name}.a 193 -create ${LIB_LIPO_FLAGS} 194 DEPENDS ${LIB_DEPENDS} 195 ) 196 add_custom_target(${name} 197 DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a) 198 add_dependencies(${LIB_PARENT_TARGET} ${name}) 199 install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a 200 DESTINATION ${LIB_INSTALL_DIR}) 201endfunction() 202 203# Filter out generic versions of routines that are re-implemented in 204# architecture specific manner. This prevents multiple definitions of the 205# same symbols, making the symbol selection non-deterministic. 206function(darwin_filter_builtin_sources output_var exclude_or_include excluded_list) 207 if(exclude_or_include STREQUAL "EXCLUDE") 208 set(filter_action GREATER) 209 set(filter_value -1) 210 elseif(exclude_or_include STREQUAL "INCLUDE") 211 set(filter_action LESS) 212 set(filter_value 0) 213 else() 214 message(FATAL_ERROR "darwin_filter_builtin_sources called without EXCLUDE|INCLUDE") 215 endif() 216 217 set(intermediate ${ARGN}) 218 foreach (_file ${intermediate}) 219 get_filename_component(_name_we ${_file} NAME_WE) 220 list(FIND ${excluded_list} ${_name_we} _found) 221 if(_found ${filter_action} ${filter_value}) 222 list(REMOVE_ITEM intermediate ${_file}) 223 elseif(${_file} MATCHES ".*/.*\\.S") 224 get_filename_component(_name ${_file} NAME) 225 string(REPLACE ".S" ".c" _cname "${_name}") 226 list(REMOVE_ITEM intermediate ${_cname}) 227 endif () 228 endforeach () 229 set(${output_var} ${intermediate} PARENT_SCOPE) 230endfunction() 231 232function(darwin_add_eprintf_library) 233 add_library(clang_rt.eprintf STATIC eprintf.c) 234 set_target_compile_flags(clang_rt.eprintf 235 -isysroot ${DARWIN_osx_SYSROOT} 236 ${DARWIN_osx_BUILTIN_MIN_VER_FLAG} 237 -arch i386) 238 set_target_properties(clang_rt.eprintf PROPERTIES 239 OUTPUT_NAME clang_rt.eprintf${COMPILER_RT_OS_SUFFIX}) 240 set_target_properties(clang_rt.eprintf PROPERTIES 241 OSX_ARCHITECTURES i386) 242 add_dependencies(builtins clang_rt.eprintf) 243 set_target_properties(clang_rt.eprintf PROPERTIES 244 ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) 245 install(TARGETS clang_rt.eprintf 246 ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) 247endfunction() 248 249# Generates builtin libraries for all operating systems specified in ARGN. Each 250# OS library is constructed by lipo-ing together single-architecture libraries. 251macro(darwin_add_builtin_libraries) 252 set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes) 253 254 if(CMAKE_CONFIGURATION_TYPES) 255 foreach(type ${CMAKE_CONFIGURATION_TYPES}) 256 set(CMAKE_C_FLAGS_${type} -O3) 257 set(CMAKE_CXX_FLAGS_${type} -O3) 258 endforeach() 259 else() 260 set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE} -O3) 261 endif() 262 263 set(CMAKE_C_FLAGS "-fPIC -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer") 264 set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) 265 set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) 266 267 set(PROFILE_SOURCES ../profile/InstrProfiling 268 ../profile/InstrProfilingBuffer 269 ../profile/InstrProfilingPlatformDarwin) 270 foreach (os ${ARGN}) 271 list_union(DARWIN_BUILTIN_ARCHS DARWIN_${os}_ARCHS BUILTIN_SUPPORTED_ARCH) 272 foreach (arch ${DARWIN_BUILTIN_ARCHS}) 273 darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS 274 OS ${os} 275 ARCH ${arch} 276 MIN_VERSION ${DARWIN_${os}_BUILTIN_MIN_VER}) 277 278 darwin_filter_builtin_sources(filtered_sources 279 EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS 280 ${${arch}_SOURCES}) 281 282 darwin_add_builtin_library(clang_rt builtins 283 OS ${os} 284 ARCH ${arch} 285 SOURCES ${filtered_sources} 286 CFLAGS -arch ${arch} 287 PARENT_TARGET builtins) 288 endforeach() 289 290 # Don't build cc_kext libraries for simulator platforms 291 if(NOT DARWIN_${os}_SKIP_CC_KEXT) 292 foreach (arch ${DARWIN_BUILTIN_ARCHS}) 293 # By not specifying MIN_VERSION this only reads the OS and OS-arch lists. 294 # We don't want to filter out the builtins that are present in libSystem 295 # because kexts can't link libSystem. 296 darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS 297 OS ${os} 298 ARCH ${arch}) 299 300 darwin_filter_builtin_sources(filtered_sources 301 EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS 302 ${${arch}_SOURCES}) 303 304 # In addition to the builtins cc_kext includes some profile sources 305 darwin_add_builtin_library(clang_rt cc_kext 306 OS ${os} 307 ARCH ${arch} 308 SOURCES ${filtered_sources} ${PROFILE_SOURCES} 309 CFLAGS -arch ${arch} -mkernel 310 DEFS KERNEL_USE 311 PARENT_TARGET builtins) 312 endforeach() 313 set(archive_name clang_rt.cc_kext_${os}) 314 if(${os} STREQUAL "osx") 315 set(archive_name clang_rt.cc_kext) 316 endif() 317 darwin_lipo_libs(${archive_name} 318 PARENT_TARGET builtins 319 LIPO_FLAGS ${${os}_cc_kext_lipo_flags} 320 DEPENDS ${${os}_cc_kext_libs} 321 OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR} 322 INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR}) 323 endif() 324 endforeach() 325 326 darwin_add_eprintf_library() 327 328 # We put the x86 sim slices into the archives for their base OS 329 foreach (os ${ARGN}) 330 if(NOT ${os} MATCHES ".*sim$") 331 darwin_lipo_libs(clang_rt.${os} 332 PARENT_TARGET builtins 333 LIPO_FLAGS ${${os}_builtins_lipo_flags} ${${os}sim_builtins_lipo_flags} 334 DEPENDS ${${os}_builtins_libs} ${${os}sim_builtins_libs} 335 OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR} 336 INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR}) 337 endif() 338 endforeach() 339 darwin_add_embedded_builtin_libraries() 340endmacro() 341 342function(darwin_add_embedded_builtin_libraries) 343 set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded) 344 if(CMAKE_CONFIGURATION_TYPES) 345 foreach(type ${CMAKE_CONFIGURATION_TYPES}) 346 set(CMAKE_C_FLAGS_${type} -Oz) 347 set(CMAKE_CXX_FLAGS_${type} -Oz) 348 endforeach() 349 else() 350 set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE} -Oz) 351 endif() 352 353 set(CMAKE_C_FLAGS "-Wall -fomit-frame-pointer -ffreestanding") 354 set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) 355 set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) 356 357 set(SOFT_FLOAT_FLAG -mfloat-abi=soft) 358 set(HARD_FLOAT_FLAG -mfloat-abi=hard) 359 360 set(PIC_FLAG_ -fPIC) 361 set(STATIC_FLAG -static) 362 363 set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64) 364 365 set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR 366 ${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded) 367 set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR 368 ${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded) 369 370 set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") 371 set(CFLAGS_armv7em "-target thumbv7-apple-darwin-eabi") 372 set(CFLAGS_armv7m "-target thumbv7-apple-darwin-eabi") 373 set(CFLAGS_i386 "-march=pentium") 374 375 set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7) 376 set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7 i386 x86_64) 377 378 darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt) 379 darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt) 380 darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt) 381 darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt) 382 darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt) 383 384 385 set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS}) 386 set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) 387 set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) 388 set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS}) 389 set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS}) 390 set(x86_64_FUNCTIONS ${common_FUNCTIONS}) 391 392 foreach(arch ${DARWIN_macho_embedded_ARCHS}) 393 darwin_filter_builtin_sources(${arch}_filtered_sources 394 INCLUDE ${arch}_FUNCTIONS 395 ${${arch}_SOURCES}) 396 if(NOT ${arch}_filtered_sources) 397 message("${arch}_SOURCES: ${${arch}_SOURCES}") 398 message("${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}") 399 message(FATAL_ERROR "Empty filtered sources!") 400 endif() 401 endforeach() 402 403 foreach(float_type SOFT HARD) 404 foreach(type PIC STATIC) 405 string(TOLOWER "${float_type}_${type}" lib_suffix) 406 foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS}) 407 set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT}) 408 set(DARWIN_macho_embedded_BUILTIN_MIN_VER_FLAG ${DARWIN_osx_BUILTIN_MIN_VER_FLAG}) 409 set(float_flag) 410 if(${arch} MATCHES "^arm") 411 set(DARWIN_macho_embedded_SYSROOT ${DARWIN_ios_SYSROOT}) 412 # x86 targets are hard float by default, but the complain about the 413 # float ABI flag, so don't pass it unless we're targeting arm. 414 set(float_flag ${${float_type}_FLOAT_FLAG}) 415 endif() 416 darwin_add_builtin_library(clang_rt ${lib_suffix} 417 OS macho_embedded 418 ARCH ${arch} 419 SOURCES ${${arch}_filtered_sources} 420 CFLAGS -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}} 421 PARENT_TARGET builtins) 422 endforeach() 423 foreach(lib ${macho_embedded_${lib_suffix}_libs}) 424 set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C) 425 endforeach() 426 darwin_lipo_libs(clang_rt.${lib_suffix} 427 PARENT_TARGET builtins 428 LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags} 429 DEPENDS ${macho_embedded_${lib_suffix}_libs} 430 OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR} 431 INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR}) 432 endforeach() 433 endforeach() 434endfunction() 435