11__lazy_modules__ = [
2- "contextlib" ,
3- "functools" ,
42 "os" ,
53 "pathlib" ,
64 "shutil" ,
75 "subprocess" ,
86 "sys" ,
9- "tempfile" ,
107]
118
12- import contextlib
13- import functools
149import os
1510import pathlib
1611import shutil
1712import subprocess
1813import sys
19- import tempfile
2014
2115try :
2216 from os import process_cpu_count as cpu_count
2923WASMTIME_HOST_RUNNER_VAR = f"{{{ WASMTIME_VAR_NAME } }}"
3024
3125
32- def separator ():
33- """Print a separator line across the terminal width."""
34- try :
35- tput_output = subprocess .check_output (
36- ["tput" , "cols" ], encoding = "utf-8"
37- )
38- except subprocess .CalledProcessError :
39- terminal_width = 80
40- else :
41- terminal_width = int (tput_output .strip ())
42- print ("⎯" * terminal_width )
43-
44-
45- def updated_env (updates = {}):
46- """Create a new dict representing the environment to use.
47-
48- The changes made to the execution environment are printed out.
49- """
50- env_defaults = {}
51- # https://reproducible-builds.org/docs/source-date-epoch/
52- git_epoch_cmd = ["git" , "log" , "-1" , "--pretty=%ct" ]
53- try :
54- epoch = subprocess .check_output (
55- git_epoch_cmd , encoding = "utf-8"
56- ).strip ()
57- env_defaults ["SOURCE_DATE_EPOCH" ] = epoch
58- except subprocess .CalledProcessError :
59- pass # Might be building from a tarball.
60- # This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence.
61- environment = env_defaults | os .environ | updates
62-
63- env_diff = {}
64- for key , value in environment .items ():
65- if os .environ .get (key ) != value :
66- env_diff [key ] = value
67-
68- env_vars = [
69- f"\n { key } ={ item } " for key , item in sorted (env_diff .items ())
70- ]
71- _shared .log ("🌎" , f"Environment changes:{ '' .join (env_vars )} " )
72-
73- return environment
74-
75-
76- def subdir (context_attr , * , clean_ok = False ):
77- """Decorator to change to a working directory."""
78-
79- def decorator (func ):
80- @functools .wraps (func )
81- def wrapper (context ):
82- nonlocal context_attr
83-
84- working_dir = getattr (context , context_attr )
85- separator ()
86- _shared .log ("📁" , os .fsdecode (working_dir ))
87- if clean_ok and context .clean and working_dir .exists ():
88- _shared .log ("🚮" , "Deleting directory (--clean)..." )
89- shutil .rmtree (working_dir )
90-
91- working_dir .mkdir (parents = True , exist_ok = True )
92-
93- with contextlib .chdir (working_dir ):
94- return func (context , working_dir )
95-
96- return wrapper
97-
98- return decorator
99-
100-
101- def call (command , * , context = None , quiet = False , ** kwargs ):
102- """Execute a command.
103-
104- If 'quiet' is true, then redirect stdout and stderr to a temporary file.
105- """
106- if context is not None :
107- quiet = context .quiet
108-
109- _shared .log ("❯" , " " .join (map (str , command )), spacing = " " )
110- if not quiet :
111- stdout = None
112- stderr = None
113- else :
114- if (log_path := getattr (context , "log_path" , None )) is None :
115- log_path = pathlib .Path (tempfile .gettempdir ())
116- log_path .mkdir (parents = True , exist_ok = True )
117- stdout = tempfile .NamedTemporaryFile (
118- "w" ,
119- encoding = "utf-8" ,
120- delete = False ,
121- dir = log_path ,
122- prefix = "cpython-wasi-" ,
123- suffix = ".log" ,
124- )
125- stderr = subprocess .STDOUT
126- _shared .log ("📝" , f"Logging output to { stdout .name } (--quiet)..." )
127-
128- try :
129- subprocess .check_call (command , ** kwargs , stdout = stdout , stderr = stderr )
130- except subprocess .CalledProcessError as error :
131- if quiet :
132- _shared .log ("❌" , f"Exit code { error .returncode } " )
133- separator ()
134- with open (stdout .name , encoding = "utf-8" ) as file :
135- lines = file .readlines ()
136- # Inefficient, but the log shouldn't be dramatically large.
137- print ("" .join (lines [- 10 :]), end = "" )
138- if not lines [- 1 ].endswith ("\n " ):
139- print ()
140- sys .exit (error .returncode )
141-
142-
143- @subdir ("build_python_path" , clean_ok = True )
26+ @_shared .subdir ("build_python_path" , clean_ok = True )
14427def configure_build_python (context , working_dir ):
14528 """Configure the build/host Python."""
14629 configure = [os .path .relpath (context .checkout / "configure" , working_dir )]
14730 configure .extend (context .configure_args )
14831
149- call (configure , context = context )
32+ context . call (configure )
15033
15134
152- @subdir ("build_python_path" )
35+ @_shared . subdir ("build_python_path" )
15336def make_build_python (context , _working_dir ):
15437 """Make/build the build Python."""
155- call (["make" , "--jobs" , str (cpu_count ()), "all" ], context = context )
38+ context . call (["make" , "--jobs" , str (cpu_count ()), "all" ])
15639
15740 binary = context .build_python_interpreter
15841 cmd = [
@@ -205,7 +88,7 @@ def wasi_sdk_env(context):
20588 return env
20689
20790
208- @subdir ("wasi_build_path" , clean_ok = True )
91+ @_shared . subdir ("wasi_build_path" , clean_ok = True )
20992def configure_wasi_python (context , working_dir ):
21093 """Configure the WASI/host build."""
21194 config_site = os .fsdecode (context .here / "config.site-wasm32-wasi" )
@@ -247,10 +130,9 @@ def configure_wasi_python(context, working_dir):
247130 if context .is_debug :
248131 configure .append ("--with-pydebug" )
249132 configure .extend (context .configure_args )
250- call (
133+ context . call (
251134 configure ,
252- env = updated_env (env_additions | wasi_sdk_env (context )),
253- context = context ,
135+ env = _shared .updated_env (env_additions | wasi_sdk_env (context )),
254136 )
255137
256138 python_wasm = working_dir / "python.wasm"
@@ -262,17 +144,18 @@ def configure_wasi_python(context, working_dir):
262144 sys .stdout .flush ()
263145
264146
265- @subdir ("wasi_build_path" )
147+ @_shared . subdir ("wasi_build_path" )
266148def make_wasi_python (context , working_dir ):
267149 """Run `make` for the WASI/host build."""
268- call (
150+ context . call (
269151 ["make" , "--jobs" , str (cpu_count ()), "all" ],
270- env = updated_env (),
271- context = context ,
152+ env = _shared .updated_env (),
272153 )
273154
274155 exec_script = working_dir / "python.sh"
275- call ([exec_script , "-c" , "import sys; print(sys.version)" ], quiet = False )
156+ context .call (
157+ [exec_script , "-c" , "import sys; print(sys.version)" ], quiet = False
158+ )
276159 _shared .log (
277160 "🎉" ,
278161 f"Use `{ exec_script .relative_to (pathlib .Path ().absolute ())} ` "
@@ -289,13 +172,13 @@ def clean_contents(context):
289172 shutil .rmtree (path )
290173
291174
292- @subdir ("build_python_path" )
175+ @_shared . subdir ("build_python_path" )
293176def pythoninfo_build_python (context , working_dir ):
294177 """Display build info of the build Python."""
295- call (["make" , "pythoninfo" ], context = context )
178+ context . call (["make" , "pythoninfo" ])
296179
297180
298- @subdir ("wasi_build_path" )
181+ @_shared . subdir ("wasi_build_path" )
299182def pythoninfo_wasi_python (context , working_dir ):
300183 """Display build info of the host/WASI Python."""
301- call (["make" , "pythoninfo" ], context = context )
184+ context . call (["make" , "pythoninfo" ])
0 commit comments