1""" 2This file assembles a toolchain for a Mac host (either M1 or Intel) 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/mac_toolchain_config.bzl) 9 10The destination folder for these files and symlinks are: 11 [outputRoot (aka Bazel cache)]/[outputUserRoot]/[outputBase]/external/clang_mac 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-17.0.6 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-17.0.6-arm64-apple-darwin22.0" 22clang_sha256_arm64 = "1264eb3c2a4a6d5e9354c3e5dc5cb6c6481e678f6456f36d2e0e566e9400fcad" 23clang_url_arm64 = "https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang+llvm-17.0.6-arm64-apple-darwin22.0.tar.xz" 24clang_ver_arm64 = "17" 25 26# No x86_64-apple binaries published by llvm-project beyond 15. 27# TODO: find a different toolchain source. 28clang_prefix_amd64 = "clang+llvm-15.0.1-x86_64-apple-darwin" 29clang_sha256_amd64 = "0b2f1a811e68d011344103274733b7670c15bbe08b2a3a5140ccad8e19d9311e" 30clang_url_amd64 = "https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.1/clang+llvm-15.0.1-x86_64-apple-darwin.tar.xz" 31clang_ver_amd64 = "15.0.1" 32 33def _get_system_sdk_path(ctx): 34 res = ctx.execute(["xcrun", "--sdk", "macosx", "--show-sdk-path"]) 35 if res.return_code != 0: 36 fail("Error Getting SDK path: " + res.stderr) 37 return res.stdout.rstrip() 38 39def _delete_macos_sdk_symlinks(ctx): 40 ctx.delete("./symlinks/xcode/MacSDK/usr") 41 ctx.delete("./symlinks/xcode/MacSDK/System/Library/Frameworks") 42 43def _create_macos_sdk_symlinks(ctx): 44 system_sdk_path = _get_system_sdk_path(ctx) 45 46 # https://bazel.build/rules/lib/actions#symlink 47 ctx.symlink( 48 # from = 49 system_sdk_path + "/usr", 50 # to = 51 "./symlinks/xcode/MacSDK/usr", 52 ) 53 54 # It is very important to symlink the frameworks directory to [sysroot]/System/Library/Frameworks 55 # because some Frameworks "re-export" other frameworks. These framework paths are relative to 56 # the sysroot (which on a typical machine is /), and it is difficult to change these paths. 57 # By making the symlinks emulate the original path structure, we can keep those re-exports 58 # from breaking. 59 ctx.symlink( 60 # from = 61 system_sdk_path + "/System/Library/Frameworks", 62 # to = 63 "./symlinks/xcode/MacSDK/System/Library/Frameworks", 64 ) 65 66def _download_mac_toolchain_impl(ctx): 67 # https://bazel.build/rules/lib/repository_ctx#os 68 # https://bazel.build/rules/lib/repository_os 69 if ctx.os.arch == "aarch64": 70 clang_ver = clang_ver_arm64 71 clang_url = clang_url_arm64 72 clang_sha256 = clang_sha256_arm64 73 clang_prefix = clang_prefix_arm64 74 else: 75 clang_ver = clang_ver_amd64 76 clang_url = clang_url_amd64 77 clang_sha256 = clang_sha256_amd64 78 clang_prefix = clang_prefix_amd64 79 80 # Download the clang toolchain (the extraction can take a while) 81 # https://bazel.build/rules/lib/repository_ctx#download_and_extract 82 ctx.download_and_extract( 83 url = gcs_mirror_url(clang_url, clang_sha256), 84 output = "", 85 stripPrefix = clang_prefix, 86 sha256 = clang_sha256, 87 ) 88 89 # Some std library headers use #include_next to include system specific headers, and 90 # some skia source files require Xcode headers when compiling, (see SkTypes.h and look 91 # for TargetedConditionals.h)) All of these are located in Xcode, stopping the Mac 92 # builds from being purely hermetic. 93 # For now, we can grab the user's Xcode path by calling xcode-select and create a symlink in 94 # our toolchain directory to refer to during compilation. 95 96 _delete_macos_sdk_symlinks(ctx) 97 _create_macos_sdk_symlinks(ctx) 98 99 # This list of files lines up with _make_default_flags() in mac_toolchain_config.bzl 100 # It is all locations that our toolchain could find a system header. 101 builtin_include_directories = [ 102 "include/c++/v1", 103 "lib/clang/" + clang_ver + "/include", 104 # Frameworks is a symlink, and the trailing slash is intentional 105 # (to ensure traversal in generate_system_module_map.sh's find). 106 "symlinks/xcode/MacSDK/System/Library/Frameworks/", 107 "symlinks/xcode/MacSDK/usr/include", 108 ] 109 110 generate_system_module_map( 111 ctx, 112 module_file = "toolchain_system_headers.modulemap", 113 folders = builtin_include_directories, 114 ) 115 116 # Create a BUILD.bazel file that makes the files necessary for compiling, 117 # linking and creating archive files visible to Bazel. 118 # The smaller the globs are, the more performant the sandboxed builds will be. 119 # Additionally, globs that are too wide can pick up infinite symlink loops, 120 # and be difficult to quash: https://github.com/bazelbuild/bazel/issues/13950 121 # https://bazel.build/rules/lib/repository_ctx#file 122 ctx.file( 123 "BUILD.bazel", 124 content = """ 125# DO NOT EDIT THIS BAZEL FILE DIRECTLY 126# Generated from ctx.file action in download_mac_toolchain.bzl 127filegroup( 128 name = "generated_module_map", 129 srcs = ["toolchain_system_headers.modulemap"], 130 visibility = ["//visibility:public"], 131) 132 133filegroup( 134 name = "archive_files", 135 srcs = [ 136 "bin/llvm-ar", 137 ], 138 visibility = ["//visibility:public"], 139) 140 141# Any framework that Skia depends on directly or indirectly needs to be listed here. 142FRAMEWORK_GLOB = [ 143 "symlinks/xcode/MacSDK/System/Library/Frameworks/AppKit.Framework/**", 144 "symlinks/xcode/MacSDK/System/Library/Frameworks/ApplicationServices.Framework/**", 145 "symlinks/xcode/MacSDK/System/Library/Frameworks/AVFAudio.Framework/**", 146 "symlinks/xcode/MacSDK/System/Library/Frameworks/AVFoundation.Framework/**", 147 "symlinks/xcode/MacSDK/System/Library/Frameworks/Carbon.Framework/**", 148 "symlinks/xcode/MacSDK/System/Library/Frameworks/CFNetwork.Framework/**", 149 "symlinks/xcode/MacSDK/System/Library/Frameworks/CloudKit.Framework/**", 150 "symlinks/xcode/MacSDK/System/Library/Frameworks/Cocoa.Framework/**", 151 "symlinks/xcode/MacSDK/System/Library/Frameworks/ColorSync.Framework/**", 152 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreData.Framework/**", 153 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreAudio.Framework/**", 154 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreAudioTypes.Framework/**", 155 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreFoundation.Framework/**", 156 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreGraphics.Framework/**", 157 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreImage.Framework/**", 158 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreLocation.Framework/**", 159 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreMedia.Framework/**", 160 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreMIDI.Framework/**", 161 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreServices.Framework/**", 162 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreText.Framework/**", 163 "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreVideo.Framework/**", 164 "symlinks/xcode/MacSDK/System/Library/Frameworks/DiskArbitration.Framework/**", 165 "symlinks/xcode/MacSDK/System/Library/Frameworks/Foundation.Framework/**", 166 "symlinks/xcode/MacSDK/System/Library/Frameworks/ImageIO.Framework/**", 167 "symlinks/xcode/MacSDK/System/Library/Frameworks/IOKit.Framework/**", 168 "symlinks/xcode/MacSDK/System/Library/Frameworks/IOSurface.Framework/**", 169 "symlinks/xcode/MacSDK/System/Library/Frameworks/Metal.Framework/**", 170 "symlinks/xcode/MacSDK/System/Library/Frameworks/MetalKit.Framework/**", 171 "symlinks/xcode/MacSDK/System/Library/Frameworks/ModelIO.Framework/**", 172 "symlinks/xcode/MacSDK/System/Library/Frameworks/OpenGL.Framework/**", 173 "symlinks/xcode/MacSDK/System/Library/Frameworks/QuartzCore.Framework/**", 174 "symlinks/xcode/MacSDK/System/Library/Frameworks/Security.Framework/**", 175 "symlinks/xcode/MacSDK/System/Library/Frameworks/Symbols.Framework/**", 176 "symlinks/xcode/MacSDK/System/Library/Frameworks/UniformTypeIdentifiers.framework/**", 177] 178 179filegroup( 180 name = "compile_files", 181 srcs = [ 182 "bin/clang", 183 ] + glob( 184 include = [ 185 "include/c++/v1/**", 186 "lib/clang/*/include/**", 187 "symlinks/xcode/MacSDK/usr/include/**", 188 ], 189 allow_empty = False, 190 ) + glob( 191 # Frameworks are SDK-dependent, and can vary between releases. 192 # We attempt to capture a super-set. 193 include = FRAMEWORK_GLOB, 194 allow_empty = True, 195 ), 196 visibility = ["//visibility:public"], 197) 198 199filegroup( 200 name = "link_files", 201 srcs = [ 202 "bin/clang", 203 "bin/ld.lld", 204 "bin/lld", 205 "lib/libc++.a", 206 "lib/libc++abi.a", 207 "lib/libunwind.a", 208 ] + glob( 209 include = [ 210 # libc++.tbd and libSystem.tbd live here. 211 "symlinks/xcode/MacSDK/usr/lib/*", 212 ], 213 allow_empty = False, 214 ) + glob( 215 # Frameworks are SDK-dependent, and can vary between releases. 216 # We attempt to capture a super-set. 217 include = FRAMEWORK_GLOB, 218 allow_empty = True, 219 ), 220 visibility = ["//visibility:public"], 221) 222""", 223 executable = False, 224 ) 225 226# https://bazel.build/rules/repository_rules 227download_mac_toolchain = repository_rule( 228 implementation = _download_mac_toolchain_impl, 229 attrs = {}, 230 doc = "Downloads clang to build Skia with." + 231 "Assumes you have xcode located on your device and have" + 232 "xcode-select in your $PATH.", 233) 234