From 2f09270a6c496b8a91b8fbd2568b650bceb9204c Mon Sep 17 00:00:00 2001 From: fylorn <249551762+fylorn@users.noreply.github.com> Date: Sat, 3 Oct 2026 15:57:51 +0800 Subject: [PATCH] Link the VC runtime statically into twcore.exe twcore.exe imported VCRUNTIME140.dll, which Windows does not ship: it comes with the Visual C++ Redistributable, usually installed by some other program. The desktop installer only carries twcore.exe, so on a machine without the redistributable the gateway cannot start. CI runners and most real machines have it installed, which is why nothing showed. - .cargo/config.toml: +crt-static for windows-msvc targets, so a local Windows build matches what is released. RUSTFLAGS overrides it, so the CI test builds stay dynamic; the release workflow does not set it. - release.yml: a step reads both exes' imports with dumpbin and fails if any Visual C++ runtime DLL is still there. Co-Authored-By: Claude Opus 5.5 --- .cargo/config.toml | 14 ++++++++++++++ .github/workflows/release.yml | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..bd87530 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,14 @@ +# Windows 上把 VC 运行库静态链接进 twcore.exe。 +# +# **不加这一条,twcore.exe 依赖 VCRUNTIME140.dll**,而这个文件不随 Windows +# 自带:它来自「Visual C++ 可再发行组件包」,一般是别的软件顺手装上的。桌面版 +# 的安装程序只放 twcore.exe、不装运行库,于是在一台没装过它的机器上,网关 +# 根本起不来 —— CI 和多数真机上都装着它,所以看不出来。UCRT 是 Windows 10 +# 起系统自带的,静态链接只是顺带把它也带上。 +# +# 写在这里而不是 release.yml 里:本机在 Windows 上编出来的和发出去的是同一种。 +# **`RUSTFLAGS` 环境变量会整个盖掉这里**(ci.yml 设了 `-D warnings`,所以 CI +# 的测试仍是动态链接的),发版流水线不设它;release.yml 里有一步查 twcore.exe +# 的导入表,这一条哪天没生效会在那里失败。 +[target.'cfg(all(windows, target_env = "msvc"))'] +rustflags = ["-C", "target-feature=+crt-static"] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3f51e23..de984c0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -185,6 +185,31 @@ jobs: } & $exe --help | Out-Null + # **不要用户另装 VC 运行库。**VC 运行库由 `.cargo/config.toml` 静态链接进来; + # 这里查两个 exe 的导入表,里面不许有 Windows 不自带的那几个 DLL。这台 + # runner 上装着运行库,exe 照样跑得起来 —— 上一步看不出这件事,只有导入表看得出。 + # 用的是链接它的那套 MSVC 里的 dumpbin,arm64 的 exe 一样读得了 + - name: No Visual C++ runtime to install + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $dumpbin = & $vswhere -latest -products * -find "VC\Tools\MSVC\**\bin\Hostx64\x64\dumpbin.exe" | + Select-Object -First 1 + if (-not $dumpbin) { throw "dumpbin.exe not found" } + foreach ($t in @("x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc")) { + $exe = "target\$t\release\twcore.exe" + $deps = & $dumpbin /nologo /dependents $exe | + ForEach-Object { $_.Trim() } | + Where-Object { $_ -match '\.dll$' } + if ($LASTEXITCODE -ne 0 -or -not $deps) { throw "could not read the imports of $exe" } + Write-Host "${exe}: $($deps -join ', ')" + $redist = @($deps | Where-Object { $_ -match '^(vcruntime|msvcp|concrt|vccorlib|vcomp)\d' }) + if ($redist.Count -gt 0) { + throw "$exe needs the Visual C++ runtime ($($redist -join ', ')) -- the static CRT in .cargo/config.toml did not apply" + } + } + - name: Package shell: pwsh run: |