xref: /aosp_15_r20/external/skia/toolchain/download_mac_toolchain.bzl (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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", "--print-path"])
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/System/Library/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
51    # It is very important to symlink the frameworks directory to [sysroot]/System/Library/Frameworks
52    # because some Frameworks "re-export" other frameworks. These framework paths are relative to
53    # the sysroot (which on a typical machine is /), and it is difficult to change these paths.
54    # By making the symlinks emulate the original path structure, we can keep those re-exports
55    # from breaking.
56    ctx.symlink(
57        # from =
58        system_xcode_path + "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks",
59        # to =
60        "./symlinks/xcode/MacSDK/System/Library/Frameworks",
61    )
62
63def _download_mac_toolchain_impl(ctx):
64    # https://bazel.build/rules/lib/repository_ctx#os
65    # https://bazel.build/rules/lib/repository_os
66    if ctx.os.arch == "aarch64":
67        clang_url = clang_url_arm64
68        clang_sha256 = clang_sha256_arm64
69        clang_prefix = clang_prefix_arm64
70    else:
71        clang_url = clang_url_amd64
72        clang_sha256 = clang_sha256_amd64
73        clang_prefix = clang_prefix_amd64
74
75    # Download the clang toolchain (the extraction can take a while)
76    # https://bazel.build/rules/lib/repository_ctx#download_and_extract
77    ctx.download_and_extract(
78        url = gcs_mirror_url(clang_url, clang_sha256),
79        output = "",
80        stripPrefix = clang_prefix,
81        sha256 = clang_sha256,
82    )
83
84    # Some std library headers use #include_next to include system specific headers, and
85    # some skia source files require Xcode headers when compiling, (see SkTypes.h and look
86    # for TargetedConditionals.h)) All of these are located in Xcode, stopping the Mac
87    # builds from being purely hermetic.
88    # For now, we can grab the user's Xcode path by calling xcode-select and create a symlink in
89    # our toolchain directory to refer to during compilation.
90
91    _delete_macos_sdk_symlinks(ctx)
92    _create_macos_sdk_symlinks(ctx)
93
94    # This list of files lines up with _make_default_flags() in mac_toolchain_config.bzl
95    # It is all locations that our toolchain could find a system header.
96    builtin_include_directories = [
97        "include/c++/v1",
98        "lib/clang/15.0.1/include",
99        "symlinks/xcode/MacSDK/System/Library/Frameworks",
100        "symlinks/xcode/MacSDK/usr/include",
101    ]
102
103    generate_system_module_map(
104        ctx,
105        module_file = "toolchain_system_headers.modulemap",
106        folders = builtin_include_directories,
107    )
108
109    # Create a BUILD.bazel file that makes the files necessary for compiling,
110    # linking and creating archive files visible to Bazel.
111    # The smaller the globs are, the more performant the sandboxed builds will be.
112    # Additionally, globs that are too wide can pick up infinite symlink loops,
113    # and be difficult to quash: https://github.com/bazelbuild/bazel/issues/13950
114    # https://bazel.build/rules/lib/repository_ctx#file
115    ctx.file(
116        "BUILD.bazel",
117        content = """
118# DO NOT EDIT THIS BAZEL FILE DIRECTLY
119# Generated from ctx.file action in download_mac_toolchain.bzl
120filegroup(
121    name = "generated_module_map",
122    srcs = ["toolchain_system_headers.modulemap"],
123    visibility = ["//visibility:public"],
124)
125
126filegroup(
127    name = "archive_files",
128    srcs = [
129        "bin/llvm-ar",
130    ],
131    visibility = ["//visibility:public"],
132)
133
134# Any framework that Skia depends on directly or indirectly needs to be listed here.
135FRAMEWORK_GLOB = [
136    "symlinks/xcode/MacSDK/System/Library/Frameworks/AppKit.Framework/**",
137    "symlinks/xcode/MacSDK/System/Library/Frameworks/ApplicationServices.Framework/**",
138    "symlinks/xcode/MacSDK/System/Library/Frameworks/Carbon.Framework/**",
139    "symlinks/xcode/MacSDK/System/Library/Frameworks/CFNetwork.Framework/**",
140    "symlinks/xcode/MacSDK/System/Library/Frameworks/CloudKit.Framework/**",
141    "symlinks/xcode/MacSDK/System/Library/Frameworks/Cocoa.Framework/**",
142    "symlinks/xcode/MacSDK/System/Library/Frameworks/ColorSync.Framework/**",
143    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreData.Framework/**",
144    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreFoundation.Framework/**",
145    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreGraphics.Framework/**",
146    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreImage.Framework/**",
147    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreLocation.Framework/**",
148    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreServices.Framework/**",
149    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreText.Framework/**",
150    "symlinks/xcode/MacSDK/System/Library/Frameworks/CoreVideo.Framework/**",
151    "symlinks/xcode/MacSDK/System/Library/Frameworks/DiskArbitration.Framework/**",
152    "symlinks/xcode/MacSDK/System/Library/Frameworks/Foundation.Framework/**",
153    "symlinks/xcode/MacSDK/System/Library/Frameworks/ImageIO.Framework/**",
154    "symlinks/xcode/MacSDK/System/Library/Frameworks/IOKit.Framework/**",
155    "symlinks/xcode/MacSDK/System/Library/Frameworks/IOSurface.Framework/**",
156    "symlinks/xcode/MacSDK/System/Library/Frameworks/Metal.Framework/**",
157    "symlinks/xcode/MacSDK/System/Library/Frameworks/MetalKit.Framework/**",
158    "symlinks/xcode/MacSDK/System/Library/Frameworks/OpenGL.Framework/**",
159    "symlinks/xcode/MacSDK/System/Library/Frameworks/QuartzCore.Framework/**",
160    "symlinks/xcode/MacSDK/System/Library/Frameworks/Security.Framework/**",
161]
162
163filegroup(
164    name = "compile_files",
165    srcs = [
166        "bin/clang",
167    ] + glob(
168        include = [
169            "include/c++/v1/**",
170            "lib/clang/15.0.1/include/**",
171            "symlinks/xcode/MacSDK/usr/include/**",
172        ] + FRAMEWORK_GLOB,
173        allow_empty = False,
174    ),
175    visibility = ["//visibility:public"],
176)
177
178filegroup(
179    name = "link_files",
180    srcs = [
181        "bin/clang",
182        "bin/ld.lld",
183        "bin/lld",
184        "lib/libc++.a",
185        "lib/libc++abi.a",
186        "lib/libunwind.a",
187    ] + glob(
188        include = [
189            # libc++.tbd and libSystem.tbd live here.
190            "symlinks/xcode/MacSDK/usr/lib/*",
191        ] + FRAMEWORK_GLOB,
192        allow_empty = False,
193    ),
194    visibility = ["//visibility:public"],
195)
196""",
197        executable = False,
198    )
199
200# https://bazel.build/rules/repository_rules
201download_mac_toolchain = repository_rule(
202    implementation = _download_mac_toolchain_impl,
203    attrs = {},
204    doc = "Downloads clang to build Skia with." +
205          "Assumes you have xcode located on your device and have" +
206          "xcode-select in your $PATH.",
207)
208