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

Commit 3bc1b81

Browse files
authored
Support building the engine on Apple Silicon Macs (#33244)
This adds support for the following builds: * macOS host builds on both x86_64 and arm64 Macs. * macOS target builds on both x86_64 and arm64 Macs. Previously, macOS target builds for any architecture were possible only on x86_64 Macs. Similarly, macOS host builds were only supported on x86_64 Macs, and only for the x86_64 architecture. arm64 host builds were not possible on Intel Macs. When building on arm64 macs, builds are performed under Rosetta for two reasons: * The Fuchsia clang toolchain for arm64 macOS is not yet available. * Swiftshader (used by our engine tests) doesn't support building OpenGL support as an arm64 binary. See: flutter/flutter#103386 Followup patches will move our use of Swiftshader to a "Swangle" (Swiftshader + ANGLE) configuration, eliminating the Swiftshader issue above. Issue: flutter/flutter#96745 Issue: flutter/flutter#79403
1 parent 15faf6d commit 3bc1b81

File tree

1 file changed

+73
-14
lines changed

1 file changed

+73
-14
lines changed

tools/gn

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import argparse
1111
import subprocess
1212
import sys
1313
import os
14+
import platform
1415

1516
SRC_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
1617

@@ -89,8 +90,6 @@ def is_host_build(args):
8990
# If target_os == None, then this is a host build.
9091
# However, for linux arm64 builds, we cross compile from x64 hosts, so the
9192
# target_os='linux' and linux-cpu='arm64'
92-
# TODO(fujino): make host platform explicit
93-
# https://github.com/flutter/flutter/issues/79403
9493
return args.target_os is None or (args.target_os == 'linux' and args.linux_cpu == 'arm64')
9594

9695
# Determines whether a prebuilt Dart SDK can be used instead of building one.
@@ -121,6 +120,47 @@ def can_use_prebuilt_dart(args):
121120
return prebuilts_dir != None and os.path.isdir(prebuilts_dir)
122121

123122

123+
# Returns the host machine operating system.
124+
def get_host_os():
125+
if sys.platform.startswith(('cygwin', 'win')):
126+
return 'win'
127+
if sys.platform == 'darwin':
128+
return 'mac'
129+
return 'linux'
130+
131+
132+
# Runs true if the currently executing python interpreter is running under
133+
# Rosetta. I.e., python3 is an x64 executable and we're on an arm64 Mac.
134+
def is_rosetta():
135+
if platform.system() == 'Darwin':
136+
p = subprocess.Popen(['sysctl', '-in', 'sysctl.proc_translated'],
137+
stdout=subprocess.PIPE,
138+
stderr=subprocess.STDOUT)
139+
output, _ = p.communicate()
140+
return output.decode('utf-8').strip() == '1'
141+
return False
142+
143+
144+
# Returns the host machine CPU architecture.
145+
def get_host_cpu(args):
146+
# If gn itself is running under Rosetta on an arm64 Mac, platform.machine()
147+
# will return x86_64; instead return the underlying host architecture.
148+
if is_rosetta():
149+
return 'arm64'
150+
m = platform.machine()
151+
if m in ['aarch64', 'arm64']:
152+
return 'arm64'
153+
if m in ['x86_64', 'AMD64', 'x64']:
154+
return 'x64'
155+
if m in ['i686', 'i386', 'x86']:
156+
return 'x86'
157+
raise Exception('Unknown CPU architecture: %s' % m)
158+
159+
160+
# Returns the target CPU architecture.
161+
#
162+
# For macOS host builds where --mac-cpu is specified, returns that value.
163+
# For all other host builds, assumes 'x64'.
124164
def get_target_cpu(args):
125165
if args.target_os == 'android':
126166
return args.android_cpu
@@ -139,7 +179,10 @@ def get_target_cpu(args):
139179
return 'wasm'
140180
if args.target_os == 'win':
141181
return args.windows_cpu
142-
# Building host artifacts. Default to x64.
182+
183+
# Host build. Default to x64 unless overridden.
184+
if get_host_os() == 'mac' and args.mac_cpu:
185+
return args.mac_cpu
143186
return 'x64'
144187

145188

@@ -212,19 +255,39 @@ def to_gn_args(args):
212255
# The GN arg is not available in the windows toolchain.
213256
gn_args['enable_lto'] = enable_lto
214257

215-
if args.target_os:
258+
# Set OS, CPU arch for host or target build.
259+
if is_host_build(args):
260+
gn_args['host_os'] = get_host_os()
261+
gn_args['host_cpu'] = get_host_cpu(args)
262+
gn_args['target_os'] = gn_args['host_os']
263+
gn_args['target_cpu'] = get_target_cpu(args)
264+
gn_args['dart_target_arch'] = gn_args['target_cpu']
265+
else:
216266
gn_args['target_os'] = args.target_os
217-
gn_args['target_cpu'] = get_target_cpu(args)
218-
gn_args['dart_target_arch'] = gn_args['target_cpu']
267+
gn_args['target_cpu'] = get_target_cpu(args)
268+
gn_args['dart_target_arch'] = gn_args['target_cpu']
219269

220-
# No cross-compilation on Windows (for now).
221-
# See: https://github.com/flutter/engine/pull/3883
270+
# No cross-compilation on Windows (for now). Use host toolchain that
271+
# matches the bit-width of the target architecture.
222272
if sys.platform.startswith(('cygwin', 'win')) and args.target_os != 'win':
273+
gn_args['host_cpu'] = cpu_for_target_arch(gn_args['target_cpu'])
223274
gn_args['target_cpu'] = cpu_for_target_arch(gn_args['target_cpu'])
224275

225-
if args.target_os == 'ios':
276+
# macOS host builds (whether x64 or arm64) must currently be built under
277+
# Rosetta on Apple Silicon Macs.
278+
# TODO(cbracken): https://github.com/flutter/flutter/issues/103386
279+
if is_host_build(args) and gn_args['host_os'] == 'mac':
280+
gn_args['host_cpu'] = 'x64'
281+
282+
# macOS target builds (whether x64 or arm64) must currently be built under
283+
# Rosetta on Apple Silicon Macs.
284+
# TODO(cbracken): https://github.com/flutter/flutter/issues/103386
285+
if 'target_os' in gn_args and gn_args['target_os'] == 'mac':
286+
gn_args['host_cpu'] = 'x64'
287+
288+
if gn_args['target_os'] == 'ios':
226289
gn_args['use_ios_simulator'] = args.simulator
227-
elif args.target_os == 'mac':
290+
elif gn_args['target_os'] == 'mac':
228291
gn_args['use_ios_simulator'] = False
229292

230293
if args.dart_debug:
@@ -275,10 +338,6 @@ def to_gn_args(args):
275338
if sys.platform.startswith(('cygwin', 'win')):
276339
gn_args['dart_use_fallback_root_certificates'] = True
277340

278-
# Make sure host_cpu matches the bit width of target_cpu on x86.
279-
if gn_args['target_cpu'] == 'x86':
280-
gn_args['host_cpu'] = 'x86'
281-
282341
if args.target_sysroot:
283342
gn_args['target_sysroot'] = args.target_sysroot
284343
gn_args['custom_sysroot'] = args.target_sysroot

0 commit comments

Comments
 (0)