Skip to content

Commit 83c230f

Browse files
Support cross compilation in macOS toolchain builds (#434)
Updates the build script used in SwiftCI for building the `docc` executable as part of Swift.org toolchains to support cross compilation. Currently the `docc` executable included in the otherwise universal macOS toolchain only supports x86_64. This resolves the issue. Resolves rdar://102870094 Closes #433
1 parent 3a3abff commit 83c230f

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

build-script-helper.py

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
from __future__ import print_function
1717

1818
import argparse
19+
import json
1920
import sys
2021
import os, platform
22+
import re
2123
import subprocess
2224

2325
def printerr(message):
@@ -43,6 +45,7 @@ def parse_args(args):
4345
parser.add_argument('--install-dir', default=None, help='The location to install the docc executable to.')
4446
parser.add_argument('--copy-doccrender-from', default=None, help='The location to copy an existing Swift-DocC-Render template from.')
4547
parser.add_argument('--copy-doccrender-to', default=None, help='The location to install an existing Swift-DocC-Render template to.')
48+
parser.add_argument("--cross-compile-hosts", dest="cross_compile_hosts", help="List of cross compile hosts targets.", default=[])
4649

4750
parsed = parser.parse_args(args)
4851

@@ -167,8 +170,16 @@ def get_swiftpm_options(action, args):
167170
# Library rpath for swift, dispatch, Foundation, etc. when installing
168171
'-Xlinker', '-rpath', '-Xlinker', '$ORIGIN/../lib/swift/linux',
169172
]
170-
171-
if action == 'install':
173+
174+
build_target = get_build_target(args)
175+
cross_compile_hosts = args.cross_compile_hosts
176+
if cross_compile_hosts:
177+
if re.search('-apple-macosx', build_target) and re.match('macosx-', cross_compile_hosts):
178+
swiftpm_args += ["--arch", "x86_64", "--arch", "arm64"]
179+
else:
180+
printerr("cannot cross-compile for %s" % cross_compile_hosts)
181+
182+
if action == 'install' or action == 'show-bin-path':
172183
# When tests are run on the host machine, `docc` is located in the build directory; to find
173184
# its linked libraries (Swift runtime dependencies), `docc` needs to link against the host
174185
# machine's toolchain libraries. When installing docc on the target machine, the `docc`
@@ -178,6 +189,9 @@ def get_swiftpm_options(action, args):
178189
if action == 'test':
179190
swiftpm_args += ['--parallel']
180191

192+
if action == 'show-bin-path':
193+
swiftpm_args += ['--show-bin-path']
194+
181195
return swiftpm_args
182196

183197
def invoke_swift(action, products, env, args, swiftpm_args):
@@ -186,7 +200,7 @@ def invoke_swift(action, products, env, args, swiftpm_args):
186200
for product in products:
187201
invoke_swift_single_product(action, product, env, args, swiftpm_args)
188202

189-
def invoke_swift_single_product(action, product, env, args, swiftpm_args):
203+
def get_call_to_invoke_swift_single_product(action, product, args, swiftpm_args):
190204
call = [args.swift_exec, action] + swiftpm_args
191205

192206
if platform.system() != 'Darwin':
@@ -197,6 +211,16 @@ def invoke_swift_single_product(action, product, env, args, swiftpm_args):
197211
call.extend(['--test-product', product])
198212
else:
199213
call.extend(['--product', product])
214+
215+
return call
216+
217+
def invoke_swift_single_product(action, product, env, args, swiftpm_args):
218+
call = get_call_to_invoke_swift_single_product(
219+
action=action,
220+
product=product,
221+
args=args,
222+
swiftpm_args=swiftpm_args
223+
)
200224

201225
# Tell Swift-DocC that we are building in a build-script environment so that
202226
# it does not need to be rebuilt if it has already been built before.
@@ -217,7 +241,6 @@ def install(args, env):
217241
verbose=args.verbose
218242
# Find the docc executable location
219243
docc_path = docc_bin_path(
220-
swift_exec=os.path.join(os.path.join(args.toolchain, 'bin'), 'swift'),
221244
args=args,
222245
env=env,
223246
verbose=verbose
@@ -245,17 +268,29 @@ def install(args, env):
245268
install_path=copy_render_to,
246269
verbose=verbose
247270
)
271+
272+
def get_build_target(args):
273+
"""Returns the target-triple of the current machine or for cross-compilation."""
274+
# Adapted from https://github.com/apple/swift-package-manager/blob/fde9916d/Utilities/bootstrap#L296
275+
command = [args.swift_exec, '-print-target-info']
276+
target_info_json = subprocess.check_output(command, stderr=subprocess.PIPE, universal_newlines=True).strip()
277+
args.target_info = json.loads(target_info_json)
278+
if platform.system() == 'Darwin':
279+
return args.target_info["target"]["unversionedTriple"]
280+
281+
return args.target_info["target"]["triple"]
282+
283+
def docc_bin_path(args, env, verbose):
284+
cmd = get_call_to_invoke_swift_single_product(
285+
action='build',
286+
product='docc',
287+
args=args,
288+
swiftpm_args=get_swiftpm_options(
289+
action='show-bin-path',
290+
args=args
291+
)
292+
)
248293

249-
def docc_bin_path(swift_exec, args, env, verbose):
250-
cmd = [
251-
swift_exec,
252-
'build',
253-
'--show-bin-path',
254-
'--package-path', args.package_path,
255-
'--scratch-path', args.build_dir,
256-
'--configuration', args.configuration,
257-
'--product', 'docc'
258-
]
259294
if verbose:
260295
print(' '.join([escape_cmd_arg(arg) for arg in cmd]))
261296
return os.path.join(

0 commit comments

Comments
 (0)