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-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 25clang_prefix_amd64 = "clang+llvm-15.0.1-x86_64-apple-darwin" 26clang_sha256_amd64 = "0b2f1a811e68d011344103274733b7670c15bbe08b2a3a5140ccad8e19d9311e" 27clang_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" 28 29def _get_system_xcode_path(ctx): 30 # https://developer.apple.com/library/archive/technotes/tn2339/_index.html 31 res = ctx.execute(["xcode-select", "-p"]) 32 if res.return_code != 0: 33 fail("Error Getting XCode path: " + res.stderr) 34 return res.stdout.rstrip() 35 36def _delete_macos_sdk_symlinks(ctx): 37 ctx.delete("./symlinks/xcode/MacSDK/usr") 38 ctx.delete("./symlinks/xcode/MacSDK/Frameworks") 39 40def _create_macos_sdk_symlinks(ctx): 41 system_xcode_path = _get_system_xcode_path(ctx) 42 43 # https://bazel.build/rules/lib/actions#symlink 44 ctx.symlink( 45 # from = 46 system_xcode_path + "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr", 47 # to = 48 "./symlinks/xcode/MacSDK/usr", 49 ) 50 ctx.symlink( 51 # from = 52 system_xcode_path + "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks", 53 # to = 54 "./symlinks/xcode/MacSDK/Frameworks", 55 ) 56 57def _download_mac_toolchain_impl(ctx): 58 # https://bazel.build/rules/lib/repository_ctx#os 59 # https://bazel.build/rules/lib/repository_os 60 if ctx.os.arch == "aarch64": 61 clang_url = clang_url_arm64 62 clang_sha256 = clang_sha256_arm64 63 clang_prefix = clang_prefix_arm64 64 else: 65 clang_url = clang_url_amd64 66 clang_sha256 = clang_sha256_amd64 67 clang_prefix = clang_prefix_amd64 68 69 # Download the clang toolchain (the extraction can take a while) 70 # https://bazel.build/rules/lib/repository_ctx#download_and_extract 71 ctx.download_and_extract( 72 url = gcs_mirror_url(clang_url, clang_sha256), 73 output = "", 74 stripPrefix = clang_prefix, 75 sha256 = clang_sha256, 76 ) 77 78 # Some std library headers use #include_next to include system specific headers, and 79 # some skia source files require Xcode headers when compiling, (see SkTypes.h and look 80 # for TargetedConditionals.h)) All of these are located in Xcode, stopping the Mac 81 # builds from being purely hermetic. 82 # For now, we can grab the user's Xcode path by calling xcode-select and create a symlink in 83 # our toolchain directory to refer to during compilation. 84 85 _delete_macos_sdk_symlinks(ctx) 86 _create_macos_sdk_symlinks(ctx) 87 88 # This list of files lines up with _make_default_flags() in mac_toolchain_config.bzl 89 # It is all locations that our toolchain could find a system header. 90 builtin_include_directories = [ 91 "include/c++/v1", 92 "lib/clang/15.0.1/include", 93 "symlinks/xcode/MacSDK/Frameworks", 94 "symlinks/xcode/MacSDK/usr/include", 95 ] 96 97 generate_system_module_map( 98 ctx, 99 module_file = "toolchain_system_headers.modulemap", 100 folders = builtin_include_directories, 101 ) 102 103 # Create a BUILD.bazel file that makes the files necessary for compiling, 104 # linking and creating archive files visible to Bazel. 105 # The smaller the globs are, the more performant the sandboxed builds will be. 106 # Additionally, globs that are too wide can pick up infinite symlink loops, 107 # and be difficult to quash: https://github.com/bazelbuild/bazel/issues/13950 108 # https://bazel.build/rules/lib/repository_ctx#file 109 ctx.file( 110 "BUILD.bazel", 111 content = """ 112# DO NOT EDIT THIS BAZEL FILE DIRECTLY 113# Generated from ctx.file action in download_mac_toolchain.bzl 114filegroup( 115 name = "generated_module_map", 116 srcs = ["toolchain_system_headers.modulemap"], 117 visibility = ["//visibility:public"], 118) 119 120filegroup( 121 name = "archive_files", 122 srcs = [ 123 "bin/llvm-ar", 124 ], 125 visibility = ["//visibility:public"], 126) 127 128filegroup( 129 name = "compile_files", 130 srcs = [ 131 "bin/clang", 132 ] + glob( 133 include = [ 134 "include/c++/v1/**", 135 "lib/clang/15.0.1/include/**", 136 "symlinks/xcode/MacSDK/Frameworks/AppKit.Framework/**", 137 "symlinks/xcode/MacSDK/Frameworks/ApplicationServices.Framework/**", 138 "symlinks/xcode/MacSDK/Frameworks/Carbon.Framework/**", 139 "symlinks/xcode/MacSDK/Frameworks/CFNetwork.Framework/**", 140 "symlinks/xcode/MacSDK/Frameworks/CloudKit.Framework/**", 141 "symlinks/xcode/MacSDK/Frameworks/Cocoa.Framework/**", 142 "symlinks/xcode/MacSDK/Frameworks/ColorSync.Framework/**", 143 "symlinks/xcode/MacSDK/Frameworks/CoreData.Framework/**", 144 "symlinks/xcode/MacSDK/Frameworks/CoreFoundation.Framework/**", 145 "symlinks/xcode/MacSDK/Frameworks/CoreGraphics.Framework/**", 146 "symlinks/xcode/MacSDK/Frameworks/CoreImage.Framework/**", 147 "symlinks/xcode/MacSDK/Frameworks/CoreLocation.Framework/**", 148 "symlinks/xcode/MacSDK/Frameworks/CoreServices.Framework/**", 149 "symlinks/xcode/MacSDK/Frameworks/CoreText.Framework/**", 150 "symlinks/xcode/MacSDK/Frameworks/CoreVideo.Framework/**", 151 "symlinks/xcode/MacSDK/Frameworks/DiskArbitration.Framework/**", 152 "symlinks/xcode/MacSDK/Frameworks/Foundation.Framework/**", 153 "symlinks/xcode/MacSDK/Frameworks/ImageIO.Framework/**", 154 "symlinks/xcode/MacSDK/Frameworks/IOKit.Framework/**", 155 "symlinks/xcode/MacSDK/Frameworks/IOSurface.Framework/**", 156 "symlinks/xcode/MacSDK/Frameworks/Metal.Framework/**", 157 "symlinks/xcode/MacSDK/Frameworks/OpenGL.Framework/**", 158 "symlinks/xcode/MacSDK/Frameworks/QuartzCore.Framework/**", 159 "symlinks/xcode/MacSDK/Frameworks/Security.Framework/**", 160 "symlinks/xcode/MacSDK/usr/include/**", 161 ], 162 allow_empty = False, 163 ), 164 visibility = ["//visibility:public"], 165) 166 167filegroup( 168 name = "link_files", 169 srcs = [ 170 "bin/clang", 171 "bin/ld.lld", 172 "bin/lld", 173 "lib/libc++.a", 174 "lib/libc++abi.a", 175 "lib/libunwind.a", 176 ] + glob( 177 include = [ 178 # libc++.tbd and libSystem.tbd live here. 179 "symlinks/xcode/MacSDK/usr/lib/*", 180 ], 181 allow_empty = False, 182 ), 183 visibility = ["//visibility:public"], 184) 185""", 186 executable = False, 187 ) 188 189# https://bazel.build/rules/repository_rules 190download_mac_toolchain = repository_rule( 191 implementation = _download_mac_toolchain_impl, 192 attrs = {}, 193 doc = "Downloads clang to build Skia with." + 194 "Assumes you have xcode located on your device and have" + 195 "xcode-select in your $PATH.", 196) 197