[*] Drop MSVC support

To keep this PR description as short as possible, I will save the
ranting about MSVC for the blog post. In short: MSVC has been nothing
but a complete and utter slog to maintain for the *entire* existence of
Eden. CI is an absolute nightmare, it requires *completely* different
compile flags and definitions, has several sets of hacks dedicated to
getting its codegen to cooperate, is a horror story with respect to
dependency management, and is now completely broken and can't launch
games anymore.

Microsoft, you have long overstayed your welcome. And you're not getting
it back ever again. Good riddance.

Signed-off-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
crueter 2026-05-06 00:25:30 -04:00
parent 86eae5cc41
commit 18c11b88a0
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
10 changed files with 57 additions and 717 deletions

View File

@ -1,6 +1,15 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
if (MSVC AND NOT I_WANT_A_BROKEN_MSVC_BUILD)
message(FATAL_ERROR "Support for the MSVC compiler has been dropped indefinitely. "
"This is not a bug. You will not receive support with issues related "
"to using Eden with MSVC, and there is ABSOLUTELY NO GUARANTEE that Eden "
"can be built on MSVC. Read more on our blog: https://eden-emu.dev/blog"
"\nSwitch to using MSYS2 instead: https://www.msys2.org"
"\nIf you *really* want to build anyways, set I_WANT_A_BROKEN_MSVC_BUILD=ON.")
endif()
cmake_minimum_required(VERSION 3.22)
project(yuzu)
@ -564,7 +573,7 @@ if (ENABLE_QT)
else()
message(STATUS "Using system Qt")
if (NOT Qt6_DIR)
set(Qt6_DIR "" CACHE PATH "Additional path to search for Qt6 libraries like C:/Qt/6.8.3/msvc2022_64/lib/cmake/Qt6")
set(Qt6_DIR "" CACHE PATH "Additional path to search for Qt6 libraries")
endif()
list(APPEND CMAKE_PREFIX_PATH "${Qt6_DIR}")
endif()

View File

@ -35,9 +35,6 @@ This is the recommended GUI method for Linux, macOS, and Windows.
<details>
<summary>Click to Open</summary>
> [!WARNING]
> On MSYS2, to use Qt Creator you are recommended to *also* install Qt from the online installer, ensuring to select the "MinGW" version.
Open the CMakeLists.txt file in your cloned directory via File -> Open File or Project (Ctrl+O), if you didn't clone Eden via the project import tool.
Select your desired "kit" (usually, the default is okay). RelWithDebInfo or Release is recommended:
@ -58,18 +55,10 @@ Hit "Configure Project", then wait for CMake to finish configuring (may take a w
>
>- *CMake* **MUST** be in your PATH (and also *ninja*, if you are using it as `<GENERATOR>`)
>- You *MUST* be in the cloned *Eden* directory
>
>On Windows:
>
> - It's recommended to install **[Ninja](https://ninja-build.org/)**
> - You must load **Visual C++ development environment**, this can be done by running our convenience script:
> - `tools/windows/load-msvc-env.ps1` (for PowerShell 5+)
> - `tools/windows/load-msvc-env.sh` (for MSYS2, Git Bash, etc)
Available `<GENERATOR>`:
- MSYS2: `MSYS Makefiles`
- MSVC: `Ninja` (preferred) or `Visual Studio 17 2022`
- MSYS2: `Ninja`
- macOS: `Ninja` (preferred) or `Xcode`
- Others: `Ninja` (preferred) or `UNIX Makefiles`
@ -79,61 +68,12 @@ Available `<BUILD_TYPE>`:
- `RelWithDebInfo` (debug symbols--compiled executable will be large)
- `Debug` (if you are using a debugger and annoyed with stuff getting optimized out)
Caveat for Debug Builds:
- If you're building with CCache, you will need to add the environment variable `CL` with the `/FS` flag ([Reference](https://learn.microsoft.com/pt-br/cpp/build/reference/fs-force-synchronous-pdb-writes?view=msvc-170))
Also see the root CMakeLists.txt for more build options. Usually the default will provide the best experience, however.
Also see the root CMakeLists.txt for more build options. Usually the default will provide the best experience.
```sh
cmake -S . -B build -G "<GENERATOR>" -DCMAKE_BUILD_TYPE=<BUILD_TYPE> -DYUZU_TESTS=OFF
```
If you are on Windows and prefer to use Clang:
```sh
cmake -S . -B build -G "<GENERATOR>" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
```
</details>
### Option C: [CLion](https://www.jetbrains.com/clion/)
<details>
<summary>Click to Open</summary>
- Clone the Repository:
<img src="https://user-images.githubusercontent.com/42481638/216899046-0d41d7d6-8e4d-4ed2-9587-b57088af5214.png" width="500">
<img src="https://user-images.githubusercontent.com/42481638/216899061-b2ea274a-e88c-40ae-bf0b-4450b46e9fea.png" width="500">
<img src="https://user-images.githubusercontent.com/42481638/216899076-0e5988c4-d431-4284-a5ff-9ecff973db76.png" width="500">
---
### Building & Setup
- Once Cloned, You will be taken to a prompt like the image below:
<img src="https://user-images.githubusercontent.com/42481638/216899092-3fe4cec6-a540-44e3-9e1e-3de9c2fffc2f.png" width="500">
- Set the settings to the image below:
- Change `Build type: Release`
- Change `Name: Release`
- Change `Toolchain Visual Studio`
- Change `Generator: Let CMake decide`
- Change `Build directory: build`
<img src="https://user-images.githubusercontent.com/42481638/216899164-6cee8482-3d59-428f-b1bc-e6dc793c9b20.png" width="500">
- Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient.
- Once this process has been completed (No loading bar bottom right), you can now build eden
- In the top right, click on the drop-down menu, select all configurations, then select eden
<img src="https://user-images.githubusercontent.com/42481638/216899226-975048e9-bc6d-4ec1-bc2d-bd8a1e15ed04.png" height="500" >
- Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built.
<img src="https://user-images.githubusercontent.com/42481638/216899275-d514ec6a-e563-470e-81e2-3e04f0429b68.png" width="500">
</details>
## Troubleshooting

View File

@ -9,6 +9,7 @@ When reporting issues or finding bugs, we often need backtraces, debug logs, or
If your bug is related to a graphical issue--e.g. mismatched colors, vertex explosions, flickering, etc.--then you are required to include graphical debugging logs in your issue reports.
Graphics Debugging is found in General -> Debug on desktop, and Advanced Settings -> Debug on Android. Android users are all set; however, desktop users may need to install the Vulkan Validation Layers:
- Windows: Install the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home)
- Linux, BSD, etc: Install `vulkan-validation-layers`, `vulkan-layers`, or similar from your package manager. It should be located in e.g. `/usr/lib64/libVkLayer_khronos_validation.so`
@ -30,15 +31,17 @@ Ignoring SIGSEGV when debugging in host:
### gdb
You must have GDB installed for aarch64 to debug the target. Install it through your package manager, e.g.:
* On Arch:
* `sudo pacman -Syu aarch64-linux-gnu-gdb`
* On Gentoo:
* `sudo emerge --ask crossdev`
* `sudo crossdev -t aarch64-unknown-linux-gnu --ex-gdb`
- On Arch:
- `sudo pacman -Syu aarch64-linux-gnu-gdb`
- On Gentoo:
- `sudo emerge --ask crossdev`
- `sudo crossdev -t aarch64-unknown-linux-gnu --ex-gdb`
Run `./build/bin/eden-cli -c <path to your config file (see logs where you run eden normally to see where it is)> -d -g <path to game>`
Or `Enable GDB Stub` at General > Debug, then hook up an aarch64-gdb:
* `target remote localhost:6543`
- `target remote localhost:6543`
Type `c` (for continue) and then if it crashes just do a `bt` (backtrace) and `layout asm`
@ -69,26 +72,27 @@ For more information type `info gdb` and read [the man page](https://man7.org/li
## Simple checklist for debugging black screens using Renderdoc
Renderdoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it [here](https://renderdoc.org).
Renderdoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it at [renderdoc.org](https://renderdoc.org).
Before using renderdoc to diagnose issues, it is always good to make sure there are no validation errors. Any errors means the behavior of the application is undefined. That said, renderdoc can help debug validation errors if you do have them.
When debugging a black screen, there are many ways the application could have setup Vulkan wrong.
Here is a short checklist of items to look at to make sure are appropriate:
* Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
* Vertex buffers are bound
* vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
* Any bound push constants and descriptors have the right data - including:
* Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
* Pipeline state is correct
* viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
* Fill mode matches expected - usually solid
* Culling mode makes sense - commonly back or none
* The winding direction is correct - typically CCW (counter clockwise)
* Scissor region is correct - usually same as viewport's x,y,width, &height
* Blend state is correct
* Depth state is correct - typically enabled with Function set to Less than or Equal
* Swapchain images are bound when rendering to the swapchain
* Image being rendered to is the same as the one being presented when rendering to the swapchain
- Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
- Vertex buffers are bound
- vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
- Any bound push constants and descriptors have the right data - including:
- Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
- Pipeline state is correct
- viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
- Fill mode matches expected - usually solid
- Culling mode makes sense - commonly back or none
- The winding direction is correct - typically CCW (counter clockwise)
- Scissor region is correct - usually same as viewport's x,y,width, &height
- Blend state is correct
- Depth state is correct - typically enabled with Function set to Less than or Equal
- Swapchain images are bound when rendering to the swapchain
- Image being rendered to is the same as the one being presented when rendering to the swapchain
Alternatively, a [RenderDoc Extension](https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw) ([Archive](https://web.archive.org/web/20250000000000*/https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw)) exists which automates doing a lot of these manual steps.

View File

@ -4,19 +4,15 @@ To build Eden, you MUST have a C++ compiler.
* On Linux, this is usually [GCC](https://gcc.gnu.org/) 11+ or [Clang](https://clang.llvm.org/) v14+
* GCC 12 also requires Clang 14+
* On Windows, we support:
* **[MSVC](https://visualstudio.microsoft.com/downloads/)** (default)
* It's STRONGLY RECOMMENDED to use the **Community** option and **Visual Studio 2022**
* You need to install: **[Desktop development with C++](https://learn.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=msvc-170)**
* **[clang-cl](https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild?view=msvc-180)**
* You need to install: **C++ Clang tools for Windows**
* **[MSYS2](https://www.msys2.org)**
* On Windows, install **[MSYS2](https://www.msys2.org)**
* MINGW64 is preferred for x86_64/amd64 compilation, but this is subject to change.
* ARM should use CLANGARM64
* On macOS, this is Apple Clang
* This can be installed with `xcode-select --install`
The following additional tools are also required:
* **[CMake](https://www.cmake.org/)** 3.22+ - already included with the Android SDK
* **[CMake](https://www.cmake.org/)** 3.22+
* **[Git](https://git-scm.com/)** for version control
* **[Windows installer](https://gitforwindows.org)**
* **[Python3](https://www.python.org/downloads/)** 3.10+ - necessary to download external repositories
@ -29,13 +25,8 @@ If you are on desktop and plan to use the Qt frontend, you *must* install Qt 6,
* On Linux, *BSD and macOS, this can be done by the package manager
* If you wish to use Qt Creator, append `qtcreator` or `qt-creator` to the commands seen below.
* MSVC/clang-cl users on Windows must install through the official [Qt](https://www.qt.io/download-qt-installer-oss) installer
* Linux and macOS users may choose to use the installer as well.
* MSYS2 can also install Qt 6 via the package manager
* For help setting up Qt Creator, run `./install.sh -h qtcreator`
If you are on **Windows** and building with **MSVC** or **clang-cl**, you may go [back home](Build.md) and continue.
* MSYS2 must install Qt 6 via the package manager (`pacman`)
## Externals
@ -44,7 +35,7 @@ The following are handled by Eden's externals:
* [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`)
* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL2=ON` OR `-DYUZU_USE_BUNDLED_SDL2=ON` to reduce compile time)
All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only):
All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/). System dependencies can be used if available.
* [Boost](https://www.boost.org/users/download/) 1.57.0+
* [Catch2](https://github.com/catchorg/Catch2) 3.0.1 if `YUZU_TESTS` or `DYNARMIC_TESTS` are on
@ -56,27 +47,23 @@ All other dependencies will be downloaded and built by [CPM](https://github.com/
* [zstd](https://facebook.github.io/zstd/) 1.5+
* [enet](http://enet.bespin.org/) 1.3+
* [Opus](https://opus-codec.org/) 1.3+
Vulkan 1.3.274+ is also needed:
* [VulkanUtilityLibraries](https://github.com/KhronosGroup/Vulkan-Utility-Libraries)
* [VulkanHeaders](https://github.com/KhronosGroup/Vulkan-Headers)
* [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools)
* [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers)
Certain other dependencies will be fetched by CPM regardless. System packages *can* be used for these libraries, but many are either not packaged by most distributions OR have issues when used by the system:
* [SimpleIni](https://github.com/brofield/simpleini)
* [DiscordRPC](https://github.com/eden-emulator/discord-rpc)
* [cubeb](https://github.com/mozilla/cubeb)
* [libusb](https://github.com/libusb/libusb)
* [VulkanMemoryAllocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
* [sirit](https://github.com/eden-emulator/sirit)
* [httplib](https://github.com/yhirose/cpp-httplib) - if `ENABLE_UPDATE_CHECKER` or `ENABLE_WEB_SERVICE` are on
* This package is known to be broken on the AUR.
* [sirit](https://github.com/eden-emulator/sirit) 1.0.1+
* [httplib](https://github.com/yhirose/cpp-httplib) 0.19+
* [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on
* [unordered-dense](https://github.com/martinus/unordered_dense)
Vulkan 1.4.317+ is also needed:
* [VulkanUtilityLibraries](https://github.com/KhronosGroup/Vulkan-Utility-Libraries)
* [VulkanHeaders](https://github.com/KhronosGroup/Vulkan-Headers)
* [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools)
* [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers)
On amd64:
* [xbyak](https://github.com/herumi/xbyak) - 7.22 or earlier is recommended

View File

@ -7,7 +7,7 @@ To change these options, add `-DOPTION_NAME=NEWVALUE` to the command line.
Notes:
- Defaults are marked per-platform.
- "Non-UNIX" just means Windows/MSVC and Android (yes, macOS is UNIX
- "Non-UNIX" just means everything except Android (yes, macOS is UNIX)
- Android generally doesn't need to change anything; if you do, go to `src/android/app/build.gradle.kts`
- To set a boolean variable to on, use `ON` for the value; to turn it off, use `OFF`
- If a variable is mentioned as being e.g. "ON" for a specific platform(s), that means it is defaulted to OFF on others
@ -28,9 +28,9 @@ These options control dependencies.
- Currently, build fails without this
- `YUZU_TZDB_PATH` (string) Path to a pre-downloaded timezone database (useful for nixOS and Gentoo)
- `YUZU_USE_BUNDLED_MOLTENVK` (ON, macOS only) Download bundled MoltenVK lib
- `YUZU_USE_BUNDLED_OPENSSL` (ON for MSVC, Android, Solaris, and OpenBSD) Download bundled OpenSSL build
- `YUZU_USE_BUNDLED_OPENSSL` (ON for Android, Solaris, and OpenBSD) Download bundled OpenSSL build
- `YUZU_USE_EXTERNAL_SDL2` (OFF) Compiles SDL2 from source
- `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2
- `YUZU_USE_BUNDLED_SDL2` (OFF) Download a prebuilt SDL2
### Miscellaneous
@ -81,7 +81,7 @@ Also desktop-only, but apply strictly to Qt
- `ENABLE_QT` (ON) Enable the Qt frontend (recommended)
- `ENABLE_QT_TRANSLATION` (OFF) Enable translations for the Qt frontend
- `YUZU_USE_BUNDLED_QT` (ON for MSVC) Download bundled Qt binaries
- `YUZU_USE_BUNDLED_QT` (OFF) Download bundled Qt binaries
- Not recommended on Linux. For Windows and macOS, the provided build is statically linked.
- `YUZU_QT_MIRROR` (string) What mirror to use for downloading the bundled Qt libraries
- `YUZU_USE_QT_MULTIMEDIA` (OFF) Use QtMultimedia for camera support

View File

@ -1,57 +0,0 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
$ErrorActionPreference = "Stop"
# Check if running as administrator
try {
net session 1>$null 2>$null
} catch {
Write-Host "This script must be run with administrator privileges!"
Exit 1
}
$VulkanSDKVer = "1.4.341.1"
if ((Get-WmiObject -Class Win32_ComputerSystem).SystemType -match '(x64)' -eq "True") {
$VulkanSDKArch = "X64"
$VulkanSDKOs = "windows"
} else {
$VulkanSDKArch = "ARM64"
$VulkanSDKOs = "warm"
}
$VULKAN_SDK = "C:/VulkanSDK/$VulkanSDKVer"
$ExeFile = "vulkansdk-windows-$VulkanSDKArch-$VulkanSDKVer.exe"
$Uri = "https://sdk.lunarg.com/sdk/download/$VulkanSDKVer/$VulkanSDKOs/$ExeFile"
$Destination = "./$ExeFile"
# Check if Vulkan SDK is already installed
if (Test-Path $VULKAN_SDK) {
Write-Host "-- Vulkan SDK already installed at $VULKAN_SDK"
return
}
echo "Downloading Vulkan SDK $VulkanSDKVer from $Uri"
$WebClient = New-Object System.Net.WebClient
$WebClient.DownloadFile($Uri, $Destination)
echo "Finished downloading $ExeFile"
$Arguments = "--root `"$VULKAN_SDK`" --accept-licenses --default-answer --confirm-command install"
echo "Installing Vulkan SDK $VulkanSDKVer"
$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -Wait -ArgumentList $Arguments
$ExitCode = $InstallProcess.ExitCode
if ($ExitCode -ne 0) {
echo "Error installing Vulkan SDK $VulkanSDKVer (Error: $ExitCode)"
Exit $ExitCode
}
echo "Finished installing Vulkan SDK $VulkanSDKVer"
if ("$env:GITHUB_ACTIONS" -eq "true") {
echo "VULKAN_SDK=$VULKAN_SDK" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$VULKAN_SDK/Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
}

View File

@ -1,44 +0,0 @@
#!/usr/bin/sh
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
: "${VULKAN_SDK_VER:=1.4.341.1}"
: "${VULKAN_ROOT:=C:/VulkanSDK/$VULKAN_SDK_VER}"
VULKAN_SDK_ARCH=X64
VULKAN_SDK_OS=windows
case "$(uname)" in
*ARM64*)
VULKAN_SDK_ARCH=ARM64
VULKAN_SDK_OS=warm
;;
esac
EXE_FILE="vulkansdk-windows-$VULKAN_SDK_ARCH-$VULKAN_SDK_VER.exe"
URI="https://sdk.lunarg.com/sdk/download/$VULKAN_SDK_VER/$VULKAN_SDK_OS/$EXE_FILE"
VULKAN_ROOT_UNIX=$(cygpath -u "$VULKAN_ROOT")
# Check if Vulkan SDK is already installed
if [ -d "$VULKAN_ROOT_UNIX" ]; then
echo "-- Vulkan SDK already installed at $VULKAN_ROOT_UNIX"
exit 0
fi
echo "Downloading Vulkan SDK $VULKAN_SDK_VER from $URI"
[ ! -f "./$EXE_FILE" ] && curl -L -o "./$EXE_FILE" "$URI"
chmod +x "./$EXE_FILE"
echo "Finished downloading $EXE_FILE"
echo "Installing Vulkan SDK $VULKAN_SDK_VER..."
if net session > /dev/null 2>&1; then
./$EXE_FILE --root "$VULKAN_ROOT" --accept-licenses --default-answer --confirm-command install
else
echo "This script must be run with administrator privileges!"
exit 1
fi
echo "Finished installing Vulkan SDK $VULKAN_SDK_VER"
# GitHub Actions integration
if [ \"${GITHUB_ACTIONS:-false}\" = \"true\" ]; then
echo \"VULKAN_SDK=$VULKAN_ROOT\" >> \"$GITHUB_ENV\"
echo \"$VULKAN_ROOT/bin\" >> \"$GITHUB_PATH\"
fi

View File

@ -1,42 +0,0 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
$osArch = $env:PROCESSOR_ARCHITECTURE
switch ($osArch) {
"AMD64" { $arch = "x64" }
"ARM64" { $arch = "arm64" }
default {
Write-Error "load-msvc-env.ps1: Unsupported architecture: $osArch"
exit 1
}
}
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (!(Test-Path $vswhere)) {
Write-Error "load-msvc-env.ps1: vswhere not found"
exit 1
}
$vs = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
if (-not $vs) {
Write-Error "load-msvc-env.ps1: Visual Studio (with Desktop development with C++) not found"
exit 1
}
$bat = "$vs\VC\Auxiliary\Build\vcvarsall.bat"
if (!(Test-Path $bat)) {
Write-Error "load-msvc-env.ps1: (vcvarsall.bat) not found"
exit 1
}
cmd /c "`"$bat`" $arch && set" | ForEach-Object {
if ($_ -match "^(.*?)=(.*)$") {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
Write-Host "load-msvc-env.ps1: MSVC environment loaded for $arch ($vs)"

View File

@ -1,24 +0,0 @@
#!/usr/bin/bash
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
ARCH_RAW="$PROCESSOR_ARCHITECTURE"
case "$ARCH_RAW" in
AMD64) ARCH="x64" ;;
ARM64) ARCH="arm64" ;;
*) echo "load-msvc-env.sh: Unsupported architecture: $ARCH_RAW"; exit 1 ;;
esac
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VCVARS_BASH="$SCRIPT_DIR/vcvarsall.sh"
if [ ! -f "$VCVARS_BASH" ]; then
echo "load-msvc-env.sh: vcvarsall.sh not found in $SCRIPT_DIR"
#exit 1
fi
chmod +x "$VCVARS_BASH"
eval "$("$VCVARS_BASH" "$ARCH")"
echo "MSVC environment loaded for $ARCH with vcvars-bash script"

View File

@ -1,433 +0,0 @@
#!/usr/bin/env bash
#
# SPDX-FileCopyrightText: Copyright 2023 Nathan Poirier <nathan@poirier.io>
# SPDX-License-Identifier: MIT License
#
# Source: https://github.com/nathan818fr/vcvars-bash
#
set -Eeuo pipefail
shopt -s inherit_errexit
declare -r VERSION='2025-07-09.1'
function detect_platform() {
case "${OSTYPE:-}" in
cygwin* | msys* | win32)
declare -gr bash_platform='win_cyg'
;;
*)
if [[ -n "${WSL_DISTRO_NAME:-}" ]]; then
declare -gr bash_platform='win_wsl'
else
printf 'error: Unsupported platform (%s)\n' "${OSTYPE:-}" >&2
printf 'hint: This script only supports Bash on Windows (Git Bash, WSL, etc.)\n' >&2
return 1
fi
;;
esac
}
function detect_mode() {
# Detect the mode depending on the name called
if [[ "$(basename -- "$0")" == vcvarsrun* ]]; then
declare -gr script_mode='run' # vcvarsrun.sh
else
declare -gr script_mode='default' # vcvarsall.sh
fi
}
function print_usage() {
case "$script_mode" in
default)
cat <<EOF
Usage: eval "\$(vcvarsall.sh [vcvarsall.bat arguments])"
Script version: $VERSION
Load MSVC environment variables using vcvarsall.bat and export them.
The script writes a list of export commands to stdout, to be evaluated by a
POSIX-compliant shell.
Example: eval "\$(vcvarsall.sh x86)"
EOF
;;
run)
cat <<EOF
Usage: vcvarsrun.sh [vcvarsall.bat arguments] -- command [arguments...]
Script version: $VERSION
Load MSVC environment variables using vcvarsall.bat and execute a command with
them.
Example: vcvarsrun.sh x64 -- cl /nologo /EHsc /Fe:hello.exe hello.cpp
EOF
;;
esac
cat <<EOF
Environment variables:
VSINSTALLDIR
The path to the Visual Studio installation directory.
Example: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community"
Default: The latest Visual Studio installation directory found by
vswhere.exe
VSWHEREPATH
The path to the vswhere.exe executable.
Example: "C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe"
Default: Automatically detected (in the PATH or well-known locations)
VSWHEREARGS
The arguments to pass to vswhere.exe.
This value is always automatically prefixed with "-latest -property installationPath".
Default: "-products *"
EOF
local vcvarsall
vcvarsall=$(find_vcvarsall)
printf '\nvcvarsall.bat arguments: %s\n' "$({ cmd "$(cmdesc "$vcvarsall")" -help </dev/null 2>/dev/null || true; } | fix_crlf | sed '/^Syntax:/d; s/^ vcvarsall.bat //')"
}
function main() {
detect_platform
detect_mode
# Parse arguments
if [[ $# -eq 0 ]]; then
print_usage >&2
return 1
fi
local arg vcvarsall_args=()
for arg in "$@"; do
shift
if [[ "$arg" == '--' ]]; then
if [[ "$script_mode" == 'default' ]]; then
printf 'error: Unexpected argument: --\n' >&2
printf 'hint: Use vcvarsrun to run a command\n' >&2
return 1
fi
break
fi
vcvarsall_args+=("$(cmdesc "$arg")")
done
if [[ "$script_mode" == 'run' && $# -eq 0 ]]; then
printf 'error: No command specified\n' >&2
return 1
fi
# Get MSVC environment variables from vcvarsall.bat
local vcvarsall vcvarsall_env
vcvarsall=$(find_vcvarsall)
vcvarsall_env=$({ cmd "$(cmdesc "$vcvarsall")" "${vcvarsall_args[@]}" '&&' 'set' </dev/null || true; } | fix_crlf)
# Filter MSVC environment variables and export them.
# The list of variables to export was based on a comparison between a clean environment and the vcvarsall.bat
# environment (on different MSVC versions, tools and architectures).
#
# Windows environment variables are case-insensitive while Unix-like environment variables are case-sensitive, so:
# - we always use uppercase names to prevent duplicates environment variables on the Unix-like side
# - we also ensure that only the first occurrence of a variable is exported (see below)
#
# While Windows environment variables are case-insensitive, it is possible to have duplicates in some edge cases.
# e.g. using Git Bash:
# export xxx=1; export XXX=2; export xXx=3; cmd.exe //c set XxX=4 '&&' set
# will output:
# XXX=4
# xXx=3
# xxx=1
declare -A seen_vars
function export_env() {
local name=${1^^}
local value=$2
if [[ ! "$name" =~ ^[A-Z0-9_]+$ ]]; then return; fi
if [[ -n "${seen_vars[$name]:-}" ]]; then return; fi
seen_vars[$name]=1
if [[ "$script_mode" == 'run' ]]; then
export "${name}=${value}"
else
printf "export %s='%s'\n" "$name" "${value//\'/\'\\\'\'}"
fi
}
local name value initialized=false
while IFS='=' read -r name value; do
if [[ "$initialized" == 'false' ]]; then
if [[ -n "$value" ]]; then name+="=$value"; fi
if [[ "$name" == *' Environment initialized for: '* ]]; then initialized=true; fi
printf '%s\n' "$name" >&2
continue
fi
case "${name^^}" in
LIB | LIBPATH | INCLUDE | EXTERNAL_INCLUDE | COMMANDPROMPTTYPE | DEVENVDIR | EXTENSIONSDKDIR | FRAMEWORK* | \
PLATFORM | PREFERREDTOOLARCHITECTURE | UCRT* | UNIVERSALCRTSDK* | VCIDE* | VCINSTALL* | VCPKG* | VCTOOLS* | \
VSCMD* | VSINSTALL* | VS[0-9]* | VISUALSTUDIO* | WINDOWSLIB* | WINDOWSSDK*)
export_env "$name" "$value"
;;
PATH)
# PATH is a special case, requiring special handling
local new_paths
new_paths=$(pathlist_win_to_unix "$value") # Convert to unix-style path list
new_paths=$(pathlist_normalize "${PATH}:${new_paths}") # Prepend the current PATH
export_env 'WINDOWS_PATH' "$value"
export_env 'PATH' "$new_paths"
;;
esac
done <<<"$vcvarsall_env"
if [[ "$initialized" == 'false' ]]; then
printf 'error: vcvarsall.bat failed' >&2
return 1
fi
# Execute command if needed
if [[ "$script_mode" == 'run' ]]; then
exec "$@"
fi
}
# Locate vcvarsall.bat
# Inputs:
# VSINSTALLDIR: The path to the Visual Studio installation directory (optional)
# VSWHEREPATH: The path to the vswhere.exe executable (optional)
# VSWHEREARGS: The arguments to pass to vswhere.exe (optional)
# Outputs:
# stdout: The windows-style path to vcvarsall.bat
function find_vcvarsall() {
local vsinstalldir
if [[ -n "${VSINSTALLDIR:-}" ]]; then
vsinstalldir="$VSINSTALLDIR"
else
local vswhere
if [[ -n "${VSWHEREPATH:-}" ]]; then
vswhere=$(unixpath "$VSWHEREPATH")
else
vswhere=$(command -v 'vswhere' 2>/dev/null || unixpath 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe')
fi
local vswhereargs=(-latest -property installationPath)
if [[ -n "${VSWHEREARGS:-}" ]]; then
parse_args_simple "$VSWHEREARGS"
vswhereargs+=("${result[@]}")
else
vswhereargs+=(-products '*')
fi
if [[ "${VCVARSBASH_DEBUG:-}" == 1 ]]; then
printf 'debug: vswhere path: %s\n' "$vswhere" >&2
printf 'debug: vswhere args:\n' >&2
printf 'debug: [ %s ]\n' "${vswhereargs[@]}" >&2
fi
vsinstalldir=$("$vswhere" "${vswhereargs[@]}" </dev/null | fix_crlf)
if [[ -z "$vsinstalldir" ]]; then
printf 'error: vswhere returned an empty installation path\n' >&2
return 1
fi
fi
printf '%s\n' "$(winpath "$vsinstalldir")\\VC\\Auxiliary\\Build\\vcvarsall.bat"
}
# Split command arguments into an array, with a simple logic
# - Arguments are separated by whitespace (space, tab, newline, carriage return)
# - To include whitespace in an argument, it must be enclosed in double quotes (")
# - When inside a double-quoted argument, quotes can be escaped by doubling them ("")
# Inputs:
# $1: The string to parse
# Outputs:
# result: An array of parsed arguments
function parse_args_simple() {
declare -g result=()
local str="$1 " # add a trailing space to simplify the last argument handling
local args=()
local current_type=none # none = waiting for next arg, normal = inside normal arg, quoted = inside quoted arg
local current_value=''
local i=0 len=${#str}
while ((i < len)); do
local c=${str:i:1}
case "$current_type" in
none)
case "$c" in
' ' | $'\t' | $'\n' | $'\r')
# Ignore whitespace
;;
'"')
# Start a quoted argument
current_type=quoted
current_value=''
;;
*)
# Start a normal argument
current_type=normal
current_value="$c"
;;
esac
;;
normal)
case "$c" in
' ' | $'\t' | $'\n' | $'\r')
# End of normal argument, add it to the list
args+=("$current_value")
current_type=none
current_value=''
;;
*)
# Continue building the normal argument
current_value+="$c"
;;
esac
;;
quoted)
case "$c" in
'"')
if [[ "${str:i+1:1}" != '"' ]]; then
# End of quoted argument, add it to the list
args+=("$current_value")
current_type=none
current_value=''
else
# Escaped quote, add a single quote to the current value
current_value+='"'
((++i)) # Skip the next quote
fi
;;
*)
# Continue building the quoted argument
current_value+="$c"
;;
esac
;;
esac
((++i))
done
if [[ "$current_type" != none ]]; then
printf 'error: Unfinished %s argument: %s\n' "$current_type" "$current_value" >&2
return 1
fi
declare -g result=("${args[@]}")
}
# Run a command with cmd.exe
# Inputs:
# $@: The command string to run (use cmdesc to escape arguments when needed)
# Outputs:
# stdout: The cmd.exe standard output
# stderr: The cmd.exe error output
function cmd() {
# This seems to work fine on all supported platforms
# (even with all the weird path and argument conversions on MSYS-like)
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' cmd.exe /s /c " ; $* "
}
# Escape a cmd.exe command argument
# Inputs:
# $1: The argument to escape
# Outputs:
# stdout: The escaped argument
function cmdesc() {
# shellcheck disable=SC2001
sed 's/[^0-9A-Za-z]/^\0/g' <<<"$1"
}
# Convert path to an absolute unix-style path
# Inputs:
# $1: The path to convert
# Outputs:
# stdout: The converted path
function unixpath() {
local path=$1
case "$bash_platform" in
win_wsl)
case "$path" in
[a-zA-Z]:\\* | [a-zA-Z]:/* | \\\\* | //*)
# Convert windows path using wslpath (unix mode, absolute path)
wslpath -u -a -- "$path"
;;
*)
# Convert unix path using realpath
realpath -m -- "$path"
;;
esac
;;
*)
cygpath -u -a -- "$path"
;;
esac
}
# Convert path to an absolute windows-style path
# Inputs:
# $1: The path to convert
# Outputs:
# stdout: The converted path
function winpath() {
local path=$1
case "$bash_platform" in
win_wsl)
case "$path" in
[a-zA-Z]:\\* | [a-zA-Z]:/* | \\\\* | //*)
# Already a windows path
printf '%s' "$path"
;;
*)
# Convert using wslpath (windows mode, absolute path)
wslpath -w -a -- "$path"
;;
esac
;;
*)
# Convert using cygpath (windows mode, absolute path, long form)
cygpath -w -a -l -- "$path"
;;
esac
}
# Convert a windows-style path list to a unix-style path list
# Inputs:
# $1: The windows-style path list to convert
# Outputs:
# stdout: The converted unix-style path list
function pathlist_win_to_unix() {
local win_paths=$1
local path_dir first=true
while IFS= read -r -d';' path_dir; do
if [[ -z "$path_dir" ]]; then continue; fi
if [[ "$first" == 'true' ]]; then first=false; else printf ':'; fi
printf '%s' "$(unixpath "$path_dir")"
done <<<"${win_paths};"
}
# Normalize a unix-style path list, removing duplicates and empty entries
# Inputs:
# $1: The list to normalize
# Outputs:
# stdout: The normalized path list
function pathlist_normalize() {
local unix_paths=$1
declare -A seen_paths
local path_dir first=true
while IFS= read -r -d ':' path_dir; do
if [[ -z "$path_dir" ]]; then continue; fi
if [[ -n "${seen_paths[$path_dir]:-}" ]]; then continue; fi
seen_paths[$path_dir]=1
if [[ "$first" == 'true' ]]; then first=false; else printf ':'; fi
printf '%s' "$path_dir"
done <<<"${unix_paths}:"
}
# Convert CRLF to LF
# Inputs:
# stdin: The input to convert
# Outputs:
# stdout: The converted input
function fix_crlf() {
sed 's/\r$//'
}
eval 'main "$@";exit "$?"'