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 if(DARWIN_${LIB_OS}_SYSROOT) 165 set(sysroot_flag -isysroot ${DARWIN_${LIB_OS}_SYSROOT}) 166 endif() 167 set_target_compile_flags(${libname} 168 ${sysroot_flag} 169 ${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG} 170 ${LIB_CFLAGS}) 171 set_property(TARGET ${libname} APPEND PROPERTY 172 COMPILE_DEFINITIONS ${LIB_DEFS}) 173 set_target_properties(${libname} PROPERTIES 174 OUTPUT_NAME ${libname}${COMPILER_RT_OS_SUFFIX}) 175 set_target_properties(${libname} PROPERTIES 176 OSX_ARCHITECTURES ${LIB_ARCH}) 177 178 if(LIB_PARENT_TARGET) 179 add_dependencies(${LIB_PARENT_TARGET} ${libname}) 180 endif() 181 182 list(APPEND ${LIB_OS}_${suffix}_libs ${libname}) 183 list(APPEND ${LIB_OS}_${suffix}_lipo_flags -arch ${arch} $<TARGET_FILE:${libname}>) 184endmacro() 185 186function(darwin_lipo_libs name) 187 cmake_parse_arguments(LIB 188 "" 189 "PARENT_TARGET;OUTPUT_DIR;INSTALL_DIR" 190 "LIPO_FLAGS;DEPENDS" 191 ${ARGN}) 192 if(LIB_DEPENDS AND LIB_LIPO_FLAGS) 193 add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a 194 COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR} 195 COMMAND lipo -output 196 ${LIB_OUTPUT_DIR}/lib${name}.a 197 -create ${LIB_LIPO_FLAGS} 198 DEPENDS ${LIB_DEPENDS} 199 ) 200 add_custom_target(${name} 201 DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a) 202 add_dependencies(${LIB_PARENT_TARGET} ${name}) 203 install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a 204 DESTINATION ${LIB_INSTALL_DIR}) 205 else() 206 message(WARNING "Not generating lipo target for ${name} because no input libraries exist.") 207 endif() 208endfunction() 209 210# Filter out generic versions of routines that are re-implemented in 211# architecture specific manner. This prevents multiple definitions of the 212# same symbols, making the symbol selection non-deterministic. 213function(darwin_filter_builtin_sources output_var exclude_or_include excluded_list) 214 if(exclude_or_include STREQUAL "EXCLUDE") 215 set(filter_action GREATER) 216 set(filter_value -1) 217 elseif(exclude_or_include STREQUAL "INCLUDE") 218 set(filter_action LESS) 219 set(filter_value 0) 220 else() 221 message(FATAL_ERROR "darwin_filter_builtin_sources called without EXCLUDE|INCLUDE") 222 endif() 223 224 set(intermediate ${ARGN}) 225 foreach (_file ${intermediate}) 226 get_filename_component(_name_we ${_file} NAME_WE) 227 list(FIND ${excluded_list} ${_name_we} _found) 228 if(_found ${filter_action} ${filter_value}) 229 list(REMOVE_ITEM intermediate ${_file}) 230 elseif(${_file} MATCHES ".*/.*\\.S" OR ${_file} MATCHES ".*/.*\\.c") 231 get_filename_component(_name ${_file} NAME) 232 string(REPLACE ".S" ".c" _cname "${_name}") 233 list(REMOVE_ITEM intermediate ${_cname}) 234 endif () 235 endforeach () 236 set(${output_var} ${intermediate} PARENT_SCOPE) 237endfunction() 238 239function(darwin_add_eprintf_library) 240 add_library(clang_rt.eprintf STATIC eprintf.c) 241 set_target_compile_flags(clang_rt.eprintf 242 -isysroot ${DARWIN_osx_SYSROOT} 243 ${DARWIN_osx_BUILTIN_MIN_VER_FLAG} 244 -arch i386) 245 set_target_properties(clang_rt.eprintf PROPERTIES 246 OUTPUT_NAME clang_rt.eprintf${COMPILER_RT_OS_SUFFIX}) 247 set_target_properties(clang_rt.eprintf PROPERTIES 248 OSX_ARCHITECTURES i386) 249 add_dependencies(builtins clang_rt.eprintf) 250 set_target_properties(clang_rt.eprintf PROPERTIES 251 ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) 252 install(TARGETS clang_rt.eprintf 253 ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) 254endfunction() 255 256# Generates builtin libraries for all operating systems specified in ARGN. Each 257# OS library is constructed by lipo-ing together single-architecture libraries. 258macro(darwin_add_builtin_libraries) 259 set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes) 260 261 set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer") 262 set(CMAKE_C_FLAGS "") 263 set(CMAKE_CXX_FLAGS "") 264 set(CMAKE_ASM_FLAGS "") 265 266 set(PROFILE_SOURCES ../profile/InstrProfiling 267 ../profile/InstrProfilingBuffer 268 ../profile/InstrProfilingPlatformDarwin) 269 foreach (os ${ARGN}) 270 list_union(DARWIN_BUILTIN_ARCHS DARWIN_${os}_ARCHS BUILTIN_SUPPORTED_ARCH) 271 foreach (arch ${DARWIN_BUILTIN_ARCHS}) 272 darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS 273 OS ${os} 274 ARCH ${arch} 275 MIN_VERSION ${DARWIN_${os}_BUILTIN_MIN_VER}) 276 277 darwin_filter_builtin_sources(filtered_sources 278 EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS 279 ${${arch}_SOURCES}) 280 281 darwin_add_builtin_library(clang_rt builtins 282 OS ${os} 283 ARCH ${arch} 284 SOURCES ${filtered_sources} 285 CFLAGS ${CFLAGS} -arch ${arch} 286 PARENT_TARGET builtins) 287 endforeach() 288 289 # Don't build cc_kext libraries for simulator platforms 290 if(NOT DARWIN_${os}_SKIP_CC_KEXT) 291 foreach (arch ${DARWIN_BUILTIN_ARCHS}) 292 # By not specifying MIN_VERSION this only reads the OS and OS-arch lists. 293 # We don't want to filter out the builtins that are present in libSystem 294 # because kexts can't link libSystem. 295 darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS 296 OS ${os} 297 ARCH ${arch}) 298 299 darwin_filter_builtin_sources(filtered_sources 300 EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS 301 ${${arch}_SOURCES}) 302 303 # In addition to the builtins cc_kext includes some profile sources 304 darwin_add_builtin_library(clang_rt cc_kext 305 OS ${os} 306 ARCH ${arch} 307 SOURCES ${filtered_sources} ${PROFILE_SOURCES} 308 CFLAGS ${CFLAGS} -arch ${arch} -mkernel 309 DEFS KERNEL_USE 310 PARENT_TARGET builtins) 311 endforeach() 312 set(archive_name clang_rt.cc_kext_${os}) 313 if(${os} STREQUAL "osx") 314 set(archive_name clang_rt.cc_kext) 315 endif() 316 darwin_lipo_libs(${archive_name} 317 PARENT_TARGET builtins 318 LIPO_FLAGS ${${os}_cc_kext_lipo_flags} 319 DEPENDS ${${os}_cc_kext_libs} 320 OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR} 321 INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR}) 322 endif() 323 endforeach() 324 325 darwin_add_eprintf_library() 326 327 # We put the x86 sim slices into the archives for their base OS 328 foreach (os ${ARGN}) 329 if(NOT ${os} MATCHES ".*sim$") 330 darwin_lipo_libs(clang_rt.${os} 331 PARENT_TARGET builtins 332 LIPO_FLAGS ${${os}_builtins_lipo_flags} ${${os}sim_builtins_lipo_flags} 333 DEPENDS ${${os}_builtins_libs} ${${os}sim_builtins_libs} 334 OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR} 335 INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR}) 336 endif() 337 endforeach() 338 darwin_add_embedded_builtin_libraries() 339endmacro() 340 341macro(darwin_add_embedded_builtin_libraries) 342 # this is a hacky opt-out. If you can't target both intel and arm 343 # architectures we bail here. 344 set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7) 345 set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7) 346 if(COMPILER_RT_SUPPORTED_ARCH MATCHES ".*armv.*") 347 list(FIND COMPILER_RT_SUPPORTED_ARCH i386 i386_idx) 348 if(i386_idx GREATER -1) 349 list(APPEND DARWIN_HARD_FLOAT_ARCHS i386) 350 endif() 351 352 list(FIND COMPILER_RT_SUPPORTED_ARCH x86_64 x86_64_idx) 353 if(x86_64_idx GREATER -1) 354 list(APPEND DARWIN_HARD_FLOAT_ARCHS x86_64) 355 endif() 356 357 set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded) 358 359 set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding") 360 set(CMAKE_C_FLAGS "") 361 set(CMAKE_CXX_FLAGS "") 362 set(CMAKE_ASM_FLAGS "") 363 364 set(SOFT_FLOAT_FLAG -mfloat-abi=soft) 365 set(HARD_FLOAT_FLAG -mfloat-abi=hard) 366 367 set(ENABLE_PIC Off) 368 set(PIC_FLAG -fPIC) 369 set(STATIC_FLAG -static) 370 371 set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64) 372 373 set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR 374 ${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded) 375 set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR 376 ${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded) 377 378 set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") 379 set(CFLAGS_i386 "-march=pentium") 380 381 darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt) 382 darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt) 383 darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt) 384 darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt) 385 darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt) 386 387 388 set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS}) 389 set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) 390 set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) 391 set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS}) 392 set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS}) 393 set(x86_64_FUNCTIONS ${common_FUNCTIONS}) 394 395 foreach(arch ${DARWIN_macho_embedded_ARCHS}) 396 darwin_filter_builtin_sources(${arch}_filtered_sources 397 INCLUDE ${arch}_FUNCTIONS 398 ${${arch}_SOURCES}) 399 if(NOT ${arch}_filtered_sources) 400 message("${arch}_SOURCES: ${${arch}_SOURCES}") 401 message("${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}") 402 message(FATAL_ERROR "Empty filtered sources!") 403 endif() 404 endforeach() 405 406 foreach(float_type SOFT HARD) 407 foreach(type PIC STATIC) 408 string(TOLOWER "${float_type}_${type}" lib_suffix) 409 foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS}) 410 set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT}) 411 set(float_flag) 412 if(${arch} MATCHES "^arm") 413 # x86 targets are hard float by default, but the complain about the 414 # float ABI flag, so don't pass it unless we're targeting arm. 415 set(float_flag ${${float_type}_FLOAT_FLAG}) 416 endif() 417 darwin_add_builtin_library(clang_rt ${lib_suffix} 418 OS macho_embedded 419 ARCH ${arch} 420 SOURCES ${${arch}_filtered_sources} 421 CFLAGS ${CFLAGS} -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}} 422 PARENT_TARGET builtins) 423 endforeach() 424 foreach(lib ${macho_embedded_${lib_suffix}_libs}) 425 set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C) 426 endforeach() 427 darwin_lipo_libs(clang_rt.${lib_suffix} 428 PARENT_TARGET builtins 429 LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags} 430 DEPENDS ${macho_embedded_${lib_suffix}_libs} 431 OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR} 432 INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR}) 433 endforeach() 434 endforeach() 435 endif() 436endmacro() 437