Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 4e33c10

Browse files
authored
[macOS] Generate universal gen_snapshots (#52885)
Previously, the `gen_snapshot_arm64` and `gen_snapshot_x64` binaries used by the tool were all built for x64 architecture. As such, developers building apps with Flutter rely on Rosetta translation with every build. This refactors the gen_snapshot build rules on macOS hosts to consistently produce `gen_snapshot_arm64` and `gen_snapshot_x64` binaries with the target architecture of the build but with as universal binaries with both host architectures. ### arm64 host build Prior to this patch we emitted: * gen_snapshot_arm64 (arch: x64, target_arch: simarm64) After this patch, we emit: * artifacts_x64/gen_snapshot_arm64 (arch: x64, target_arch: simarm64) * artifacts_arm64/gen_snapshot_arm64 (arch: arm64, target_arch: arm64) * gen_snapshot_arm64 (universal binary composed of both of the above) ### x64 host build Prior to this patch we emitted: * gen_snapshot_x64 (arch: x64, target_arch: x64) After this patch, we emit: * artifacts_x64/gen_snapshot_x64 (arch: x64, target_arch: x64) * artifacts_arm64/gen_snapshot_x64 (arch: arm64, target_arch: simx64) * gen_snapshot_x64 (universal binary composed of both of the above) Note that host builds on macOS currently default to a host architecture of x64 (can be overridden via `--force-mac-arm64`) regardless of host architecture and thus, the build itself relies on Rosetta translation when invoked on Apple Silicon arm64 hardware. This is to ensure a consistent build in CI regardless of bot architecture. See: https://github.com/flutter/engine/blob/6fa734d686888a39add026a2a98d6ec311c23efb/tools/gn#L502-L505 Issue: flutter/flutter#101138 Issue: flutter/flutter#69157 Related issue: flutter/flutter#103386 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 93f1b5a commit 4e33c10

File tree

4 files changed

+103
-10
lines changed

4 files changed

+103
-10
lines changed

build/archives/BUILD.gn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ if (is_mac) {
287287
output = "$full_platform_name$suffix/gen_snapshot.zip"
288288
files = [
289289
{
290-
source = "$root_out_dir/gen_snapshot_$target_cpu"
291-
destination = "gen_snapshot_$target_cpu"
290+
source = "${root_out_dir}/gen_snapshot_${target_cpu}"
291+
destination = "gen_snapshot_${target_cpu}"
292292
},
293293
]
294294
}

ci/licenses_golden/excluded_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@
416416
../../../flutter/sky/tools/create_embedder_framework.py
417417
../../../flutter/sky/tools/create_full_ios_framework.py
418418
../../../flutter/sky/tools/create_ios_framework.py
419+
../../../flutter/sky/tools/create_macos_binary.py
419420
../../../flutter/sky/tools/create_macos_framework.py
420421
../../../flutter/sky/tools/create_macos_gen_snapshots.py
421422
../../../flutter/sky/tools/create_xcframework.py

lib/snapshot/BUILD.gn

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,16 +186,54 @@ if (host_os == "mac" && target_os != "mac" &&
186186
#
187187
# This target is used for builds targeting macOS.
188188
if (host_os == "mac" && target_os == "mac") {
189-
copy("create_macos_gen_snapshots") {
190-
# The toolchain-specific output directory. For cross-compiles, this is a
191-
# clang-x64 or clang-arm64 subdirectory of the top-level build directory.
192-
host_output_dir =
193-
get_label_info("$dart_src/runtime/bin:gen_snapshot($host_toolchain)",
194-
"root_out_dir")
189+
template("build_mac_gen_snapshot") {
190+
assert(defined(invoker.host_arch))
191+
host_cpu = invoker.host_arch
195192

196-
sources = [ "${host_output_dir}/gen_snapshot" ]
193+
build_toolchain = "//build/toolchain/mac:clang_$host_cpu"
194+
if (host_cpu == target_cpu) {
195+
gen_snapshot_target_name = "gen_snapshot_host_targeting_host"
196+
} else {
197+
gen_snapshot_target_name = "gen_snapshot"
198+
}
199+
gen_snapshot_target =
200+
"$dart_src/runtime/bin:$gen_snapshot_target_name($build_toolchain)"
201+
202+
copy(target_name) {
203+
# The toolchain-specific output directory. For cross-compiles, this is a
204+
# clang-x64 or clang-arm64 subdirectory of the top-level build directory.
205+
output_dir = get_label_info(gen_snapshot_target, "root_out_dir")
206+
207+
sources = [ "${output_dir}/${gen_snapshot_target_name}" ]
208+
outputs =
209+
[ "${root_out_dir}/artifacts_$host_cpu/gen_snapshot_${target_cpu}" ]
210+
deps = [ gen_snapshot_target ]
211+
}
212+
}
213+
214+
build_mac_gen_snapshot("create_macos_gen_snapshot_arm64_${target_cpu}") {
215+
host_arch = "arm64"
216+
}
217+
218+
build_mac_gen_snapshot("create_macos_gen_snapshot_x64_${target_cpu}") {
219+
host_arch = "x64"
220+
}
221+
222+
action("create_macos_gen_snapshots") {
223+
script = "//flutter/sky/tools/create_macos_binary.py"
197224
outputs = [ "${root_out_dir}/gen_snapshot_${target_cpu}" ]
198-
deps = [ "$dart_src/runtime/bin:gen_snapshot($host_toolchain)" ]
225+
args = [
226+
"--in-arm64",
227+
rebase_path("${root_out_dir}/artifacts_arm64/gen_snapshot_${target_cpu}"),
228+
"--in-x64",
229+
rebase_path("${root_out_dir}/artifacts_x64/gen_snapshot_${target_cpu}"),
230+
"--out",
231+
rebase_path("${root_out_dir}/gen_snapshot_${target_cpu}"),
232+
]
233+
deps = [
234+
":create_macos_gen_snapshot_arm64_${target_cpu}",
235+
":create_macos_gen_snapshot_x64_${target_cpu}",
236+
]
199237
}
200238
}
201239

sky/tools/create_macos_binary.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright 2013 The Flutter Authors. All rights reserved.
4+
# Use of this source code is governed by a BSD-style license that can be
5+
# found in the LICENSE file.
6+
7+
import argparse
8+
import os
9+
import subprocess
10+
import sys
11+
12+
13+
def canonical_path(path):
14+
"""Returns the canonical path for the input path.
15+
If the input path is not absolute, it is treated as relative to the engine
16+
source tree's buildroot directory."""
17+
if os.path.isabs(path):
18+
return path
19+
buildroot_dir = os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..', '..', '..'))
20+
return os.path.join(buildroot_dir, path)
21+
22+
23+
def assert_file_exists(binary_path, arch):
24+
if not os.path.isfile(binary_path):
25+
print('Cannot find macOS %s binary at %s' % (arch, binary_path))
26+
sys.exit(1)
27+
28+
29+
def create_universal_binary(in_arm64, in_x64, out):
30+
subprocess.check_call(['lipo', in_arm64, in_x64, '-create', '-output', out])
31+
32+
33+
def main():
34+
parser = argparse.ArgumentParser(
35+
description='Creates a universal binary from input arm64, x64 binaries'
36+
)
37+
parser.add_argument('--in-arm64', type=str, required=True)
38+
parser.add_argument('--in-x64', type=str, required=True)
39+
parser.add_argument('--out', type=str, required=True)
40+
args = parser.parse_args()
41+
42+
in_arm64 = canonical_path(args.in_arm64)
43+
in_x64 = canonical_path(args.in_x64)
44+
out = canonical_path(args.out)
45+
46+
assert_file_exists(in_arm64, 'arm64')
47+
assert_file_exists(in_x64, 'x64')
48+
create_universal_binary(in_arm64, in_x64, out)
49+
50+
return 0
51+
52+
53+
if __name__ == '__main__':
54+
sys.exit(main())

0 commit comments

Comments
 (0)