Files
codex/.github/actions/setup-msvc-env/action.yml
2026-05-13 17:06:07 -07:00

168 lines
5.5 KiB
YAML

name: setup-msvc-env
description: Expose an MSVC developer environment for the requested Windows target.
inputs:
target:
description: Rust target triple that will be built on this Windows runner.
required: true
host-arch:
description: Optional Visual Studio host architecture override.
required: false
default: ""
runs:
using: composite
steps:
- name: Expose MSVC SDK environment
shell: pwsh
run: |
switch ("${{ inputs.target }}") {
"x86_64-pc-windows-msvc" {
$targetArch = "x64"
$requiredComponent = "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"
}
"aarch64-pc-windows-msvc" {
$targetArch = "arm64"
$requiredComponent = "Microsoft.VisualStudio.Component.VC.Tools.ARM64"
}
default {
throw "Unsupported Windows MSVC target: ${{ inputs.target }}"
}
}
$hostArch = "${{ inputs.host-arch }}"
if (-not $hostArch) {
$hostArch = if ($env:PROCESSOR_ARCHITEW6432 -eq "ARM64" -or $env:PROCESSOR_ARCHITECTURE -eq "ARM64") {
"arm64"
} else {
"x64"
}
}
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (-not (Test-Path $vswhere)) {
throw "vswhere.exe not found"
}
$installPath = & $vswhere -latest -products * -requires $requiredComponent -property installationPath 2>$null
if (-not $installPath) {
throw "Could not locate a Visual Studio installation with component $requiredComponent"
}
$vsDevCmd = Join-Path $installPath "Common7\Tools\VsDevCmd.bat"
if (-not (Test-Path $vsDevCmd)) {
throw "VsDevCmd.bat not found at $vsDevCmd"
}
$varsToExport = @(
"INCLUDE",
"LIB",
"LIBPATH",
"PATH",
"UCRTVersion",
"UniversalCRTSdkDir",
"VCINSTALLDIR",
"VCToolsInstallDir",
"WindowsLibPath",
"WindowsSdkBinPath",
"WindowsSdkDir",
"WindowsSDKLibVersion",
"WindowsSDKVersion"
)
$envLines = & cmd.exe /c ('"{0}" -no_logo -arch={1} -host_arch={2} >nul && set' -f $vsDevCmd, $targetArch, $hostArch)
$vcToolsInstallDir = $null
foreach ($line in $envLines) {
if ($line -notmatch "^(.*?)=(.*)$") {
continue
}
$name = $matches[1]
$value = $matches[2]
if ($varsToExport -contains $name) {
if ($name -ieq "Path") {
$name = "PATH"
}
if ($name -eq "VCToolsInstallDir") {
$vcToolsInstallDir = $value
}
"$name=$value" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
}
}
if (-not $vcToolsInstallDir) {
throw "VCToolsInstallDir was not exported by VsDevCmd.bat"
}
$linker = $null
$rustc = Get-Command rustc -ErrorAction SilentlyContinue
if ($rustc) {
$sysroot = (& rustc --print sysroot 2>$null).Trim()
if ($sysroot) {
$rustLld = Join-Path $sysroot "lib\rustlib\x86_64-pc-windows-msvc\bin\rust-lld.exe"
if (Test-Path $rustLld) {
$linker = $rustLld
}
}
}
if (-not $linker) {
$linker = Join-Path $installPath "VC\Tools\Llvm\x64\bin\lld-link.exe"
}
if (-not (Test-Path $linker)) {
$linker = Join-Path $vcToolsInstallDir "bin\Host${hostArch}\${targetArch}\link.exe"
}
if (-not (Test-Path $linker)) {
throw "Windows linker not found at $linker"
}
if ((Split-Path -Leaf $linker) -match "lld") {
$wrapperDir = Join-Path $env:RUNNER_TEMP "arm64-archive-lld-wrapper"
New-Item -Path $wrapperDir -ItemType Directory -Force | Out-Null
$wrapperPath = Join-Path $wrapperDir "lld-link-wrapper.exe"
$wrapperSource = @'
using System;
using System.Diagnostics;
internal static class Program
{
private static int Main(string[] args)
{
var linker = Environment.GetEnvironmentVariable("ARM64_ARCHIVE_REAL_LINKER");
if (string.IsNullOrEmpty(linker))
{
Console.Error.WriteLine("ARM64_ARCHIVE_REAL_LINKER is not set");
return 1;
}
var startInfo = new ProcessStartInfo(linker)
{
UseShellExecute = false,
};
foreach (var arg in args)
{
if (!string.Equals(arg, "/arm64hazardfree", StringComparison.OrdinalIgnoreCase))
{
startInfo.ArgumentList.Add(arg);
}
}
using var process = Process.Start(startInfo);
if (process is null)
{
Console.Error.WriteLine($"Failed to start linker: {linker}");
return 1;
}
process.WaitForExit();
return process.ExitCode;
}
}
'@
Add-Type -TypeDefinition $wrapperSource -Language CSharp -OutputAssembly $wrapperPath -OutputType ConsoleApplication
"ARM64_ARCHIVE_REAL_LINKER=$linker" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
$linker = $wrapperPath
}
Write-Output "Using Windows linker: $linker"
$cargoTarget = "${{ inputs.target }}".ToUpperInvariant().Replace("-", "_")
"CARGO_TARGET_${cargoTarget}_LINKER=$linker" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append