U++ Integration for VSCode
Build, run, debug, and manage U++ packages in VSCode using the umk command-line tool.
Install from VS Code Marketplace
🚧 Under Active Development
This extension is evolving rapidly — expect the occasional rough edge as features land.
Primary development happens on Linux (Arch/CachyOS). Windows is supported but slightly behind.
macOS has not been tested yet — contributions welcome.
What's New in v0.9.1
- Automatic build thread count —
upp.buildThreads adds -H<n> to umk commands. 'auto' uses your CPU core count, or set a fixed number. Explicit H in buildFlags still wins.
What's New in v0.9.0
- UppHub Package Manager (
Ctrl+Shift+U) — browse, install, update, and uninstall community packages
- Integrated terminal support — run programs in VS Code's terminal, auto-enabled on headless/remote (code-server, VPS, SSH)
- U++ installation health check — webview guidance with platform-specific install instructions
- Error limit — kill builds after a configurable number of errors
- Blitz toggle — enable/disable BLITZ builds directly from the sidebar
- C++ standard selector — dropdown populated from
.bm files
- Workspace/package mismatch detection — panel with Recreate Workspace button
- Auto-generate
launch.json — alongside IntelliSense updates
- Debug adapter panel — shown when debug extension is missing, with one-click install
- clangd
.clangd config generation — auto-generates config and preamble for U++ headers
What is U++?
U++ (formerly known as Ultimate++) is a C++ rapid application development framework. It uses a bundle system with .var files for assemblies and .upp files to organize packages. The umk tool is U++'s command-line build utility, which this extension wraps to provide a seamless VSCode experience.
So what is U++ exactly?
Is it a software framework? Cross-platform? A GUI toolkit? A C++ enhancement? A C++ std:: library replacement? An IDE (integrated development environment)? Or even a complete web framework? Blazingly fast? Multithreading? Really memory effective? Rapid development? Less code? Integrated icon and form layout designers? Integrated code documentation system? Subpixel graphics? Easy SQL for most databases? OpenGL? Other libraries? Much more?
The short answer is — yes, to all of those things.
But then the next natural question appears — why would me or someone else need this mostly unknown thing? Where is the catch? Pros and cons? Especially when there are so many established and/or promising other tools? Developers are spoilt for choice nowadays, aren't they?
Wait — have I not touched software licenses yet? How many of them have all the mentioned features? And how many of them have the very, very permissive licenses for commercial applications? The answer, my friends, is blowing in the wind... Not many.
So more choices and competition is a good thing? This is a principle of capitalism and open source. But every time someone starts and develops a new thing, he/she/they need some time to overcome doubters. For the U++ project, this "some time" is 20 years of improvements. And I still cannot understand why U++ has not attracted as many developers as it deserves by its design ideas. Moreover, why does it attract a lot of doubting-hating-nonsense opinions when someone mentions U++ on the internet?
Common objections
"How do you dare create an alternative to the C++ standard library? With all kinds of containers? And say it is better, faster, and easier to use for GUI widgets? It lowers the popularity of C++!"
You cannot believe it is not butter, as in a famous advert? This is not about replacing C++ — it is about making C++ development faster, cleaner, and more productive. U++ complements the standard library where it falls short, especially in GUI development, build management, and cross-platform abstraction.
"You claim your library is faster. There are lies, damned lies, and then there are your benchmarks!"
Yes, maybe. But maybe only std::unordered_map has those problems? These opinions really exist.
"Forcing an IDE on users is a major limitation."
What? Compare that to Microsoft Windows and Visual Studio — for years. Then came Apple and Xcode. And when someone creates an easier-to-use alternative, some start fires?
But such blame https://www.reddit.com/r/cpp/comments/juiudg/comment/gce8yuz/?utm_source=share&utm_medium=web2x&context=3 inspired me to create this extension!
Features
- Assembly & package management — browse, select, and create packages across multiple U++ assemblies from a sidebar UI
- Build & run — build and run your U++ projects with a single click or keyboard shortcut
- Debug — build with debug symbols and launch gdb automatically
- UppHub Package Manager (
Ctrl+Shift+U) — browse, install, update, and uninstall community packages
- IntelliSense — auto-generate
c_cpp_properties.json and compile_commands.json for accurate code completion
- clangd integration — auto-generate
compile_commands.json with watch mode, auto-restart clangd, auto-generate .clangd config
- IntelliSense settings panel — configure generation mode, UMK command, clangd diagnostic suppression, and view
c_cpp_properties.json
- Integrated terminal — run programs in VS Code's terminal, auto-enabled on headless/remote environments
- Workspace management — automatic
.code-workspace creation and switching per assembly
- Configurable — build methods, flags, link modes, output paths, error limits, C++ standard, and more
Requirements
- U++ with
umk on $PATH (ships as part of the build tools)
- Native Debug extension (optional, for VS Code debugger integration)
- GDB (
sudo apt install gdb)
Installing U++
U++ is not available via winget, Homebrew, or apt.
You can download it directly from ultimatepp.org and install manually using instructions.
Or, this extension will do everything all automatically for you!
Linux
U++ sources will be installed to ~/upp-stable. Two options are available:
umk only (no GTK required — works on headless VPS / servers):
After installation,the extension should auto-detect ~/upp-stable.
macOS
Requires Xcode Command Line Tools (xcode-select --install).
The install script will install Homebrew and openssl if needed.
Windows
Download the .7z archive from the download page and extract it with 7-Zip. The umk.exe binary is inside the extracted directory — add it to your $PATH.
Quick Start
- Open a workspace containing your U++ project
- Click the
⚙ UPP: no assembly item in the status bar
- Select your assembly (loaded from
~/.config/u++/theide/*.var)
- Pick a package from any assembly (or the selected one)
- Press
Ctrl+Shift+B → Build
- Press
Ctrl+Shift+Q → Run or Ctrl+Shift+D → Debug
Commands
| Command |
Keybinding |
Description |
UPP: Build Package |
Ctrl+Shift+B |
Build the active package |
UPP: Build & Run Package |
Ctrl+Shift+Q |
Build then execute the resulting binary |
UPP: Debug Build & Run |
Ctrl+Shift+D |
Build with debug symbols, launch gdb |
UPP: Stop Running Process |
Ctrl+Shift+X |
Send Ctrl+C to the running process |
UPP: Show Logs |
Alt+L |
Open the UPP Build output channel |
UPP: UppHub Package Manager |
Ctrl+Shift+U |
Browse, install, update community packages |
UPP: Rebuild All (-a) |
— |
Clean rebuild |
UPP: Select Active Assembly |
— |
Pick the assembly + main package |
UPP: New Package |
— |
Create a new package in the active assembly |
UPP: Open Output Directory |
— |
Open the build output dir in file explorer |
UPP: Generate compile_commands.json |
— |
Generate for all packages in dependency tree |
The sidebar shows the current build state and provides quick access to all actions:
| Item |
Description |
| New Package |
Create a new U++ package from templates |
| Assembly |
Current assembly name (click to change) |
| Package |
Current package (click to browse all packages across assemblies) |
| Description |
Package description (click to edit) |
| Method |
Build method (GCC, CLANG, etc.) |
| Output |
Debug or Release mode |
| Config |
Extra compilation flags |
| C++ Standard |
C++ standard version (c++17, c++20, c++23, etc.) |
| Blitz |
Toggle BLITZ builds (-b) |
| Error Limit |
Kill build after N errors (0 = unlimited) |
| Build As |
Full build command |
| Run / Stop |
Build and run in terminal |
| Debug / Stop Debug |
Build with debug symbols and run |
| Output Dir |
Where the release binary is built |
| IntelliSense Files |
Generation mode dropdown + Generate/Regenerate button |
Package Selection
Click Package in the sidebar to open the package browser. Even without an assembly selected, you can search packages across all assemblies. The assembly name is shown in brackets (e.g. Core [git-reference]).
Double-click an assembly in the left panel to open its .var file for editing.
Click + New Assembly at the bottom of the assembly list to create a new assembly.
Settings
{
"upp.varDir": "",
"upp.umkPath": "umk",
"upp.buildMethod": "CLANG",
"upp.buildFlags": "",
"upp.buildThreads": "auto",
"upp.blitz": false,
"upp.extraFlags": "",
"upp.outPath": "",
"upp.outputDir": "",
"upp.outputPerAssembly": false,
"upp.useTarget": false,
"upp.debuggerPath": "gdb",
"upp.cppStandard": "",
"upp.errorLimit": 10,
"upp.buildCommand": "",
"upp.debugCommand": "",
"upp.releaseCommand": "",
"upp.restartClangdAfterGenerate": true
}
| Setting |
Default |
Description |
upp.varDir |
"" |
Directory containing .var assembly files. Defaults to ~/.config/u++/theide/ |
upp.umkPath |
"umk" |
Full path to umk if not on $PATH |
upp.buildMethod |
"CLANG" |
Build method name or path to .bm file |
upp.buildFlags |
"" |
Build flags without dash (e.g. "bsH8" for BLITZ+shared+8 threads) |
upp.buildThreads |
"auto" |
Parallel build threads passed as -H<n>. 'auto' uses CPU core count. Empty disables auto-assignment. Ignored if buildFlags already contains H. |
upp.blitz |
false |
Enable BLITZ builds (-b). When enabled, U++ precompiles headers for faster builds |
upp.extraFlags |
"" |
Compilation flags as +FLAG,FLAG (e.g. "GUI,X11") |
upp.outPath |
"" |
Override output file or directory |
upp.workspacesDir |
"" |
Directory for .code-workspace files |
upp.outputDir |
"" |
U++ build output directory. Defaults to ~/.cache/upp.out/ |
upp.outputPerAssembly |
false |
Mirror U++ output_per_assembly: prepend <assembly>/ to the output path |
upp.useTarget |
false |
Mirror umk -u (use_target): store all target files in the same directory |
upp.debuggerPath |
"gdb" |
Path to gdb executable |
upp.cppStandard |
"" |
Override the C++ standard for IntelliSense (e.g. "c++17", "c++20"). Leave empty to use the platform default |
upp.errorLimit |
10 |
Kill the build after this many errors. 0 = unlimited (umk default) |
upp.guiMode |
"auto" |
"auto", "gui", or "console" — controls +GUI flag |
upp.runArgs |
"" |
Extra arguments passed to the binary when running |
upp.buildCommand |
"" |
Auto-generated umk build command (editable) |
upp.debugCommand |
"" |
Auto-generated debug build command (strips r and d flags) |
upp.releaseCommand |
"" |
Auto-generated release build command (adds r flag) |
upp.compileCommandsMode |
"auto" |
"manual" or "auto" — how compile_commands.json files are generated |
upp.generateCompileCommands |
"" |
Auto-generated umk command for compile_commands.json |
upp.outputConsole |
"auto" |
When to open output panel: "always", "auto", "never" |
upp.terminalApp |
"" |
External terminal emulator to run programs in. Empty = auto-detect |
upp.useIntegratedTerminal |
false |
Run programs in VS Code's integrated terminal. Auto-enabled on headless/remote |
upp.restartClangdAfterGenerate |
true |
Restart clangd after generating compile_commands.json |
upp.clangdSuppress |
["ambiguous_reference", ...] |
Clangd diagnostic codes to suppress for U++ framework headers |
upp.autoPackageSwitchWorkspace |
true |
Auto-switch workspace when selecting a package |
Debugging
How it works
- Click Debug (or
Ctrl+Shift+D)
- Extension builds with debug symbols (automatically strips
r and d from build flags)
- Generates
.vscode/launch.json with correct binary path
- Launches gdb via Native Debug or C/C++
Without a debug extension, opens gdb <binary> in the terminal for manual debugging.
Binary path resolution
The extension computes the output path exactly the way umk does (mirroring
MakeBuild::OutDir in uppsrc/ide/Builders/Build.cpp), then falls back to a
filesystem scan if the computed path doesn't exist yet.
Default umk layout (upp.outputPerAssembly = false, upp.useTarget = false):
<out>/<package>/<method>.<variant>/<binary>
For example, a debug + shared build of the Log package with method CLANG:
~/.cache/upp.out/Log/CLANG.Debug.Debug_Full.Main.Noblitz.Shared/Log
With upp.outputPerAssembly = true (theide-style) the assembly name is prepended:
~/.cache/upp.out/<assembly>/<package>/<method>.<variant>/<binary>
With upp.useTarget = true (umk -u) the <package>/ segment is omitted and
Main is excluded from the variant name:
~/.cache/upp.out/<method>.<variant>/<binary>
The variant name is built from the build configuration flags (sorted +
InitCaps'd): Debug, Debug_Full (default, unless -d), Main (main
package, unless useTarget), Noblitz (debug + no -b), Blitz (release
with -b), Shared/Shared.So (link modes), plus +FLAG configuration flags.
When the computed path doesn't exist, the extension scans <out> for build
directories (names starting with CLANG., GCC., etc.) containing the binary.
Build flags for debug
The debug command automatically strips these flags from upp.buildFlags:
r — release mode (removes optimizations, keeps debug symbols)
d — minimal debug mode (removes debug symbols)
This ensures the binary always has full debug symbols for gdb.
Recommended Linux stack
- VS Code / VS Code OSS
- Native Debug (lightweight, no Microsoft dependencies)
- GDB (
sudo apt install gdb)
compile_commands.json Generation
For clangd and clang-based tooling.
Modes
| Mode |
Behavior |
auto |
Watch source files, regenerate automatically (2s debounce) — default |
manual |
Generate on demand via sidebar button |
clangd integration
After generating compile_commands.json, the extension automatically restarts the clangd language server (if upp.restartClangdAfterGenerate is true) so it picks up the new data immediately.
UMK Build Flags
| Flag |
Description |
| (none) |
Debug mode with full debug symbols (default) |
a |
Rebuild all |
b |
Use BLITZ build |
r |
Release mode |
1 |
Release mode, optimize for size |
2 |
Release mode, optimize for speed |
s |
Use shared libraries |
S |
Use shared libraries and build as shared library |
v |
Verbose output |
l |
Silent mode |
m |
Create a map file |
u |
Use target directory |
M |
Create makefile |
Hn |
Number of build threads (e.g. H8) |
j |
Generate compile_commands.json |
h |
Delete UppHub folder and reinstall missing packages |
U |
Install missing UppHub packages and update all |
Assembly files live in ~/.config/u++/theide/ (modern U++) or ~/.upp/theide/ (legacy):
UPP = "/path/to/nest1;/path/to/nest2;";
OUTPUT = "/path/to/cache/out";
The UPP key holds semicolon-separated nest directories used for include path resolution.
Known Limitations
- Linux-first — primary development and testing on Arch/CachyOS. Windows works but may lag behind. macOS is untested.
- U++ required —
umk must be installed and available on $PATH
- GDB required — debugging needs gdb installed (
sudo apt install gdb on Debian/Ubuntu, pacman -S gdb on Arch)
Development
git clone https://github.com/arilect/upp-umk.git
cd upp-umk
npm install
npm run compile
To watch for changes during development:
npm run watch
To package as a .vsix:
npm install -g @vscode/vsce
vsce package
code --install-extension upp-umk-*.vsix
License
MIT