Skip to content

Instantly share code, notes, and snippets.

@mmozeiko
Last active March 13, 2025 03:42
Show Gist options
  • Save mmozeiko/7f3162ec2988e81e56d5c4e22cde9977 to your computer and use it in GitHub Desktop.
Save mmozeiko/7f3162ec2988e81e56d5c4e22cde9977 to your computer and use it in GitHub Desktop.
Download MSVC compiler/linker & Windows SDK without installing full Visual Studio

This downloads standalone MSVC compiler, linker & other tools, also headers/libraries from Windows SDK into portable folder, without installing Visual Studio. Has bare minimum components - no UWP/Store/WindowsRT stuff, just files & tools for native desktop app development.

Run py.exe portable-msvc.py and it will download output into msvc folder. By default it will download latest available MSVC & Windows SDK - currently v14.40.33807 and v10.0.26100.0.

You can list available versions with py.exe portable-msvc.py --show-versions and then pass versions you want with --msvc-version and --sdk-version arguments.

To use cl.exe/link.exe first run setup_TARGET.bat - after that PATH/INCLUDE/LIB env variables will be updated to use all the tools as usual. You can also use clang-cl.exe with these includes & libraries.

To use clang-cl.exe without running setup.bat, pass extra /winsysroot msvc argument (msvc is folder name where output is stored).

#!/usr/bin/env python3
import io
import os
import sys
import stat
import json
import shutil
import hashlib
import zipfile
import tempfile
import argparse
import subprocess
import urllib.error
import urllib.request
from pathlib import Path
OUTPUT = Path("msvc") # output folder
DOWNLOADS = Path("downloads") # temporary download files
# NOTE: not all host & target architecture combinations are supported
DEFAULT_HOST = "x64"
ALL_HOSTS = "x64 x86 arm64".split()
DEFAULT_TARGET = "x64"
ALL_TARGETS = "x64 x86 arm arm64".split()
MANIFEST_URL = "https://aka.ms/vs/17/release/channel"
MANIFEST_PREVIEW_URL = "https://aka.ms/vs/17/pre/channel"
ssl_context = None
def download(url):
with urllib.request.urlopen(url, context=ssl_context) as res:
return res.read()
total_download = 0
def download_progress(url, check, filename):
fpath = DOWNLOADS / filename
if fpath.exists():
data = fpath.read_bytes()
if hashlib.sha256(data).hexdigest() == check.lower():
print(f"\r{filename} ... OK")
return data
global total_download
with fpath.open("wb") as f:
data = io.BytesIO()
with urllib.request.urlopen(url, context=ssl_context) as res:
total = int(res.headers["Content-Length"])
size = 0
while True:
block = res.read(1<<20)
if not block:
break
f.write(block)
data.write(block)
size += len(block)
perc = size * 100 // total
print(f"\r{filename} ... {perc}%", end="")
print()
data = data.getvalue()
digest = hashlib.sha256(data).hexdigest()
if check.lower() != digest:
sys.exit(f"Hash mismatch for f{pkg}")
total_download += len(data)
return data
# super crappy msi format parser just to find required .cab files
def get_msi_cabs(msi):
index = 0
while True:
index = msi.find(b".cab", index+4)
if index < 0:
return
yield msi[index-32:index+4].decode("ascii")
def first(items, cond = lambda x: True):
return next((item for item in items if cond(item)), None)
### parse command-line arguments
ap = argparse.ArgumentParser()
ap.add_argument("--show-versions", action="store_true", help="Show available MSVC and Windows SDK versions")
ap.add_argument("--accept-license", action="store_true", help="Automatically accept license")
ap.add_argument("--msvc-version", help="Get specific MSVC version")
ap.add_argument("--sdk-version", help="Get specific Windows SDK version")
ap.add_argument("--preview", action="store_true", help="Use preview channel for Preview versions")
ap.add_argument("--target", default=DEFAULT_TARGET, help=f"Target architectures, comma separated ({','.join(ALL_TARGETS)})")
ap.add_argument("--host", default=DEFAULT_HOST, help=f"Host architecture", choices=ALL_HOSTS)
args = ap.parse_args()
host = args.host
targets = args.target.split(',')
for target in targets:
if target not in ALL_TARGETS:
sys.exit(f"Unknown {target} target architecture!")
### get main manifest
URL = MANIFEST_PREVIEW_URL if args.preview else MANIFEST_URL
try:
manifest = json.loads(download(URL))
except urllib.error.URLError as err:
import ssl
if isinstance(err.args[0], ssl.SSLCertVerificationError):
# for more info about Python & issues with Windows certificates see https://stackoverflow.com/a/52074591
print("ERROR: ssl certificate verification error")
try:
import certifi
except ModuleNotFoundError:
print("ERROR: please install 'certifi' package to use Mozilla certificates")
print("ERROR: or update your Windows certs, see instructions here: https://woshub.com/updating-trusted-root-certificates-in-windows-10/#h2_3")
sys.exit()
print("NOTE: retrying with certifi certificates")
ssl_context = ssl.create_default_context(cafile=certifi.where())
manifest = json.loads(download(URL))
else:
raise
### download VS manifest
ITEM_NAME = "Microsoft.VisualStudio.Manifests.VisualStudioPreview" if args.preview else "Microsoft.VisualStudio.Manifests.VisualStudio"
vs = first(manifest["channelItems"], lambda x: x["id"] == ITEM_NAME)
payload = vs["payloads"][0]["url"]
vsmanifest = json.loads(download(payload))
### find MSVC & WinSDK versions
packages = {}
for p in vsmanifest["packages"]:
packages.setdefault(p["id"].lower(), []).append(p)
msvc = {}
sdk = {}
for pid,p in packages.items():
if pid.startswith("Microsoft.VC.".lower()) and pid.endswith(".Tools.HostX64.TargetX64.base".lower()):
pver = ".".join(pid.split(".")[2:4])
if pver[0].isnumeric():
msvc[pver] = pid
elif pid.startswith("Microsoft.VisualStudio.Component.Windows10SDK.".lower()) or \
pid.startswith("Microsoft.VisualStudio.Component.Windows11SDK.".lower()):
pver = pid.split(".")[-1]
if pver.isnumeric():
sdk[pver] = pid
if args.show_versions:
print("MSVC versions:", " ".join(sorted(msvc.keys())))
print("Windows SDK versions:", " ".join(sorted(sdk.keys())))
sys.exit(0)
msvc_ver = args.msvc_version or max(sorted(msvc.keys()))
sdk_ver = args.sdk_version or max(sorted(sdk.keys()))
if msvc_ver in msvc:
msvc_pid = msvc[msvc_ver]
msvc_ver = ".".join(msvc_pid.split(".")[2:6])
else:
sys.exit(f"Unknown MSVC version: f{args.msvc_version}")
if sdk_ver in sdk:
sdk_pid = sdk[sdk_ver]
else:
sys.exit(f"Unknown Windows SDK version: f{args.sdk_version}")
print(f"Downloading MSVC v{msvc_ver} and Windows SDK v{sdk_ver}")
### agree to license
tools = first(manifest["channelItems"], lambda x: x["id"] == "Microsoft.VisualStudio.Product.BuildTools")
resource = first(tools["localizedResources"], lambda x: x["language"] == "en-us")
license = resource["license"]
if not args.accept_license:
accept = input(f"Do you accept Visual Studio license at {license} [Y/N] ? ")
if not accept or accept[0].lower() != "y":
sys.exit(0)
OUTPUT.mkdir(exist_ok=True)
DOWNLOADS.mkdir(exist_ok=True)
### download MSVC
msvc_packages = [
f"microsoft.visualcpp.dia.sdk",
f"microsoft.vc.{msvc_ver}.crt.headers.base",
f"microsoft.vc.{msvc_ver}.crt.source.base",
f"microsoft.vc.{msvc_ver}.asan.headers.base",
f"microsoft.vc.{msvc_ver}.pgo.headers.base",
]
for target in targets:
msvc_packages += [
f"microsoft.vc.{msvc_ver}.tools.host{host}.target{target}.base",
f"microsoft.vc.{msvc_ver}.tools.host{host}.target{target}.res.base",
f"microsoft.vc.{msvc_ver}.crt.{target}.desktop.base",
f"microsoft.vc.{msvc_ver}.crt.{target}.store.base",
f"microsoft.vc.{msvc_ver}.premium.tools.host{host}.target{target}.base",
f"microsoft.vc.{msvc_ver}.pgo.{target}.base",
]
if target in ["x86", "x64"]:
msvc_packages += [f"microsoft.vc.{msvc_ver}.asan.{target}.base"]
redist_suffix = ".onecore.desktop" if target == "arm" else ""
redist_pkg = f"microsoft.vc.{msvc_ver}.crt.redist.{target}{redist_suffix}.base"
if redist_pkg not in packages:
redist_name = f"microsoft.visualcpp.crt.redist.{target}{redist_suffix}"
redist = first(packages[redist_name])
redist_pkg = first(redist["dependencies"], lambda dep: dep.endswith(".base")).lower()
msvc_packages += [redist_pkg]
for pkg in sorted(msvc_packages):
if pkg not in packages:
print(f"\r{pkg} ... !!! MISSING !!!")
continue
p = first(packages[pkg], lambda p: p.get("language") in (None, "en-US"))
for payload in p["payloads"]:
filename = payload["fileName"]
download_progress(payload["url"], payload["sha256"], filename)
with zipfile.ZipFile(DOWNLOADS / filename) as z:
for name in z.namelist():
if name.startswith("Contents/"):
out = OUTPUT / Path(name).relative_to("Contents")
out.parent.mkdir(parents=True, exist_ok=True)
out.write_bytes(z.read(name))
### download Windows SDK
sdk_packages = [
f"Windows SDK for Windows Store Apps Tools-x86_en-us.msi",
f"Windows SDK for Windows Store Apps Headers-x86_en-us.msi",
f"Windows SDK for Windows Store Apps Headers OnecoreUap-x86_en-us.msi",
f"Windows SDK for Windows Store Apps Libs-x86_en-us.msi",
f"Universal CRT Headers Libraries and Sources-x86_en-us.msi",
]
for target in ALL_TARGETS:
sdk_packages += [
f"Windows SDK Desktop Headers {target}-x86_en-us.msi",
f"Windows SDK OnecoreUap Headers {target}-x86_en-us.msi",
]
for target in targets:
sdk_packages += [f"Windows SDK Desktop Libs {target}-x86_en-us.msi"]
with tempfile.TemporaryDirectory(dir=DOWNLOADS) as d:
dst = Path(d)
sdk_pkg = packages[sdk_pid][0]
sdk_pkg = packages[first(sdk_pkg["dependencies"]).lower()][0]
msi = []
cabs = []
# download msi files
for pkg in sorted(sdk_packages):
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
if payload is None:
continue
msi.append(DOWNLOADS / pkg)
data = download_progress(payload["url"], payload["sha256"], pkg)
cabs += list(get_msi_cabs(data))
# download .cab files
for pkg in cabs:
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
download_progress(payload["url"], payload["sha256"], pkg)
print("Unpacking msi files...")
# run msi installers
for m in msi:
subprocess.check_call(f'msiexec.exe /a "{m}" /quiet /qn TARGETDIR="{OUTPUT.resolve()}"')
(OUTPUT / m.name).unlink()
### versions
msvcv = first((OUTPUT / "VC/Tools/MSVC").glob("*")).name
sdkv = first((OUTPUT / "Windows Kits/10/bin").glob("*")).name
# place debug CRT runtime files into MSVC bin folder (not what real Visual Studio installer does... but is reasonable)
# NOTE: these are Target architecture, not Host architecture binaries
redist = OUTPUT / "VC/Redist"
if redist.exists():
redistv = first((redist / "MSVC").glob("*")).name
src = redist / "MSVC" / redistv / "debug_nonredist"
for target in targets:
for f in (src / target).glob("**/*.dll"):
dst = OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{host}" / target
f.replace(dst / f.name)
shutil.rmtree(redist)
# copy msdia140.dll file into MSVC bin folder
# NOTE: this is meant only for development - always Host architecture, even when placed into all Target architecture folders
msdia140dll = {
"x86": "msdia140.dll",
"x64": "amd64/msdia140.dll",
"arm": "arm/msdia140.dll",
"arm64": "arm64/msdia140.dll",
}
dst = OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{host}"
src = OUTPUT / "DIA%20SDK/bin" / msdia140dll[host]
for target in targets:
shutil.copyfile(src, dst / target / src.name)
shutil.rmtree(OUTPUT / "DIA%20SDK")
### cleanup
shutil.rmtree(OUTPUT / "Common7", ignore_errors=True)
shutil.rmtree(OUTPUT / "VC/Tools/MSVC" / msvcv / "Auxiliary")
for target in targets:
for f in [f"store", "uwp", "enclave", "onecore"]:
shutil.rmtree(OUTPUT / "VC/Tools/MSVC" / msvcv / "lib" / target / f, ignore_errors=True)
shutil.rmtree(OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{host}" / target / "onecore", ignore_errors=True)
for f in ["Catalogs", "DesignTime", f"bin/{sdkv}/chpe", f"Lib/{sdkv}/ucrt_enclave"]:
shutil.rmtree(OUTPUT / "Windows Kits/10" / f, ignore_errors=True)
for arch in ["x86", "x64", "arm", "arm64"]:
if arch not in targets:
shutil.rmtree(OUTPUT / "Windows Kits/10/Lib" / sdkv / "ucrt" / arch, ignore_errors=True)
shutil.rmtree(OUTPUT / "Windows Kits/10/Lib" / sdkv / "um" / arch, ignore_errors=True)
if arch != host:
shutil.rmtree(OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{arch}", ignore_errors=True)
shutil.rmtree(OUTPUT / "Windows Kits/10/bin" / sdkv / arch, ignore_errors=True)
# executable that is collecting & sending telemetry every time cl/link runs
for target in targets:
(OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{host}/{target}/vctip.exe").unlink(missing_ok=True)
# extra files for nvcc
build = OUTPUT / "VC/Auxiliary/Build"
build.mkdir(parents=True, exist_ok=True)
(build / "vcvarsall.bat").write_text("rem both bat files are here only for nvcc, do not call them manually")
(build / "vcvars64.bat").touch()
### setup.bat
for target in targets:
SETUP = fr"""@echo off
set VSCMD_ARG_HOST_ARCH={host}
set VSCMD_ARG_TGT_ARCH={target}
set VCToolsVersion={msvcv}
set WindowsSDKVersion={sdkv}\
set VCToolsInstallDir=%~dp0VC\Tools\MSVC\{msvcv}\
set WindowsSdkBinPath=%~dp0Windows Kits\10\bin\
set PATH=%~dp0VC\Tools\MSVC\{msvcv}\bin\Host{host}\{target};%~dp0Windows Kits\10\bin\{sdkv}\{host};%~dp0Windows Kits\10\bin\{sdkv}\{host}\ucrt;%PATH%
set INCLUDE=%~dp0VC\Tools\MSVC\{msvcv}\include;%~dp0Windows Kits\10\Include\{sdkv}\ucrt;%~dp0Windows Kits\10\Include\{sdkv}\shared;%~dp0Windows Kits\10\Include\{sdkv}\um;%~dp0Windows Kits\10\Include\{sdkv}\winrt;%~dp0Windows Kits\10\Include\{sdkv}\cppwinrt
set LIB=%~dp0VC\Tools\MSVC\{msvcv}\lib\{target};%~dp0Windows Kits\10\Lib\{sdkv}\ucrt\{target};%~dp0Windows Kits\10\Lib\{sdkv}\um\{target}
"""
(OUTPUT / f"setup_{target}.bat").write_text(SETUP)
print(f"Total downloaded: {total_download>>20} MB")
print("Done!")
@realyukii
Copy link

I think it's an issue of msys, but tried on powershell:
image

and it seems not an issue of msys

@realyukii
Copy link

the script is in the latest version:

ACER@LAPTOP MSYS ~
$  sha256sum.exe portable-msvc.py
da47e39afb4e8f757bbd036171ef7295534b06bcdfa40004c5b2befc715ae389 *portable-msvc.py

ACER@LAPTOP MSYS ~
$  curl -o latest-version.py -L "https://gist.githubusercontent.com/mmozeiko/7f3162ec2988e81e56d5c4e22cde9977/raw/9f8555326867d4ecba70ee07f105f159f5d8afd5/portable-msvc.py"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 12625  100 12625    0     0   1215      0  0:00:10  0:00:10 --:--:--  3036

ACER@LAPTOP MSYS ~
$  sha256sum.exe latest-version.py
da47e39afb4e8f757bbd036171ef7295534b06bcdfa40004c5b2befc715ae389 *latest-version.py

@mmozeiko
Copy link
Author

I think the error in msys2 happens because you are using msys python.exe, not Windows native one. The msys2 python resolves paths to msys2 paths - you can see it tries to unpack installation into /home/ACER/msvc folder, but Windows does not know what is /home/... path. It needs native path - like C:\Users\whatever\...

Try to execute it with native python, do not use msys2 python executable.

I'm not sure why it is showing UI, but can try adding extra arguments for logging - /log and C:\some\folder\log.txt. Then examine log file when UI is shown, maybe it will explain what is wrong.

@realyukii
Copy link

realyukii commented Oct 22, 2024

after looking at the documentation about error code, I found it's ERROR_TOO_MANY_SEM_REQUESTS? I'm not sure where I should look into the error code, whether it's a decimal or hexadecimal form?

EDIT: sorry I'm not notice your comment before posting this comment, will try your suggestion.

EDIT 2:
by the way after trial and error, I found that the UI prompt seems only occurs when executing the script on the msys2 terminal.
and it executed without error on powershell, no have idea why msiexec isn't reliable on msys2 environment.

so I ended up following your suggestion ^^

@Raduq91
Copy link

Raduq91 commented Nov 14, 2024

Hi @mmozeiko ,how to download/add a component "Microsoft.VisualStudio.Component.VC.Modules.x86.x64". Adding lines in msvc_packages did not work
f"microsoft.vc.{msvc_ver}.modules.x86.x64.base", or f"microsoft.vc.modules.x86.x64.base", ?

Some info, ex. files go into MSVC\14.39.33519\ifc\x64\Debug Release
set "IFCPATH=%MSVC_ROOT%\ifc\x64
(copied manually files from visual studio installer)

With import std.core instead of #include, main.cpp with some functions(array, string, vector, cout) builds in around 0.350s instead of 0.850s

@mmozeiko
Copy link
Author

I think it should be microsoft.visualcpp.ifc.{target}. But I've never used modules, so no idea if it'll work. I prefer to use precompiled headers instead.

@novicearts
Copy link

Thanks for this script. I have a windows 8.1 machine I'd like to keep minimal w.r.t. msvc installation, but the versioning system confuses me.
Are you aware of any table that indicates which version of msvc and windows SDK is best compatible with windows 8 and 7?

@mmozeiko
Copy link
Author

mmozeiko commented Nov 17, 2024

@codedevmk
Copy link

Error on line 285? Ensure your execution path has no spaces for subprocess:
subprocess.check_call(["msiexec.exe", "/a", m, "/quiet", "/qn", f"TARGETDIR={OUTPUT.resolve()}"]) to work.

@clibdev
Copy link

clibdev commented Dec 21, 2024

When attempting to compile a CUDA file using nvcc.exe, I encountered the following error: "nvcc fatal : Host compiler targets unsupported OS".

After searching on the NVIDIA forum, I discovered that nvcc.exe requires the presence of two specific files: VC\Auxiliary\Build\vcvarsall.bat and VC\Auxiliary\Build\vcvars64.bat. To resolve the issue, I created empty versions of these files, and nvcc.exe began working as expected.

@mmozeiko, could you update your script to include the creation of these empty files (VC\Auxiliary\Build\vcvarsall.bat and VC\Auxiliary\Build\vcvars64.bat)?

Reference: https://forums.developer.nvidia.com/t/nvcc-fatal-host-compiler-targets-unsupported-os-on-win11-with-vs-2022-cuda-12-2/267193

@mmozeiko
Copy link
Author

Added both bat files.

@madebr
Copy link

madebr commented Jan 20, 2025

When using a portable Windows python executable, running python portable-msvc.py --show-versions fails with the following error:

Traceback (most recent call last):
  File "Z:\tmp\portable-msvc.py", line 159, in <module>
    exit(0)
    ^^^^
NameError: name 'exit' is not defined

Replacing every occurrence of exit(...) with sys.exit(...) fixes the issue.

@madebr
Copy link

madebr commented Jan 20, 2025

Running portable-msvc.py --target x86 --accept-license fails with the following error:

Traceback (most recent call last):
  File "D:\portable-msvc.py", line 261, in <module>
    sdk_pkg = packages[first(sdk_pkg["packages"]).lower()][0]

@mmozeiko
Copy link
Author

What is the full error when that happens? It works for me.
You may want to put something like print(sdk_pid, json.dumps(sdk_pkg, indent=2)) before line 261 and see what it prints out. If it prints out empty json then dump the whole packages json to see look inside to figure out why sdk_pid is not there.

@madebr
Copy link

madebr commented Jan 20, 2025

What is the full error when that happens? It works for me. You may want to put something like print(sdk_pid, json.dumps(sdk_pkg, indent=2)) before line 261 and see what it prints out. If it prints out empty json then dump the whole packages json to see look inside to figure out why sdk_pid is not there.

After downloading the latest portable-msvc script, the error went away.
Not sure what went wrong since wget'ed it yesterday.
The diff shows "packages" was replaced with "dependencies".

Sorry about the false alarm.

@mmozeiko
Copy link
Author

Updated code so it can find latest 14.43 preview version.

@CortexReaver
Copy link

CortexReaver commented Feb 23, 2025

there is no "setup_TARGET.bat" and "setup_x64.bat" doesn't do ANYTHING at all. Windows 10 Pro 22H2 19045.5247 running it from admin.
The setx command is working for me, not set

@mmozeiko
Copy link
Author

mmozeiko commented Feb 23, 2025

TARGET there means which target architecture you want to target. You run for whichever target you'll want to compile.
You don't need to run it from admin. That's irrelevant. You run it when you need environment set up. What exactly do you mean that bat file doesn't do anything?

@CortexReaver
Copy link

CortexReaver commented Feb 23, 2025

Because it doesn't do anything.
This works tho:

@echo off

setx VSCMD_ARG_HOST_ARCH x64
setx VSCMD_ARG_TGT_ARCH x64

setx VCToolsVersion 14.43.34808
setx WindowsSDKVersion 10.0.26100.0\

setx VCToolsInstallDir "%~dp0VC\Tools\MSVC\14.43.34808\"
setx WindowsSdkBinPath "%~dp0Windows Kits\10\bin\"

setx PATH "%~dp0VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64;%~dp0Windows Kits\10\bin\10.0.26100.0\x64;%~dp0Windows Kits\10\bin\10.0.26100.0\x64\ucrt;%PATH%"
setx INCLUDE "%~dp0VC\Tools\MSVC\14.43.34808\include;%~dp0Windows Kits\10\Include\10.0.26100.0\ucrt;%~dp0Windows Kits\10\Include\10.0.26100.0\shared;%~dp0Windows Kits\10\Include\10.0.26100.0\um;%~dp0Windows Kits\10\Include\10.0.26100.0\winrt;%~dp0Windows Kits\10\Include\10.0.26100.0\cppwinrt"
setx LIB "%~dp0VC\Tools\MSVC\14.43.34808\lib\x64;%~dp0Windows Kits\10\Lib\10.0.26100.0\ucrt\x64;%~dp0Windows Kits\10\Lib\10.0.26100.0\um\x64"

After that you still need to cleanup some quote symbols in the variables but it is still better than adding all of these by hand.

@mmozeiko
Copy link
Author

mmozeiko commented Feb 23, 2025

You are wrong about "anything". It does something. And I think you are misunderstanding what it is supposed to do. It only sets up environment for current command prompt session. That's is its only purpose.

It's works similarly like vcvarsall.bat file in full VS installation. Read more information about it here: https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-170

It won't modify global system environment. You usually don't want that - because what if you need different target architecture? Or different version compiler? Manipulating global environment will be super messy. This is not an installer script. It just places files in local folder and its up to you to use them correctly.

@CortexReaver
Copy link

You still don't get it. It won't add ANY variables at all, nor global or user specific. After running the bat file nothing has changed there at all. As I described earlier "set" has not worked for me, maybe this is an issue with my specific version of windows, idk. But I've provided an alternative bat file in case there some newbie like me who doesn't want to deal with all the M$ crap.

@mmozeiko
Copy link
Author

mmozeiko commented Feb 24, 2025

It won't add ANY variables at all, nor global or user specific.

Yes, that's expected. That is how it is supposed to work. I just sets variables in current command prompt without affecting global user or system env variables. As I said above, it works the same way how vcvarsall.bat file works. Please read the link I posted above.

@ysiivan
Copy link

ysiivan commented Feb 25, 2025

Installed ok thanks., Environment set. Rust installer still says "Rust requires a linker and Windows API libraries but they don't seem to be
available."
Any idea what else needs to be done?

@mmozeiko
Copy link
Author

I have never used rust, so I do not know how rust finds & uses C/C++ compiler or linker. You'll need to figure out it yourself. For example, for python it is documented here: https://docs.python.org/3.9/distutils/apiref.html#module-distutils.msvccompiler - it requires to set DISTUTILS_USE_SDK env variable. Maybe similar thing exists for rust.

@ysiivan
Copy link

ysiivan commented Feb 26, 2025

Adding this here in case someone ends up in the same boat like me. The Rust installer (and rustup I'm told) check for these two env var: VCINSTALLDIR and VCINSTALLDIR.
I think the installer just uses them as flags (set or not set), but in any case I set mine like so (PowerShell):

# $PSScriptRoot is the msvc folder
$env:VCINSTALLDIR = "$PSScriptRoot\VC\"
$env:VSINSTALLDIR = "$PSScriptRoot\"

Big thanks to you for the portable msvc and to the great folks from the Rust forum that helped with this!

@benjcarson
Copy link

Error on line 287? Ensure your execution path has no spaces for subprocess: subprocess.check_call(["msiexec.exe", "/a", m, "/quiet", "/qn", f"TARGETDIR={OUTPUT.resolve()}"]) to work.

Another reason this error may occur is if you run this script from a drive other than c:\. Apparently msiexec won't install .msi files located on secondary drives. Is anyone is aware of a command line option to make that work?

@mk14steve
Copy link

Brilliant. I set it up for Arm64 and I can compile c++ and arm64 asm from command line. Don't need bloaty visual studio!

@marakew
Copy link

marakew commented Mar 11, 2025

why your remove DIA SDK, can you keep it and normalize path instead %20 ?
also threre are need todo clean up in
Windows Kits\10\Redist\ D3D\{arm64 x64 x86}
and
Windows Kits\10\Redist\NBN\{arm64 x64 x86}

also may be need to add ifc module support as option for downloads

@marakew
Copy link

marakew commented Mar 11, 2025

interesting is it possible to add WDK to this script to allow driver develop bin/include/libs

@marakew
Copy link

marakew commented Mar 11, 2025

can you add formatted output json response files with options like --dump-json ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment