2424CHECKOUT = EMSCRIPTEN_DIR .parent .parent .parent
2525EMSCRIPTEN_VERSION_FILE = EMSCRIPTEN_DIR / "emscripten_version.txt"
2626
27- CROSS_BUILD_DIR = CHECKOUT / "cross-build"
28- NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build"
27+ DEFAULT_CROSS_BUILD_DIR = CHECKOUT / "cross-build"
2928HOST_TRIPLE = "wasm32-emscripten"
3029
31- DOWNLOAD_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "build"
32- HOST_BUILD_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "build"
33- HOST_DIR = HOST_BUILD_DIR / "python"
34- PREFIX_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "prefix"
30+
31+ def get_build_paths (cross_build_dir = None ):
32+ """Compute all build paths from the given cross-build directory."""
33+ if cross_build_dir is None :
34+ cross_build_dir = DEFAULT_CROSS_BUILD_DIR
35+ cross_build_dir = Path (cross_build_dir )
36+ host_triple_dir = cross_build_dir / HOST_TRIPLE
37+ return {
38+ "cross_build_dir" : cross_build_dir ,
39+ "native_build_dir" : cross_build_dir / "build" ,
40+ "host_triple_dir" : host_triple_dir ,
41+ "host_build_dir" : host_triple_dir / "build" ,
42+ "host_dir" : host_triple_dir / "build" / "python" ,
43+ "prefix_dir" : host_triple_dir / "prefix" ,
44+ }
3545
3646LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local"
3747LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n "
@@ -115,12 +125,17 @@ def updated_env(updates, emsdk_cache):
115125 return environment
116126
117127
118- def subdir (working_dir , * , clean_ok = False ):
119- """Decorator to change to a working directory."""
128+ def subdir (path_key , * , clean_ok = False ):
129+ """Decorator to change to a working directory.
130+
131+ path_key is a key into context.build_paths, used to resolve the working
132+ directory at call time.
133+ """
120134
121135 def decorator (func ):
122136 @functools .wraps (func )
123137 def wrapper (context ):
138+ working_dir = context .build_paths [path_key ]
124139 try :
125140 tput_output = subprocess .check_output (
126141 ["tput" , "cols" ], encoding = "utf-8"
@@ -177,20 +192,21 @@ def build_platform():
177192 return sysconfig .get_config_var ("BUILD_GNU_TYPE" )
178193
179194
180- def build_python_path ():
195+ def build_python_path (context ):
181196 """The path to the build Python binary."""
182- binary = NATIVE_BUILD_DIR / "python"
197+ native_build_dir = context .build_paths ["native_build_dir" ]
198+ binary = native_build_dir / "python"
183199 if not binary .is_file ():
184200 binary = binary .with_suffix (".exe" )
185201 if not binary .is_file ():
186202 raise FileNotFoundError (
187- f"Unable to find `python(.exe)` in { NATIVE_BUILD_DIR } "
203+ f"Unable to find `python(.exe)` in { native_build_dir } "
188204 )
189205
190206 return binary
191207
192208
193- @subdir (NATIVE_BUILD_DIR , clean_ok = True )
209+ @subdir ("native_build_dir" , clean_ok = True )
194210def configure_build_python (context , working_dir ):
195211 """Configure the build/host Python."""
196212 if LOCAL_SETUP .exists ():
@@ -206,12 +222,12 @@ def configure_build_python(context, working_dir):
206222 call (configure , quiet = context .quiet )
207223
208224
209- @subdir (NATIVE_BUILD_DIR )
225+ @subdir ("native_build_dir" )
210226def make_build_python (context , working_dir ):
211227 """Make/build the build Python."""
212228 call (["make" , "--jobs" , str (cpu_count ()), "all" ], quiet = context .quiet )
213229
214- binary = build_python_path ()
230+ binary = build_python_path (context )
215231 cmd = [
216232 binary ,
217233 "-c" ,
@@ -241,7 +257,7 @@ def download_and_unpack(working_dir: Path, url: str, expected_shasum: str):
241257 shutil .unpack_archive (tmp_file .name , working_dir )
242258
243259
244- @subdir (HOST_BUILD_DIR , clean_ok = True )
260+ @subdir ("host_build_dir" , clean_ok = True )
245261def make_emscripten_libffi (context , working_dir ):
246262 ver = "3.4.6"
247263 libffi_dir = working_dir / f"libffi-{ ver } "
@@ -253,13 +269,13 @@ def make_emscripten_libffi(context, working_dir):
253269 )
254270 call (
255271 [EMSCRIPTEN_DIR / "make_libffi.sh" ],
256- env = updated_env ({"PREFIX" : PREFIX_DIR }, context .emsdk_cache ),
272+ env = updated_env ({"PREFIX" : context . build_paths [ "prefix_dir" ] }, context .emsdk_cache ),
257273 cwd = libffi_dir ,
258274 quiet = context .quiet ,
259275 )
260276
261277
262- @subdir (HOST_BUILD_DIR , clean_ok = True )
278+ @subdir ("host_build_dir" , clean_ok = True )
263279def make_mpdec (context , working_dir ):
264280 ver = "4.0.1"
265281 mpdec_dir = working_dir / f"mpdecimal-{ ver } "
@@ -275,7 +291,7 @@ def make_mpdec(context, working_dir):
275291 mpdec_dir / "configure" ,
276292 "CFLAGS=-fPIC" ,
277293 "--prefix" ,
278- PREFIX_DIR ,
294+ context . build_paths [ "prefix_dir" ] ,
279295 "--disable-shared" ,
280296 ],
281297 cwd = mpdec_dir ,
@@ -289,14 +305,15 @@ def make_mpdec(context, working_dir):
289305 )
290306
291307
292- @subdir (HOST_DIR , clean_ok = True )
308+ @subdir ("host_dir" , clean_ok = True )
293309def configure_emscripten_python (context , working_dir ):
294310 """Configure the emscripten/host build."""
311+ paths = context .build_paths
295312 config_site = os .fsdecode (EMSCRIPTEN_DIR / "config.site-wasm32-emscripten" )
296313
297314 emscripten_build_dir = working_dir .relative_to (CHECKOUT )
298315
299- python_build_dir = NATIVE_BUILD_DIR / "build"
316+ python_build_dir = paths [ "native_build_dir" ] / "build"
300317 lib_dirs = list (python_build_dir .glob ("lib.*" ))
301318 assert len (lib_dirs ) == 1 , (
302319 f"Expected a single lib.* directory in { python_build_dir } "
@@ -322,13 +339,13 @@ def configure_emscripten_python(context, working_dir):
322339 capture_output = True ,
323340 )
324341 host_runner = res .stdout .strip ()
325- pkg_config_path_dir = (PREFIX_DIR / "lib/pkgconfig/" ).resolve ()
342+ pkg_config_path_dir = (paths [ "prefix_dir" ] / "lib/pkgconfig/" ).resolve ()
326343 env_additions = {
327344 "CONFIG_SITE" : config_site ,
328345 "HOSTRUNNER" : host_runner ,
329346 "EM_PKG_CONFIG_PATH" : str (pkg_config_path_dir ),
330347 }
331- build_python = os .fsdecode (build_python_path ())
348+ build_python = os .fsdecode (build_python_path (context ))
332349 configure = [
333350 "emconfigure" ,
334351 os .path .relpath (CHECKOUT / "configure" , working_dir ),
@@ -342,7 +359,7 @@ def configure_emscripten_python(context, working_dir):
342359 "--disable-ipv6" ,
343360 "--enable-big-digits=30" ,
344361 "--enable-wasm-dynamic-linking" ,
345- f"--prefix={ PREFIX_DIR } " ,
362+ f"--prefix={ paths [ 'prefix_dir' ] } " ,
346363 ]
347364 if pydebug :
348365 configure .append ("--with-pydebug" )
@@ -403,7 +420,7 @@ def configure_emscripten_python(context, working_dir):
403420 sys .stdout .flush ()
404421
405422
406- @subdir (HOST_DIR )
423+ @subdir ("host_dir" )
407424def make_emscripten_python (context , working_dir ):
408425 """Run `make` for the emscripten/host build."""
409426 call (
@@ -432,9 +449,10 @@ def build_all(context):
432449
433450def clean_contents (context ):
434451 """Delete all files created by this script."""
435- if CROSS_BUILD_DIR .exists ():
436- print (f"🧹 Deleting { CROSS_BUILD_DIR } ..." )
437- shutil .rmtree (CROSS_BUILD_DIR )
452+ host_triple_dir = context .build_paths ["host_triple_dir" ]
453+ if host_triple_dir .exists ():
454+ print (f"🧹 Deleting { host_triple_dir } ..." )
455+ shutil .rmtree (host_triple_dir )
438456
439457 if LOCAL_SETUP .exists ():
440458 with LOCAL_SETUP .open ("rb" ) as file :
@@ -489,6 +507,14 @@ def main():
489507 dest = "quiet" ,
490508 help = "Redirect output from subprocesses to a log file" ,
491509 )
510+ subcommand .add_argument (
511+ "--cross-build-dir" ,
512+ action = "store" ,
513+ default = None ,
514+ dest = "cross_build_dir" ,
515+ help = "Path to the cross-build directory "
516+ f"(default: { DEFAULT_CROSS_BUILD_DIR } )" ,
517+ )
492518 subcommand .add_argument (
493519 "--emsdk-cache" ,
494520 action = "store" ,
@@ -521,6 +547,8 @@ def main():
521547
522548 context = parser .parse_args ()
523549
550+ context .build_paths = get_build_paths (context .cross_build_dir )
551+
524552 if context .emsdk_cache :
525553 validate_emsdk_version (context .emsdk_cache )
526554 context .emsdk_cache = Path (context .emsdk_cache ).absolute ()
0 commit comments