1""" 2This file assembles a toolchain for cross compiling on a Mac host for iOS using the Clang Compiler 3and a locally-installed XCode. 4 5It downloads the necessary executables and creates symlinks in the external subfolder of the Bazel 6cache (the same place third party deps are downloaded with http_archive or similar functions in 7WORKSPACE.bazel). These will be able to be used via our 8custom c++ toolchain configuration (see //toolchain/ios_toolchain_config.bzl) 9 10The destination folder for these files and symlinks are: 11 [outputRoot (aka Bazel cache)]/[outputUserRoot]/[outputBase]/external/clang_ios 12 (See https://bazel.build/docs/output_directories#layout-diagram) 13""" 14 15load(":clang_layering_check.bzl", "generate_system_module_map") 16load(":utils.bzl", "gcs_mirror_url") 17 18# From https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.1 19# When updating this, don't forget to use //bazel/gcs_mirror to upload a new version. 20# go run bazel/gcs_mirror/gcs_mirror.go --url [clang_url] --sha256 [clang_sha256] 21clang_prefix_arm64 = "clang+llvm-15.0.1-arm64-apple-darwin21.0" 22clang_sha256_arm64 = "858f86d96b5e4880f69f7a583daddbf97ee94e7cffce0d53aa05cba6967f13b8" 23clang_url_arm64 = "https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.1/clang+llvm-15.0.1-arm64-apple-darwin21.0.tar.xz" 24 25ios_sdk_root = "/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/" 26 27def _get_system_xcode_path(ctx): 28 # https://developer.apple.com/library/archive/technotes/tn2339/_index.html 29 res = ctx.execute(["xcode-select", "--print-path"]) 30 if res.return_code != 0: 31 fail("Error Getting XCode path: " + res.stderr) 32 return res.stdout.rstrip() 33 34def _delete_ios_sdk_symlinks(ctx): 35 ctx.delete("./symlinks/xcode/iOSSDK/usr") 36 ctx.delete("./symlinks/xcode/iOSSDK/System/Library/Frameworks") 37 38def _create_ios_sdk_symlinks(ctx): 39 system_xcode_path = _get_system_xcode_path(ctx) 40 41 # https://bazel.build/rules/lib/actions#symlink 42 ctx.symlink( 43 # from = 44 system_xcode_path + ios_sdk_root + "usr", 45 # to = 46 "./symlinks/xcode/iOSSDK/usr", 47 ) 48 49 # It is very important to symlink the frameworks directory to [sysroot]/System/Library/Frameworks 50 # because some Frameworks "re-export" other frameworks. These framework paths are relative to 51 # the sysroot (which on a typical machine is /), and it is difficult to change these paths. 52 # By making the symlinks emulate the original path structure, we can keep those re-exports 53 # from breaking. 54 ctx.symlink( 55 # from = 56 system_xcode_path + ios_sdk_root + "System/Library/Frameworks", 57 # to = 58 "./symlinks/xcode/iOSSDK/System/Library/Frameworks", 59 ) 60 61def _download_ios_toolchain_impl(ctx): 62 # Download the clang toolchain (the extraction can take a while) 63 # https://bazel.build/rules/lib/repository_ctx#download_and_extract 64 ctx.download_and_extract( 65 url = gcs_mirror_url(clang_url_arm64, clang_sha256_arm64), 66 output = "", 67 stripPrefix = clang_prefix_arm64, 68 sha256 = clang_sha256_arm64, 69 ) 70 71 # Some std library headers use #include_next to include system specific headers, and 72 # some skia source files require Xcode headers when compiling, (see SkTypes.h and look 73 # for TargetedConditionals.h)) All of these are located in Xcode, stopping the Mac 74 # builds from being purely hermetic. 75 # For now, we can grab the user's Xcode path by calling xcode-select and create a symlink in 76 # our toolchain directory to refer to during compilation. 77 78 _delete_ios_sdk_symlinks(ctx) 79 _create_ios_sdk_symlinks(ctx) 80 81 # This list of files lines up with _make_default_flags() in ios_toolchain_config.bzl 82 # It is all locations that our toolchain could find a system header. 83 builtin_include_directories = [ 84 "include/c++/v1", 85 "lib/clang/15.0.1/include", 86 "symlinks/xcode/iOSSDK/System/Library/Frameworks", 87 "symlinks/xcode/iOSSDK/usr/include", 88 ] 89 90 generate_system_module_map( 91 ctx, 92 module_file = "toolchain_system_headers.modulemap", 93 folders = builtin_include_directories, 94 ) 95 96 # Create a BUILD.bazel file that makes the files necessary for compiling, 97 # linking and creating archive files visible to Bazel. 98 # The smaller the globs are, the more performant the sandboxed builds will be. 99 # Additionally, globs that are too wide can pick up infinite symlink loops, 100 # and be difficult to quash: https://github.com/bazelbuild/bazel/issues/13950 101 # https://bazel.build/rules/lib/repository_ctx#file 102 ctx.file( 103 "BUILD.bazel", 104 content = """ 105# DO NOT EDIT THIS BAZEL FILE DIRECTLY 106# Generated from ctx.file action in download_ios_toolchain.bzl 107filegroup( 108 name = "generated_module_map", 109 srcs = ["toolchain_system_headers.modulemap"], 110 visibility = ["//visibility:public"], 111) 112 113filegroup( 114 name = "archive_files", 115 srcs = [ 116 "bin/llvm-ar", 117 ], 118 visibility = ["//visibility:public"], 119) 120 121# Any framework that Skia depends on directly or indirectly needs to be listed here. 122FRAMEWORK_GLOB = [ 123 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CFNetwork.Framework/**", 124 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CloudKit.Framework/**", 125 "symlinks/xcode/iOSSDK/System/Library/Frameworks/ColorSync.Framework/**", 126 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreData.Framework/**", 127 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreFoundation.Framework/**", 128 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreGraphics.Framework/**", 129 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreImage.Framework/**", 130 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreLocation.Framework/**", 131 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreServices.Framework/**", 132 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreText.Framework/**", 133 "symlinks/xcode/iOSSDK/System/Library/Frameworks/CoreVideo.Framework/**", 134 "symlinks/xcode/iOSSDK/System/Library/Frameworks/Foundation.Framework/**", 135 "symlinks/xcode/iOSSDK/System/Library/Frameworks/ImageIO.Framework/**", 136 "symlinks/xcode/iOSSDK/System/Library/Frameworks/IOKit.Framework/**", 137 "symlinks/xcode/iOSSDK/System/Library/Frameworks/IOSurface.Framework/**", 138 "symlinks/xcode/iOSSDK/System/Library/Frameworks/Metal.Framework/**", 139 "symlinks/xcode/iOSSDK/System/Library/Frameworks/MetalKit.Framework/**", 140 "symlinks/xcode/iOSSDK/System/Library/Frameworks/MobileCoreServices.Framework/**", 141 "symlinks/xcode/iOSSDK/System/Library/Frameworks/ModelIO.Framework/**", 142 "symlinks/xcode/iOSSDK/System/Library/Frameworks/OpenGLES.Framework/**", 143 "symlinks/xcode/iOSSDK/System/Library/Frameworks/QuartzCore.Framework/**", 144 "symlinks/xcode/iOSSDK/System/Library/Frameworks/Security.Framework/**", 145 "symlinks/xcode/iOSSDK/System/Library/Frameworks/Symbols.Framework/**", 146 "symlinks/xcode/iOSSDK/System/Library/Frameworks/UIKit.Framework/**", 147 "symlinks/xcode/iOSSDK/System/Library/Frameworks/UserNotifications.Framework/**", 148] 149 150filegroup( 151 name = "compile_files", 152 srcs = [ 153 "bin/clang", 154 ] + glob( 155 include = [ 156 "include/c++/v1/**", 157 "lib/clang/15.0.1/include/**", 158 "symlinks/xcode/iOSSDK/usr/include/**", 159 ] + FRAMEWORK_GLOB, 160 allow_empty = False, 161 ), 162 visibility = ["//visibility:public"], 163) 164 165filegroup( 166 name = "link_files", 167 srcs = [ 168 "bin/clang", 169 "bin/ld.lld", 170 "bin/lld", 171 "lib/libc++.a", 172 "lib/libc++abi.a", 173 "lib/libunwind.a", 174 ] + glob( 175 include = [ 176 # libc++.tbd and libSystem.tbd live here. 177 "symlinks/xcode/iOSSDK/usr/lib/*", 178 ] + FRAMEWORK_GLOB, 179 allow_empty = False, 180 ), 181 visibility = ["//visibility:public"], 182) 183""", 184 executable = False, 185 ) 186 187# https://bazel.build/rules/repository_rules 188download_ios_toolchain = repository_rule( 189 implementation = _download_ios_toolchain_impl, 190 attrs = {}, 191 doc = "Downloads clang to build Skia with." + 192 "Assumes you have xcode located on your device and have" + 193 "xcode-select in your $PATH.", 194) 195