CMake Launch Environment
Run your environment setup script once, and every CMake launch gets its environment.
You already have a script that sets up your build environment — the one you source
before running anything by hand. This extension runs that same script and hands its
environment to whatever CMake Tools launches, so Debug and Run just work.
No launch.json edits. No duplicating your environment into settings.
The problem
Your Qt app needs its libraries on the search path, QT_PLUGIN_PATH pointing at
the platform plugins, and QML import paths set — before the process starts. It runs
fine from your terminal, because you sourced env.sh first.
Then you press Debug, and it fails with an error that looks nothing like the actual
problem. A missing platform plugin. A silent exit. A dialog about qt.conf.
So you copy your environment into launch.json, by hand, per configuration, and
keep it in sync forever.
This extension removes that chore.
Getting started
- Open a CMake project. A new item appears in the status bar showing your active
build type —
Debug: no script selected.
- Click it. A picker lists the shell scripts in your workspace.
- Pick your environment script. It runs immediately, and the status bar shows a
check mark with the script's name.
- Press CMake Tools' Debug or Run Without Debugging. Your program starts
with everything the script exported.
That's the whole configuration surface. There are no settings to edit.
Your choice is remembered. Reopen the project and the same script is still
assigned — it re-runs automatically in the background so the environment is ready
before you press Debug.
To point at a script outside the workspace, choose Browse… in the picker. If it
turns out to live inside your workspace after all, it is stored as
${workspaceFolder}/… so the assignment stays portable.
To stop injecting, click the status bar item and choose Clear assignment.
What it covers
Every way VS Code can start your program:
| Launch path |
Covered |
| CMake Tools Debug button |
✅ |
| CMake Tools Run Without Debugging |
✅ |
Hand-written launch.json (cppdbg / cppvsdbg) |
✅ |
| Plain F5 |
✅ |
| Any terminal you open |
✅ |
Where a launch configuration already sets an environment entry, your script wins
for the variables it defines; anything else you wrote is left alone.
Supported scripts
| Platform |
Scripts |
| macOS, Linux |
.sh, .bash, .zsh, .ksh |
| Windows |
.ps1, .cmd, .bat |
The picker only offers scripts it can actually run on your machine, so you will not
see .bat on macOS or .sh on Windows.
Commands
All three are also reachable from the Command Palette.
| Command |
What it does |
CMake Launch Environment: Select Environment Script… |
Opens the picker. Re-picking the current script re-runs it. |
CMake Launch Environment: Clear Environment Script… |
Removes the assignment and stops injecting. |
CMake Launch Environment: Show Captured Environment… |
Opens the full captured environment in an editor. |
Requirements
- VS Code 1.82 or later
- CMake Tools
— used to read the active build type
- The C/C++ extension, for debugging (
cppdbg / cppvsdbg)
Hover to see what your script actually did
Hovering the status bar item shows what is in effect right now:
- Set by this script — the variables your script added or changed, with their
values. Usually a handful, and the ones you actually care about.
- Unchanged from your environment — everything else it captured, by name.
- Path values are clickable. A file opens in the editor; a directory opens in
Finder or Explorer. A
PATH-style list is broken into its individual entries.
- A path that does not exist is flagged rather than linked. This is the point:
a
QT_PLUGIN_PATH pointing somewhere that is not there is the usual cause of a
launch failing with an error that mentions nothing about paths.
For the complete list with every value, use Show all N variables in the hover,
or the CMake Launch Environment: Show Captured Environment… command. That opens
a document you can scroll, search and copy from — which a hover cannot do well.
The status bar tells you the truth
The status bar shows what is actually in effect, never just what you selected:
| It shows |
It means |
Debug: no script selected |
Nothing assigned. Click to pick one. |
Debug: env.sh with a check mark |
The script ran and its environment is being injected. |
Debug: env.sh — capture failed |
The script did not run successfully. Nothing is being injected. Hover for the reason. |
CMake Env: no build type |
CMake Tools has not reported a build type yet. Configure the project first. |
CMake Env: CMake Tools unavailable |
CMake Tools is not installed or did not start. |
A script is never shown as active unless its capture genuinely succeeded — so a
failing script is visible immediately, rather than looking fine while your program
launches with the wrong environment.
Why the capture is trustworthy
Environments are read back with a real serializer — NUL-delimited on POSIX, JSON on
Windows — never by parsing text line by line.
That matters more than it sounds. Line-based parsing is the cause of a long-standing
bug in CMake Tools' own environmentSetupScript
(#2686): a shell that
exports a function, or a variable whose value contains a newline, silently corrupts
everything after it. A truncated environment is worse than no feature at all,
because the failure surfaces somewhere else entirely.
So values containing =, values spanning multiple lines, and shells that export
functions all come through intact. Your script's own echo output can't corrupt the
capture either.
What is remembered
Assignments are saved per workspace and restored when you reopen the project. They
are stored in VS Code's workspace state — personal to your machine, not committed
to the repository.
The captured environment itself is never saved. Only which script you picked.
On reopening, the script is re-run rather than a previous session's variables being
replayed, because a script that changed in between would otherwise inject something
stale without you knowing. Until that re-run finishes the status bar shows
capturing…, and no environment is injected.
If the script has been deleted or moved since, the assignment is dropped rather
than restored broken.
Known limitations
Changing build type does not re-run the script. If you switch from Debug to
Release, the status bar updates, but you need to pick a script for the new build
type. Automatic re-capture is planned.
The script runs when you assign it, not on every launch. If you edit the script,
re-pick it from the picker to re-run it.
A terminal opened before you assigned a script won't have the variables. VS Code
applies environment changes when a terminal is created. Open a new one.
On Windows, a .ps1 containing non-ASCII characters needs a UTF-8 BOM. Windows
PowerShell 5.1 otherwise reads the file using the system code page and the characters
arrive mangled — the same as it would in your own terminal. Most editors save
PowerShell scripts with a BOM already.
Feedback
Bugs and suggestions:
github.com/sblkr/vscode-launch-environment/issues
Building it yourself, or curious why it works the way it does?
See CONTRIBUTING.md and DECISIONS.md.