mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-06-06 07:45:56 +08:00
[*] 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:
parent
86eae5cc41
commit
18c11b88a0
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
43
docs/Deps.md
43
docs/Deps.md
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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)"
|
||||
@ -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"
|
||||
@ -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 "$?"'
|
||||
Loading…
Reference in New Issue
Block a user