Skip to content

Commit dfb823c

Browse files
committed
Fix an issue if user passes a relative path to Python, and some system cache libraries need rebuilding. Emcc tool would spawn sub-emcc tools to rebuild the cache, with different CWD, resulting in the relative path lookups pointing to the wrong relative directories. To fix the issue, normalize the relative tool paths first.
1 parent 161f6c4 commit dfb823c

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

test/test_sanity.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,3 +846,26 @@ def test_bootstrap_without_em_config(self):
846846

847847
# Running bootstrap.py should not fail
848848
self.run_process([utils.exe_path_from_root('bootstrap')], env=env)
849+
850+
# Verify that if user specifies a relative path to Python executable, then
851+
# Emscripten is still able to build.
852+
def test_emcc_with_relative_python_path(self):
853+
restore_and_set_up()
854+
# Clear the cache, since rebuilding the cache has been observed to fail
855+
# if Python path is specified as relative.
856+
self.clear_cache()
857+
858+
try:
859+
relative_python = os.path.relpath(os.environ.get('EMSDK_PYTHON'), os.getcwd())
860+
except ValueError:
861+
self.skipTest('Python and Emscripten are located on different drives, cannot run this test.')
862+
863+
relative_python_escaped = relative_python.replace("\\", "\\\\")
864+
add_to_config(f'PYTHON = "{relative_python_escaped}"')
865+
866+
env = os.environ.copy()
867+
env['EMSDK_PYTHON'] = relative_python
868+
869+
output = self.do([EMCC, test_file('hello_world.c')], env=env)
870+
self.assertNotContained('error', output)
871+
self.assertExists('a.out.js')

tools/config.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,23 @@ def normalize_config_settings():
7474
PORTS = os.path.join(CACHE, 'ports')
7575

7676

77+
def normalize_relative_environment_variables():
78+
# User may have specified environment variables to point to the location
79+
# of e.g. Python or Node, like with
80+
#
81+
# EMSDK_PYTHON=../../path/to/python emcc test/hello_world.c
82+
#
83+
# As part of its operation, emcc may spawn sub-emcc tasks when building
84+
# libraries to cache. These sub-emcc tasks may run in a different CWD, so
85+
# normalize the path directives to current environment here, so that any
86+
# sub-tool spawns will see the path to the tool from the parent process.
87+
# However, be careful not to normalize e.g. 'python' or other PATH lookups.
88+
for env_var in {'EMSDK_PYTHON', 'NODE_JS'}:
89+
path = os.environ.get(env_var)
90+
if path and ('\\' in path or '/' in path):
91+
os.environ[env_var] = os.path.abspath(os.environ[env_var])
92+
93+
7794
def set_config_from_tool_location(config_key, tool_binary, f):
7895
val = globals()[config_key]
7996
if val is None:
@@ -168,6 +185,7 @@ def read_config():
168185
set_config_from_tool_location('BINARYEN_ROOT', 'wasm-opt', lambda x: os.path.dirname(os.path.dirname(x)))
169186

170187
normalize_config_settings()
188+
normalize_relative_environment_variables()
171189

172190

173191
def generate_config(path):

0 commit comments

Comments
 (0)