Skip to content

tgbender/portablemsvc

Repository files navigation

portablemsvc

PortableMSVC is a command-line utility for downloading, extracting, and managing a fully portable Microsoft C/C++ toolchain (MSVC + Windows SDK) on Windows—without requiring a full Visual Studio install.

Features

  • Fetch the latest (or specified) MSVC toolset and Windows SDK from the official Visual Studio release channel
  • Download and extract ZIPs, VSIX, MSI, and embedded CABs via msiexec without UI
  • Prune unneeded files (debug symbols, telemetry, etc.) to minimize disk usage
  • Generate env.json, activate.cmd, activate.ps1, and activate.xsh for easy environment setup
  • Support for xonsh, PowerShell, and Command Prompt activation
  • Register/unregister toolchains in HKCU\Environment, with automatic PATH backup
  • Maintain multiple portable installs side-by-side via a simple JSON database
  • Plumbum-based CLI with subcommands for listing, installing, and managing toolchains

Requirements

  • Windows 10+
  • Python 3.12+
    • May work on lower versions but not tested
  • msiexec.exe on PATH (standard on Windows)
  • Required Python packages (install via pip install . or pip install -r requirements.txt):
    • plumbum (CLI framework)
    • winregenv (registry manipulation)
    • filelock (atomic file/registry locking)

Installation

Using UV (https://github.com/astral-sh/uv) Recommended

uv tool install git+https://github.com/tgbender/portablemsvc@main

The UV tool bin directory may need to be added to path

Alternative: Clone and install locally

git clone https://github.com/your-org/portablemsvc.git
cd portablemsvc
pip install .

This provides the portablemsvc console script on your PATH.

Usage

Run portablemsvc --help to view global options and subcommands.

Subcommands

  • search - Search available MSVC and SDK versions
  • list - List installed toolchains
  • install - Install a portable toolchain
  • register - Register toolchain into HKCU\Environment
  • unregister - Unregister toolchain from HKCU\Environment
  • install-from-lockfile - Reproducible install from a lockfile
  • get-path - Get install path for build scripts

Search Available Versions

portablemsvc search [--channel release|preview] [--no-cache] [--full]

Search for available MSVC and Windows SDK versions before installing.

Install a Portable Toolchain

portablemsvc install
  [--host x64|x86|arm|arm64]
  [--target x64|x86|arm|arm64|all]
  [--msvc-version <major.minor>]
  [--sdk-version <build>]
  [--channel release|preview]
  [--accept-license]
  [--no-cache]
  [--output <custom_dir>]

By default, installs the latest x64 MSVC + SDK under: %LOCALAPPDATA%\portable\msvc\msvc-<full_version>_sdk-<build>

Environment Variable Overrides:

Variable Purpose
PORTABLEMSVC_CACHE Override download cache directory
PORTABLEMSVC_DATA Override install directory
PORTABLEMSVC_CONFIG Override config directory
PORTABLEMSVC_TEMP Override temp directory

Example:

set PORTABLEMSVC_CACHE=D:\cache\portablemsvc
portablemsvc install

List Installed Toolchains

portablemsvc list

Displays for each install:

  • ID
  • Path
  • MSVC (manifest) version
  • MSVC (internal) build folder version
  • SDK version
  • Host & Targets
  • Installed at timestamp

Register / Unregister

  • Register the toolchain into your user environment:

    portablemsvc register [--id <install_id>]
  • Unregister (restore original PATH):

    portablemsvc unregister [--id <install_id>]

Example Workflow

  1. Install the latest x64 toolchain
    (you will be prompted to review and accept the Microsoft license terms):

    portablemsvc install
  2. Register it into your environment:

    portablemsvc register
  3. Activate the environment (choose one):

    Command Prompt:

    activate.cmd

    PowerShell:

    .\activate.ps1

    xonsh:

    source activate.xsh
  4. Verify:

    where link.exe
    rustup show        # should show x86_64-pc-windows-msvc
    cargo build        # should invoke link.exe from your portable MSVC
  5. List all installs:

    portablemsvc list
  6. Switch to another install later:

    portablemsvc register --id <other_install_id>
  7. Cleanup:

    portablemsvc unregister

Build Script Integration

The get-path command outputs the installation root for use in build scripts:

# Get path for latest install
MSVC_ROOT=$(portablemsvc get-path)

# Get path by lockfile (matches MSVC/SDK versions)
MSVC_ROOT=$(portablemsvc get-path --lockfile ./portablemsvc.lock)

# Get path by install ID
MSVC_ROOT=$(portablemsvc get-path --id <install_id>)

# Use in build
source "$MSVC_ROOT/activate.cmd"
nmake /f Makefile

The env.json file contains all environment variables needed for building:

  • CC, CXX, AR - Compiler paths
  • PATH, INCLUDE, LIB - Search paths
  • TOOL_VERSIONS - PE file versions of tools

CI/CD Usage

For reproducible builds in CI, use a lockfile:

# Install and generate lockfile (commit this to your repo)
portablemsvc install --accept-license --output .\msvc

# In CI, install from the lockfile for bit-for-bit reproducibility
portablemsvc install-from-lockfile portablemsvc.lock --accept-license

GitHub Actions Example:

- uses: actions/setup-python@v5
  with:
    python-version: "3.12"
- uses: astral-sh/setup-uv@v5
- run: uv tool install portablemsvc
- run: portablemsvc install-from-lockfile portablemsvc.lock --accept-license
  env:
    PORTABLEMSVC_CACHE: D:\cache\portablemsvc
# Get the path and use it
- run: |
    MSVC_PATH=$(portablemsvc get-path --lockfile portablemsvc.lock)
    "$MSVC_PATH/activate.cmd" && cargo build --release
  shell: bash

Contributing

Contributions and issues are welcome!

  • Run mise run lint to check code style and types
  • Run mise run test to run the test suite
  • Keep PRs focused on a single feature or bugfix
  • Add tests for all new behavior

License

This project is MIT-licensed. See LICENSE for details.

Disclaimer

The MSVC and Windows SDK toolchains downloaded by PortableMSVC remain subject to Microsoft's license terms and conditions.
By using this tool to fetch, install, or manage those toolchains, you agree to comply with all applicable Microsoft licensing requirements.

Acknowledgments

Huge thanks to @mmozeiko for foundational work on portable MSVC tooling inspiration.

Testing 🔍

Run the test suite:

# Fast tests (no downloads)
mise run test

# Most tests including slow_installs but not integration (~20GB downloads)
mise run test-most

# Full tests including integration (~20GB downloads)
mise run test-all

Test coverage includes:

  • C/C++ compilation with Windows SDK headers
  • Static library creation with lib.exe
  • Tool version capture (PE file metadata)
  • Environment variable verification
  • Lockfile-based reproducible installs

TODO

  • Verify that portablemsvc install --target=x64,arm64,arm
    • all specified host/target tool directories appear under VC/Tools/MSVC/.../bin
    • correct compiler/linker executables (cl.exe, link.exe) are present per target
  • Add integration tests covering the --target=all shorthand
  • Ensure generated env.json and activation scripts include all targets
  • Confirm redistribution DLLs (msdia140.dll, debug CRTs) deploy properly per target
  • Exercise cross‐compilation scenarios (e.g. Host=x64 → Target=arm)
  • Automate CI runs on Windows 10 and 11 to catch platform‐specific issues

About

PortableMSVC is a command-line tool that automates downloading, caching, extracting, and managing fully portable Microsoft C/C++ toolchains (MSVC and Windows SDK) on Windows—no Visual Studio installation required.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages