Skip to content

Commit 1ba8317

Browse files
authored
Merge pull request #36917 from buttaface/swiftpm
[build] Allow cross-compiling build-script products for non-Darwin hosts too
2 parents 2ab97ed + e9eb3b0 commit 1ba8317

File tree

10 files changed

+138
-51
lines changed

10 files changed

+138
-51
lines changed

utils/build_swift/build_swift/driver_arguments.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,11 @@ def create_argument_parser():
563563
help='A space separated list of targets to cross-compile host '
564564
'Swift tools for. Can be used multiple times.')
565565

566+
option('--cross-compile-deps-path', store_path,
567+
help='The path to a directory that contains prebuilt cross-compiled '
568+
'library dependencies of the corelibs and other Swift repos, '
569+
'such as the libcurl dependency of FoundationNetworking')
570+
566571
option('--stdlib-deployment-targets', store,
567572
type=argparse.ShellSplitType(),
568573
default=None,

utils/build_swift/tests/expected_options.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
'cmark_build_variant': 'Debug',
132132
'compiler_vendor': defaults.COMPILER_VENDOR,
133133
'coverage_db': None,
134+
'cross_compile_deps_path': None,
134135
'cross_compile_hosts': [],
135136
'darwin_deployment_version_ios':
136137
defaults.DARWIN_DEPLOYMENT_VERSION_IOS,
@@ -696,6 +697,7 @@ class BuildScriptImplOption(_BaseOption):
696697
PathOption('--clang-profile-instr-use'),
697698
PathOption('--cmake'),
698699
PathOption('--coverage-db'),
700+
PathOption('--cross-compile-deps-path'),
699701
PathOption('--host-cc'),
700702
PathOption('--host-cxx'),
701703
PathOption('--host-libtool'),

utils/swift_build_support/swift_build_support/build_script_invocation.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ def convert_to_impl_arguments(self):
181181
if args.cross_compile_hosts:
182182
impl_args += [
183183
"--cross-compile-hosts", " ".join(args.cross_compile_hosts)]
184+
if args.cross_compile_deps_path is not None:
185+
impl_args += [
186+
"--cross-compile-deps-path=%s" % args.cross_compile_deps_path
187+
]
184188

185189
if args.test_paths:
186190
impl_args += ["--test-paths", " ".join(args.test_paths)]
@@ -664,12 +668,14 @@ def execute(self):
664668
self._execute_impl(pipeline, all_hosts, perform_epilogue_opts)
665669
else:
666670
assert(index != last_impl_index)
667-
# Once we have performed our last impl pipeline, we no longer
668-
# support cross compilation.
669-
#
670-
# This just maintains current behavior.
671671
if index > last_impl_index:
672-
self._execute(pipeline, [self.args.host_target])
672+
non_darwin_cross_compile_hostnames = [
673+
target for target in self.args.cross_compile_hosts if not
674+
StdlibDeploymentTarget.get_target_for_name(
675+
target).platform.is_darwin
676+
]
677+
self._execute(pipeline, [self.args.host_target] +
678+
non_darwin_cross_compile_hostnames)
673679
else:
674680
self._execute(pipeline, all_host_names)
675681

@@ -727,6 +733,8 @@ def _execute_impl(self, pipeline, all_hosts, should_run_epilogue_operations):
727733

728734
def _execute(self, pipeline, all_host_names):
729735
for host_target in all_host_names:
736+
if self.args.skip_local_build and host_target == self.args.host_target:
737+
continue
730738
for product_class in pipeline:
731739
# Execute clean, build, test, install
732740
self.execute_product_build_steps(product_class, host_target)

utils/swift_build_support/swift_build_support/products/benchmarks.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ def _get_toolchain_path(host_target, product, args):
104104
# this logic initially was inside run_build_script_helper
105105
# and was factored out so it can be used in testing as well
106106

107-
toolchain_path = swiftpm.SwiftPM.get_install_destdir(args,
108-
host_target,
109-
product.build_dir)
107+
toolchain_path = product.host_install_destdir(host_target)
110108
if platform.system() == 'Darwin':
111109
# The prefix is an absolute path, so concatenate without os.path.
112110
toolchain_path += \

utils/swift_build_support/swift_build_support/products/indexstoredb.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,8 @@ def run_build_script_helper(action, host_target, product, args,
8080
script_path = os.path.join(
8181
product.source_dir, 'Utilities', 'build-script-helper.py')
8282

83-
install_destdir = args.install_destdir
84-
if swiftpm.SwiftPM.has_cross_compile_hosts(args):
85-
install_destdir = swiftpm.SwiftPM.get_install_destdir(args,
86-
host_target,
87-
product.build_dir)
88-
toolchain_path = targets.toolchain_path(install_destdir,
89-
args.install_prefix)
83+
install_destdir = product.host_install_destdir(host_target)
84+
toolchain_path = product.native_toolchain_path(host_target)
9085
is_release = product.is_release()
9186
configuration = 'release' if is_release else 'debug'
9287
helper_cmd = [
@@ -110,4 +105,22 @@ def run_build_script_helper(action, host_target, product, args,
110105
elif args.enable_tsan:
111106
helper_cmd.extend(['--sanitize', 'thread'])
112107

108+
if not product.is_darwin_host(
109+
host_target) and product.is_cross_compile_target(host_target):
110+
helper_cmd.extend(['--cross-compile-host', host_target])
111+
build_toolchain_path = install_destdir + args.install_prefix
112+
resource_dir = '%s/lib/swift' % build_toolchain_path
113+
helper_cmd += [
114+
'--cross-compile-config',
115+
targets.StdlibDeploymentTarget.get_target_for_name(host_target).platform
116+
.swiftpm_config(args, output_dir=build_toolchain_path,
117+
swift_toolchain=toolchain_path,
118+
resource_path=resource_dir)
119+
]
120+
121+
if action == 'install' and product.product_name() == "sourcekitlsp":
122+
helper_cmd.extend([
123+
'--prefix', install_destdir + args.install_prefix
124+
])
125+
113126
shell.call(helper_cmd)

utils/swift_build_support/swift_build_support/products/product.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,18 +195,23 @@ def install_toolchain_path(self, host_target):
195195
"""toolchain_path() -> string
196196
197197
Returns the path to the toolchain that is being created as part of this
198-
build, or to a native prebuilt toolchain that was passed in.
198+
build
199199
"""
200-
if self.args.native_swift_tools_path is not None:
201-
return os.path.split(self.args.native_swift_tools_path)[0]
202-
203200
install_destdir = self.args.install_destdir
204201
if self.args.cross_compile_hosts:
205-
build_root = os.path.dirname(self.build_dir)
206-
install_destdir = '%s/intermediate-install/%s' % (build_root, host_target)
202+
if self.is_darwin_host(host_target):
203+
install_destdir = self.host_install_destdir(host_target)
204+
else:
205+
install_destdir = os.path.join(install_destdir, self.args.host_target)
207206
return targets.toolchain_path(install_destdir,
208207
self.args.install_prefix)
209208

209+
def native_toolchain_path(self, host_target):
210+
if self.args.native_swift_tools_path is not None:
211+
return os.path.split(self.args.native_swift_tools_path)[0]
212+
else:
213+
return self.install_toolchain_path(host_target)
214+
210215
def is_darwin_host(self, host_target):
211216
return host_target.startswith("macosx") or \
212217
host_target.startswith("iphone") or \

utils/swift_build_support/swift_build_support/products/skstresstester.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,7 @@ def should_install(self, host_target):
100100
return self.args.install_skstresstester
101101

102102
def install(self, host_target):
103-
install_destdir = swiftpm.SwiftPM.get_install_destdir(self.args,
104-
host_target,
105-
self.build_dir)
103+
install_destdir = self.host_install_destdir(host_target)
106104
install_prefix = install_destdir + self.args.install_prefix
107105
self.run_build_script_helper('install', host_target, [
108106
'--prefix', install_prefix

utils/swift_build_support/swift_build_support/products/swiftdriver.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,8 @@ def run_build_script_helper(action, host_target, product, args):
8686
script_path = os.path.join(
8787
product.source_dir, 'Utilities', 'build-script-helper.py')
8888

89-
install_destdir = args.install_destdir
90-
if swiftpm.SwiftPM.has_cross_compile_hosts(args):
91-
install_destdir = swiftpm.SwiftPM.get_install_destdir(args,
92-
host_target,
93-
product.build_dir)
94-
toolchain_path = targets.toolchain_path(install_destdir,
95-
args.install_prefix)
89+
install_destdir = product.host_install_destdir(host_target)
90+
toolchain_path = product.native_toolchain_path(host_target)
9691

9792
# Pass Dispatch directory down if we built it
9893
dispatch_build_dir = os.path.join(
@@ -134,10 +129,26 @@ def run_build_script_helper(action, host_target, product, args):
134129
]
135130
# Pass Cross compile host info
136131
if swiftpm.SwiftPM.has_cross_compile_hosts(args):
137-
helper_cmd += ['--cross-compile-hosts']
138-
for cross_compile_host in args.cross_compile_hosts:
139-
helper_cmd += [cross_compile_host]
132+
if product.is_darwin_host(host_target):
133+
helper_cmd += ['--cross-compile-hosts']
134+
for cross_compile_host in args.cross_compile_hosts:
135+
helper_cmd += [cross_compile_host]
136+
elif product.is_cross_compile_target(host_target):
137+
helper_cmd += ['--cross-compile-hosts', host_target]
138+
build_toolchain_path = install_destdir + args.install_prefix
139+
resource_dir = '%s/lib/swift' % build_toolchain_path
140+
helper_cmd += [
141+
'--cross-compile-config',
142+
targets.StdlibDeploymentTarget.get_target_for_name(
143+
host_target).platform.swiftpm_config(
144+
args, output_dir=build_toolchain_path,
145+
swift_toolchain=toolchain_path, resource_path=resource_dir)]
140146
if args.verbose_build:
141147
helper_cmd.append('--verbose')
142148

149+
if action == 'install':
150+
helper_cmd += [
151+
'--prefix', install_destdir + args.install_prefix
152+
]
153+
143154
shell.call(helper_cmd)

utils/swift_build_support/swift_build_support/products/swiftpm.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from . import swift
2424
from . import xctest
2525
from .. import shell
26+
from ..targets import StdlibDeploymentTarget
2627

2728

2829
class SwiftPM(product.Product):
@@ -44,7 +45,8 @@ def should_build(self, host_target):
4445
def run_bootstrap_script(self, action, host_target, additional_params=[]):
4546
script_path = os.path.join(
4647
self.source_dir, 'Utilities', 'bootstrap')
47-
toolchain_path = self.install_toolchain_path(host_target)
48+
49+
toolchain_path = self.native_toolchain_path(host_target)
4850
swiftc = os.path.join(toolchain_path, "bin", "swiftc")
4951

5052
# FIXME: We require llbuild build directory in order to build. Is
@@ -92,9 +94,22 @@ def run_bootstrap_script(self, action, host_target, additional_params=[]):
9294

9395
# Pass Cross compile host info
9496
if self.has_cross_compile_hosts(self.args):
95-
helper_cmd += ['--cross-compile-hosts']
96-
for cross_compile_host in self.args.cross_compile_hosts:
97-
helper_cmd += [cross_compile_host]
97+
if self.is_darwin_host(host_target):
98+
helper_cmd += ['--cross-compile-hosts']
99+
for cross_compile_host in self.args.cross_compile_hosts:
100+
helper_cmd += [cross_compile_host]
101+
elif self.is_cross_compile_target(host_target):
102+
helper_cmd += ['--cross-compile-hosts', host_target,
103+
'--skip-cmake-bootstrap']
104+
build_toolchain_path = self.host_install_destdir(
105+
host_target) + self.args.install_prefix
106+
resource_dir = '%s/lib/swift' % build_toolchain_path
107+
helper_cmd += [
108+
'--cross-compile-config',
109+
StdlibDeploymentTarget.get_target_for_name(host_target).platform
110+
.swiftpm_config(self.args, output_dir=build_toolchain_path,
111+
swift_toolchain=toolchain_path,
112+
resource_path=resource_dir)]
98113

99114
helper_cmd.extend(additional_params)
100115

@@ -122,18 +137,8 @@ def should_install(self, host_target):
122137
def has_cross_compile_hosts(self, args):
123138
return args.cross_compile_hosts
124139

125-
@classmethod
126-
def get_install_destdir(self, args, host_target, build_dir):
127-
install_destdir = args.install_destdir
128-
if self.has_cross_compile_hosts(args):
129-
build_root = os.path.dirname(build_dir)
130-
install_destdir = '%s/intermediate-install/%s' % (build_root, host_target)
131-
return install_destdir
132-
133140
def install(self, host_target):
134-
install_destdir = self.get_install_destdir(self.args,
135-
host_target,
136-
self.build_dir)
141+
install_destdir = self.host_install_destdir(host_target)
137142
install_prefix = install_destdir + self.args.install_prefix
138143

139144
self.run_bootstrap_script('install', host_target, [

utils/swift_build_support/swift_build_support/targets.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ def cmake_options(self, args):
8080
"""
8181
return ''
8282

83+
def swiftpm_config(self, args, output_dir, swift_toolchain, resource_path):
84+
"""
85+
Generate a JSON file that SPM can use to cross-compile
86+
"""
87+
raise NotImplementedError('Generating a SwiftPM cross-compilation JSON file '
88+
'for %s is not supported yet' % self.name)
89+
8390

8491
class DarwinPlatform(Platform):
8592
def __init__(self, name, archs, sdk_name=None, is_simulator=False):
@@ -155,8 +162,7 @@ def swift_flags(self, args):
155162
flags += '-resource-dir %s/swift-%s-%s/lib/swift ' % (
156163
args.build_root, self.name, args.android_arch)
157164

158-
android_toolchain_path = '%s/toolchains/llvm/prebuilt/%s' % (
159-
args.android_ndk, StdlibDeploymentTarget.host_target().name)
165+
android_toolchain_path = self.ndk_toolchain_path(args)
160166

161167
flags += '-sdk %s/sysroot ' % (android_toolchain_path)
162168
flags += '-tools-directory %s/bin' % (android_toolchain_path)
@@ -171,6 +177,42 @@ def cmake_options(self, args):
171177
options += '-DCMAKE_ANDROID_NDK:PATH=%s' % (args.android_ndk)
172178
return options
173179

180+
def ndk_toolchain_path(self, args):
181+
return '%s/toolchains/llvm/prebuilt/%s' % (
182+
args.android_ndk, StdlibDeploymentTarget.host_target().name)
183+
184+
def swiftpm_config(self, args, output_dir, swift_toolchain, resource_path):
185+
config_file = '%s/swiftpm-android-%s.json' % (output_dir, args.android_arch)
186+
187+
if os.path.exists(config_file):
188+
print("Using existing config at %s" % config_file)
189+
return config_file
190+
191+
spm_json = '{\n'
192+
spm_json += ' "version": 1,\n'
193+
spm_json += ' "target": "%s-unknown-linux-android%s",\n' % (
194+
args.android_arch, args.android_api_level)
195+
spm_json += ' "toolchain-bin-dir": "%s/bin",\n' % swift_toolchain
196+
spm_json += ' "sdk": "%s/sysroot",\n' % self.ndk_toolchain_path(args)
197+
198+
spm_json += ' "extra-cc-flags": [ "-fPIC", "-I%s/usr/include" ],\n' % (
199+
args.cross_compile_deps_path)
200+
201+
spm_json += ' "extra-swiftc-flags": [\n'
202+
spm_json += ' "-resource-dir", "%s",\n' % resource_path
203+
spm_json += ' "-tools-directory", "%s/bin",\n' % (
204+
self.ndk_toolchain_path(args))
205+
spm_json += ' "-Xcc", "-I%s/usr/include",\n' % args.cross_compile_deps_path
206+
spm_json += ' "-L%s/usr/lib"\n' % args.cross_compile_deps_path
207+
spm_json += ' ],\n'
208+
209+
spm_json += ' "extra-cpp-flags": [ "-lstdc++" ]\n'
210+
spm_json += '}'
211+
212+
with open(config_file, 'w') as f:
213+
f.write(spm_json)
214+
return config_file
215+
174216

175217
class Target(object):
176218
"""

0 commit comments

Comments
 (0)