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