20
20
import subprocess
21
21
from pathlib import Path
22
22
from typing import List , Union , Optional
23
+ import json
23
24
24
25
# -----------------------------------------------------------------------------
25
26
# General utilities
@@ -68,11 +69,29 @@ def escape_cmd_arg(arg: Union[str, Path]) -> str:
68
69
# SwiftPM wrappers
69
70
70
71
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
+
71
87
def get_swiftpm_options (
88
+ swift_exec : Path ,
72
89
package_path : Path ,
73
90
build_path : Path ,
74
91
multiroot_data_file : Optional [Path ],
75
92
configuration : str ,
93
+ cross_compile_host : Optional [str ],
94
+ cross_compile_config : Optional [Path ],
76
95
verbose : bool ,
77
96
) -> List [Union [str , Path ]]:
78
97
args : List [Union [str , Path ]] = [
@@ -87,8 +106,17 @@ def get_swiftpm_options(
87
106
args += ["--multiroot-data-file" , multiroot_data_file ]
88
107
if verbose :
89
108
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
+ ]
92
120
args += [
93
121
"-Xlinker" ,
94
122
"-rpath" ,
@@ -101,6 +129,21 @@ def get_swiftpm_options(
101
129
"-Xlinker" ,
102
130
"@executable_path/../lib/swift-5.5/macosx" ,
103
131
]
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
+
104
147
return args
105
148
106
149
@@ -118,6 +161,8 @@ def invoke_swiftpm(
118
161
build_path : Path ,
119
162
multiroot_data_file : Optional [Path ],
120
163
configuration : str ,
164
+ cross_compile_host : Optional [str ],
165
+ cross_compile_config : Optional [Path ],
121
166
env ,
122
167
verbose : bool ,
123
168
):
@@ -126,7 +171,14 @@ def invoke_swiftpm(
126
171
"""
127
172
args = [swift_exec , action ]
128
173
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 ,
130
182
)
131
183
if action == "test" :
132
184
args += ["--test-product" , product , "--disable-testable-imports" ]
@@ -151,6 +203,8 @@ def build(args: argparse.Namespace) -> None:
151
203
build_path = args .build_path ,
152
204
multiroot_data_file = args .multiroot_data_file ,
153
205
configuration = args .configuration ,
206
+ cross_compile_host = args .cross_compile_host ,
207
+ cross_compile_config = args .cross_compile_config ,
154
208
env = env ,
155
209
verbose = args .verbose ,
156
210
)
@@ -167,6 +221,8 @@ def test(args: argparse.Namespace) -> None:
167
221
build_path = args .build_path ,
168
222
multiroot_data_file = args .multiroot_data_file ,
169
223
configuration = args .configuration ,
224
+ cross_compile_host = args .cross_compile_host ,
225
+ cross_compile_config = args .cross_compile_config ,
170
226
env = env ,
171
227
verbose = args .verbose ,
172
228
)
@@ -179,10 +235,13 @@ def install(args: argparse.Namespace) -> None:
179
235
180
236
env = get_swiftpm_environment_variables ()
181
237
swiftpm_args = get_swiftpm_options (
238
+ swift_exec = args .swift_exec ,
182
239
package_path = args .package_path ,
183
240
build_path = args .build_path ,
184
241
multiroot_data_file = args .multiroot_data_file ,
185
242
configuration = args .configuration ,
243
+ cross_compile_host = args .cross_compile_host ,
244
+ cross_compile_config = args .cross_compile_config ,
186
245
verbose = args .verbose ,
187
246
)
188
247
cmd = [args .swift_exec , "build" , "--show-bin-path" ] + swiftpm_args
@@ -222,6 +281,13 @@ def add_common_args(parser: argparse.ArgumentParser) -> None:
222
281
type = Path ,
223
282
help = "the toolchain to use when building this package" ,
224
283
)
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
+ )
225
291
226
292
227
293
def parse_args () -> argparse .Namespace :
0 commit comments