diff --git a/test/test_sanity.py b/test/test_sanity.py index e3385e42792eb..b87b760ad270a 100644 --- a/test/test_sanity.py +++ b/test/test_sanity.py @@ -846,3 +846,26 @@ def test_bootstrap_without_em_config(self): # Running bootstrap.py should not fail self.run_process([utils.exe_path_from_root('bootstrap')], env=env) + + # Verify that if user specifies a relative path to Python executable, then + # Emscripten is still able to build. + def test_emcc_with_relative_python_path(self): + restore_and_set_up() + # Clear the cache, since rebuilding the cache has been observed to fail + # if Python path is specified as relative. + self.clear_cache() + + try: + relative_python = os.path.relpath(os.environ.get('EMSDK_PYTHON'), os.getcwd()) + except ValueError: + self.skipTest('Python and Emscripten are located on different drives, cannot run this test.') + + relative_python_escaped = relative_python.replace("\\", "\\\\") + add_to_config(f'PYTHON = "{relative_python_escaped}"') + + env = os.environ.copy() + env['EMSDK_PYTHON'] = relative_python + + output = self.do([EMCC, test_file('hello_world.c')], env=env) + self.assertNotContained('error', output) + self.assertExists('a.out.js') diff --git a/tools/config.py b/tools/config.py index d22f2f017c65d..147623070bf4a 100644 --- a/tools/config.py +++ b/tools/config.py @@ -74,6 +74,20 @@ def normalize_config_settings(): PORTS = os.path.join(CACHE, 'ports') +def normalize_relative_python_path(): + # User may have specified the EMSDK_PYTHON environment variable to point to + # the Python interpreter, e.g. + # + # EMSDK_PYTHON=../../path/to/python emcc test/hello_world.c + # + # As part of its operation, emcc may spawn sub-emcc tasks when building + # libraries to cache. These sub-emcc tasks will run in a different CWD, so + # reinitialize EMSDK_PYTHON here so that sub-tool spawns will use the same + # Python interpreter as the parent. + if os.environ.get('EMSDK_PYTHON'): + os.environ['EMSDK_PYTHON'] = sys.executable + + def set_config_from_tool_location(config_key, tool_binary, f): val = globals()[config_key] if val is None: @@ -168,6 +182,7 @@ def read_config(): set_config_from_tool_location('BINARYEN_ROOT', 'wasm-opt', lambda x: os.path.dirname(os.path.dirname(x))) normalize_config_settings() + normalize_relative_python_path() def generate_config(path):