feat: Evaluate environmentSetupScript before CMake executable search#4763
Draft
feat: Evaluate environmentSetupScript before CMake executable search#4763
Conversation
…2301) When a kit defines an environmentSetupScript that modifies $PATH, the script is now evaluated before searching for the cmake executable, so that PATH changes from the script are respected during cmake lookup. Changes: - src/paths.ts: Add optional searchPATH parameter to which(), getCMakePath(), getCTestPath(), getCPackPath() to allow overriding the search PATH - src/workspace.ts: Forward searchPATH through DirectoryContext wrapper methods - src/cmakeProject.ts: In getCMakePathofProject(), evaluate kit environment via effectiveKitEnvironment() when active kit has environmentSetupScript, and pass the kit's PATH to path resolution - CHANGELOG.md: Add feature entry - test/unit-tests/backend/paths.test.ts: Add tests for which with custom PATH Co-authored-by: hanniavalera <90047725+hanniavalera@users.noreply.github.com>
Co-authored-by: hanniavalera <90047725+hanniavalera@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Allow alterations to $PATH in environmentSetupScript for CMake search
feat: Evaluate environmentSetupScript before CMake executable search
Feb 26, 2026
On Windows, the `which` npm package uses PATHEXT (.EXE;.CMD;.BAT;.COM) to resolve executables. The test was creating files without a recognized extension, causing `which` to fail with 'not found' on Windows CI. Fix: On Windows, create .cmd files and search by base name (which appends .cmd via PATHEXT). On non-Windows, keep the existing behavior with chmod +x. Co-authored-by: hanniavalera <90047725+hanniavalera@users.noreply.github.com>
Copilot AI
added a commit
that referenced
this pull request
Mar 2, 2026
…se studies Co-authored-by: hanniavalera <90047725+hanniavalera@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This change addresses item #2301
This changes visible behavior
The following changes are proposed:
environmentSetupScriptbefore resolving the CMake executable path, so$PATHmodifications from the script are respected during cmake/ctest/cpack lookupsearchPATHparameter throughPaths.which()→getCMakePath()/getCTestPath()/getCPackPath()→DirectoryContextwrappers, using thewhichnpm package's nativepathoptiongetCMakePathofProject(), calleffectiveKitEnvironment()when the active kit has anenvironmentSetupScriptand pass the resulting PATH into the resolution chainThe purpose of this change
The extension resolved the cmake binary via
process.env.PATH(VS Code launch-time PATH) beforeeffectiveKitEnvironment()ever ran. Kits whoseenvironmentSetupScriptadded cmake to$PATHcould never have that cmake found — the script ran too late (during driver_setKit()).Other Notes/Information
Backward compatible: All new parameters are optional. No behavior change when
environmentSetupScriptis absent.Presets mode unaffected: Presets use
configurePreset.cmakeExecutable, orthogonal to kit environment.extension.tsinit() unchanged: Startup cmake check runs before any kit is active — left as-is (best-effort).Double script execution: The setup script may run once for cmake resolution and again in the driver's
_setKit(). Accepted as pragmatic; optimizable with caching later if needed.Key change in
src/cmakeProject.ts:Original prompt
This section details on the original issue you should resolve
<issue_title>Allow alterations to the $PATH in an environmentSetupScript to take effect before searching for the CMake executable</issue_title>
<issue_description>### Discussed in #2299
Currently the extension searches for the CMake executable before
environmentSetupScriptis evaluated. In the event that the setup script alters the $PATH, those changes won't be in effect when looking for the CMake binary.</issue_description><agent_instructions>You are Copilot coding agent acting as a senior maintainer/contributor for the VS Code extension repository microsoft/vscode-cmake-tools. You are deeply familiar with CMake, CMake kits, CMake Presets, VS Code extension APIs, and the architecture of this repo (TypeScript-heavy, commands in src/extension.ts, project logic in src/cmakeProject.ts, drivers in src/drivers/, kit management in src/kits/kit.ts, path resolution in src/paths.ts, workspace context in src/workspace.ts, configuration schema in package.json, typed config access in src/config.ts).
Source of Truth
Implement the following feature request: #2301 - #2301 — Allow alterations to the $PATH in an environmentSetupScript to take effect before searching for the CMake executable
Feature Summary
When a kit defines an environmentSetupScript, the script may modify $PATH to include a directory containing the cmake binary. Currently, the extension searches for the CMake executable before the kit's environmentSetupScript is evaluated, so any $PATH changes from the script are ignored during cmake lookup. The fix is to evaluate the kit's environment (including running the setup script) before resolving the cmake executable path, so that a script-modified $PATH is respected.
Understanding the Problem (orient yourself here first)
The ordering issue spans several files. Read these carefully before writing code — the analysis below reflects the current codebase, but you should verify each claim and adjust your approach if anything has changed.
The current flow (simplified):
src/cmakeProject.ts → getCMakePathofProject() (~L1408): Calls this.workspaceContext.getCMakePath() to find the cmake binary.
src/workspace.ts → DirectoryContext.getCMakePath() (~L48): Delegates to paths.getCMakePath().
src/paths.ts → Paths.getCMakePath() (~L252): When the setting is 'auto' or 'cmake', calls this.which('cmake').
src/paths.ts → Paths.which() (~L196): Uses the which npm package, which searches process.env.PATH — the PATH at VS Code launch time.
Only later, when the CMake driver is created and _setKit() is called in src/drivers/cmakeDriver.ts (~L753), does effectiveKitEnvironment() in src/kits/kit.ts (~L1052) run the environmentSetupScript via getShellScriptEnvironment() and capture its environment.
Result: The cmake binary search at step 3-4 uses the stale process.env.PATH, not the kit's script-modified PATH.
Where the kit environment is built:
src/kits/kit.ts → effectiveKitEnvironment() (~L1052): This is the function that runs getShellScriptEnvironment() when kit.environmentSetupScript is defined, then layers on kit.environmentVariables and VS kit variables. It returns the full effective Environment for the kit.
src/kits/kit.ts → getShellScriptEnvironment() (~L670): Executes the user's setup script in a temp wrapper, captures the resulting environment variables (including PATH), and returns them.
Where the environment is consumed (too late for cmake search):
src/drivers/cmakeDriver.ts → _setKit() (~L753): Calls effectiveKitEnvironment() and stores the result in this._kitEnvironmentVariables. This happens when the driver is initialized — but the cmake executable was already resolved before the driver was created.
Files to Explore for Implementation
These are the files most likely to need changes. Read them to understand the current patterns and identify the best integration points. The suggestions below are starting points — you may find a cleaner approach after exploring the code.
src/paths.ts — which() method (~L196) and getCMakePath() (~L252). The which npm package accepts an options object with a path property for overriding the search PATH. Explore whether threading an optional Environment parameter through these methods is the right approach, or whether there's a simpler alternative. Also consider getCTestPath() and getCPackPath() which depend on getCMakePath().
src/workspace.ts — DirectoryContext.getCMakePath() (~L48) is a thin wrapper around paths.getCMakePath(). If the paths layer needs an environment parameter, this wrapper likely needs to forward it.
src/cmakeProject.ts — getCMakePathofProject() (~L1408) is the entry point for cmake resolution. This is probably where the kit's environment should be pre-evaluated before the path lookup. Also look at getCMakeExecutable() (~L1414) and getCMakeDriverInstance() (~L1434) to understand the...
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.