• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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