xref: /aosp_15_r20/external/skia/toolchain/download_ios_toolchain.bzl (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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