2020import subprocess
2121from pathlib import Path
2222from typing import List , Union , Optional
23+ import json
2324
2425# -----------------------------------------------------------------------------
2526# General utilities
@@ -68,11 +69,29 @@ def escape_cmd_arg(arg: Union[str, Path]) -> str:
6869# SwiftPM wrappers
6970
7071
72+ def get_build_target (swift_exec : Path , cross_compile_config : Optional [Path ]) -> str :
73+ """Returns the target-triple of the current machine or for cross-compilation."""
74+ command = [swift_exec , "-print-target-info" ]
75+ if cross_compile_config :
76+ cross_compile_json = json .load (open (cross_compile_config ))
77+ command += ["-target" , cross_compile_json ["target" ]]
78+ target_info_json = subprocess .check_output (
79+ command , stderr = subprocess .PIPE , universal_newlines = True
80+ ).strip ()
81+ target_info = json .loads (target_info_json )
82+ if "-apple-macosx" in target_info ["target" ]["unversionedTriple" ]:
83+ return target_info ["target" ]["unversionedTriple" ]
84+ return target_info ["target" ]["triple" ]
85+
86+
7187def get_swiftpm_options (
88+ swift_exec : Path ,
7289 package_path : Path ,
7390 build_path : Path ,
7491 multiroot_data_file : Optional [Path ],
7592 configuration : str ,
93+ cross_compile_host : Optional [str ],
94+ cross_compile_config : Optional [Path ],
7695 verbose : bool ,
7796) -> List [Union [str , Path ]]:
7897 args : List [Union [str , Path ]] = [
@@ -87,8 +106,17 @@ def get_swiftpm_options(
87106 args += ["--multiroot-data-file" , multiroot_data_file ]
88107 if verbose :
89108 args += ["--verbose" ]
90- if platform .system () == "Darwin" :
91- args += ["-Xlinker" , "-rpath" , "-Xlinker" , "/usr/lib/swift" ]
109+ build_target = get_build_target (
110+ swift_exec , cross_compile_config = cross_compile_config
111+ )
112+ build_os = build_target .split ("-" )[2 ]
113+ if build_os .startswith ("macosx" ):
114+ args += [
115+ "-Xlinker" ,
116+ "-rpath" ,
117+ "-Xlinker" ,
118+ "/usr/lib/swift" ,
119+ ]
92120 args += [
93121 "-Xlinker" ,
94122 "-rpath" ,
@@ -101,6 +129,21 @@ def get_swiftpm_options(
101129 "-Xlinker" ,
102130 "@executable_path/../lib/swift-5.5/macosx" ,
103131 ]
132+ else :
133+ # Library rpath for swift, dispatch, Foundation, etc. when installing
134+ args += [
135+ "-Xlinker" ,
136+ "-rpath" ,
137+ "-Xlinker" ,
138+ "$ORIGIN/../lib/swift/" + build_os ,
139+ ]
140+
141+ if cross_compile_host :
142+ if build_os .startswith ("macosx" ) and cross_compile_host .startswith ("macosx-" ):
143+ args += ["--arch" , "x86_64" , "--arch" , "arm64" ]
144+ else :
145+ fatal_error ("cannot cross-compile for %s" % cross_compile_host )
146+
104147 return args
105148
106149
@@ -118,6 +161,8 @@ def invoke_swiftpm(
118161 build_path : Path ,
119162 multiroot_data_file : Optional [Path ],
120163 configuration : str ,
164+ cross_compile_host : Optional [str ],
165+ cross_compile_config : Optional [Path ],
121166 env ,
122167 verbose : bool ,
123168):
@@ -126,7 +171,14 @@ def invoke_swiftpm(
126171 """
127172 args = [swift_exec , action ]
128173 args += get_swiftpm_options (
129- package_path , build_path , multiroot_data_file , configuration , verbose
174+ swift_exec = swift_exec ,
175+ package_path = package_path ,
176+ build_path = build_path ,
177+ multiroot_data_file = multiroot_data_file ,
178+ configuration = configuration ,
179+ cross_compile_host = cross_compile_host ,
180+ cross_compile_config = cross_compile_config ,
181+ verbose = verbose ,
130182 )
131183 if action == "test" :
132184 args += ["--test-product" , product , "--disable-testable-imports" ]
@@ -151,6 +203,8 @@ def build(args: argparse.Namespace) -> None:
151203 build_path = args .build_path ,
152204 multiroot_data_file = args .multiroot_data_file ,
153205 configuration = args .configuration ,
206+ cross_compile_host = args .cross_compile_host ,
207+ cross_compile_config = args .cross_compile_config ,
154208 env = env ,
155209 verbose = args .verbose ,
156210 )
@@ -167,6 +221,8 @@ def test(args: argparse.Namespace) -> None:
167221 build_path = args .build_path ,
168222 multiroot_data_file = args .multiroot_data_file ,
169223 configuration = args .configuration ,
224+ cross_compile_host = args .cross_compile_host ,
225+ cross_compile_config = args .cross_compile_config ,
170226 env = env ,
171227 verbose = args .verbose ,
172228 )
@@ -179,10 +235,13 @@ def install(args: argparse.Namespace) -> None:
179235
180236 env = get_swiftpm_environment_variables ()
181237 swiftpm_args = get_swiftpm_options (
238+ swift_exec = args .swift_exec ,
182239 package_path = args .package_path ,
183240 build_path = args .build_path ,
184241 multiroot_data_file = args .multiroot_data_file ,
185242 configuration = args .configuration ,
243+ cross_compile_host = args .cross_compile_host ,
244+ cross_compile_config = args .cross_compile_config ,
186245 verbose = args .verbose ,
187246 )
188247 cmd = [args .swift_exec , "build" , "--show-bin-path" ] + swiftpm_args
@@ -222,6 +281,13 @@ def add_common_args(parser: argparse.ArgumentParser) -> None:
222281 type = Path ,
223282 help = "the toolchain to use when building this package" ,
224283 )
284+ parser .add_argument (
285+ "--cross-compile-host" , help = "cross-compile for another host instead"
286+ )
287+ parser .add_argument (
288+ "--cross-compile-config" ,
289+ help = "an SPM JSON destination file containing Swift cross-compilation flags" ,
290+ )
225291
226292
227293def parse_args () -> argparse .Namespace :
0 commit comments