Support extra activated path via `activated_path_extra` In newer versions of emscripten, executables are being moved into a `bin` subdirectory instead of residing in the root directory. To enable `emsdk` to add `bin` to `PATH` while maintaining backwards compatibility with older emscripten releases, this change introduces an optional `activated_path_extra` property on `Tool`. When configuring `PATH` or checking environment activation, `activated_path_extra` is checked and included in addition to the primary `activated_path` if the directory exists on disk. Alternatives considered: - Delimited strings (e.g. semicolon or colon separated) in `activated_path`: Rejected because colon (`:`) conflicts with Windows drive letters (`C:\...`), and splitting string paths would require updating all call sites that expect `activated_path` to be a single directory (e.g., when writing `emscripten-version.txt`). - JSON arrays in `activated_path`: While this avoids delimiter collisions on Windows, making `activated_path` polymorphic (either a string or list) would similarly complicate call sites requiring a single root directory. - Hardcoded directory checking: Dynamically checking if a `bin` subdirectory exists in Python code was rejected to avoid excessive special-case tool checks in `emsdk.py`.
diff --git a/emsdk.py b/emsdk.py index 2576355..41f378f 100644 --- a/emsdk.py +++ b/emsdk.py
@@ -1580,8 +1580,8 @@ """ path_add = [to_native_path(EMSDK_PATH)] for tool in active_tools: - if tool.activated_path: - path = to_native_path(tool.expand_vars(tool.activated_path)) + for path in tool.activated_paths(): + path = to_native_path(path) # If the tool has an activated_path_skip attribute then we don't add # the tools path to the users path if a program by that name is found # in the existing PATH. This allows us to, for example, add our version @@ -1821,6 +1821,7 @@ is_old = False version = None activated_path = None + activated_path_extra = None cmake_build_type = None install_path = None activated_path_skip = False @@ -1859,6 +1860,16 @@ def __repr__(self): return self.name + def activated_paths(self): + paths = [] + if self.activated_path_extra: + path = self.expand_vars(self.activated_path_extra) + if os.path.exists(path): + paths.append(path) + if self.activated_path: + paths.append(self.expand_vars(self.activated_path)) + return paths + def expand_vars(self, str): if '%installation_dir%' in str: str = str.replace('%installation_dir%', sdk_path(self.installation_dir())) @@ -2066,13 +2077,12 @@ debug_print(f'{self} is not active, because environment variable key="{key}" has value "{os.getenv(key)}" but should have value "{value}"') return False - if self.activated_path: - path = to_unix_path(self.expand_vars(self.activated_path)) - for p in path: - path_items = os.environ['PATH'].replace('\\', '/').split(ENVPATH_SEPARATOR) - if not normalized_contains(path_items, p): - debug_print(f'{self} is not active, because environment variable PATH item "{p}" is not present (PATH={os.environ["PATH"]})') - return False + for path in self.activated_paths(): + p = to_unix_path(path) + path_items = os.environ['PATH'].replace('\\', '/').split(ENVPATH_SEPARATOR) + if not normalized_contains(path_items, p): + debug_print(f'{self} is not active, because environment variable PATH item "{p}" is not present (PATH={os.environ["PATH"]})') + return False return True def can_be_installed(self):
diff --git a/emsdk_manifest.json b/emsdk_manifest.json index dc54039..0035a2a 100644 --- a/emsdk_manifest.json +++ b/emsdk_manifest.json
@@ -40,6 +40,7 @@ "download_prefix": "%releases-tag%-", "install_path": "upstream", "activated_path": "%installation_dir%/emscripten", + "activated_path_extra": "%installation_dir%/emscripten/bin", "activated_cfg": "LLVM_ROOT='%installation_dir%/bin';BINARYEN_ROOT='%installation_dir%';EMSCRIPTEN_ROOT='%installation_dir%/emscripten'", "emscripten_releases_hash": "%releases-tag%" }, @@ -53,6 +54,7 @@ "download_prefix": "%releases-tag%-", "install_path": "upstream", "activated_path": "%installation_dir%/emscripten", + "activated_path_extra": "%installation_dir%/emscripten/bin", "activated_cfg": "LLVM_ROOT='%installation_dir%/bin';BINARYEN_ROOT='%installation_dir%';EMSCRIPTEN_ROOT='%installation_dir%/emscripten'", "emscripten_releases_hash": "%releases-tag%" }, @@ -503,6 +505,7 @@ "download_prefix": "emscripten-e", "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'", "activated_path": "%installation_dir%", + "activated_path_extra": "%installation_dir%/bin", "activated_env": "EMSCRIPTEN=%installation_dir%", "custom_install_script": "emscripten_install" }, @@ -515,6 +518,7 @@ "unix_url": "https://github.com/emscripten-core/emscripten/archive/%tag%.tar.gz", "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'", "activated_path": "%installation_dir%", + "activated_path_extra": "%installation_dir%/bin", "activated_env": "EMSCRIPTEN=%installation_dir%", "custom_install_script": "emscripten_install" }, @@ -525,6 +529,7 @@ "unix_url": "https://github.com/emscripten-core/emscripten/archive/%precompiled_tag%.tar.gz", "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'", "activated_path": "%installation_dir%", + "activated_path_extra": "%installation_dir%/bin", "activated_env": "EMSCRIPTEN=%installation_dir%" }, { @@ -568,6 +573,7 @@ "git_branch": "main", "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'", "activated_path": "%installation_dir%", + "activated_path_extra": "%installation_dir%/bin", "activated_env": "EMSCRIPTEN=%installation_dir%", "cmake_build_type": "Release", "custom_install_script": "emscripten_install" @@ -581,6 +587,7 @@ "git_branch": "main", "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'", "activated_path": "%installation_dir%", + "activated_path_extra": "%installation_dir%/bin", "activated_env": "EMSCRIPTEN=%installation_dir%", "cmake_build_type": "Release", "custom_install_script": "emscripten_install"