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