Skip to content

Commit 20cd800

Browse files
fylornclaude
andauthored
Link the VC runtime statically into twcore.exe (#277)
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 <noreply@anthropic.com>
1 parent 550e6fd commit 20cd800

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

‎.cargo/config.toml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Windows 上把 VC 运行库静态链接进 twcore.exe。
2+
#
3+
# **不加这一条,twcore.exe 依赖 VCRUNTIME140.dll**,而这个文件不随 Windows
4+
# 自带:它来自「Visual C++ 可再发行组件包」,一般是别的软件顺手装上的。桌面版
5+
# 的安装程序只放 twcore.exe、不装运行库,于是在一台没装过它的机器上,网关
6+
# 根本起不来 —— CI 和多数真机上都装着它,所以看不出来。UCRT 是 Windows 10
7+
# 起系统自带的,静态链接只是顺带把它也带上。
8+
#
9+
# 写在这里而不是 release.yml 里:本机在 Windows 上编出来的和发出去的是同一种。
10+
# **`RUSTFLAGS` 环境变量会整个盖掉这里**(ci.yml 设了 `-D warnings`,所以 CI
11+
# 的测试仍是动态链接的),发版流水线不设它;release.yml 里有一步查 twcore.exe
12+
# 的导入表,这一条哪天没生效会在那里失败。
13+
[target.'cfg(all(windows, target_env = "msvc"))']
14+
rustflags = ["-C", "target-feature=+crt-static"]

‎.github/workflows/release.yml‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,31 @@ jobs:
185185
}
186186
& $exe --help | Out-Null
187187
188+
# **不要用户另装 VC 运行库。**VC 运行库由 `.cargo/config.toml` 静态链接进来;
189+
# 这里查两个 exe 的导入表,里面不许有 Windows 不自带的那几个 DLL。这台
190+
# runner 上装着运行库,exe 照样跑得起来 —— 上一步看不出这件事,只有导入表看得出。
191+
# 用的是链接它的那套 MSVC 里的 dumpbin,arm64 的 exe 一样读得了
192+
- name: No Visual C++ runtime to install
193+
shell: pwsh
194+
run: |
195+
$ErrorActionPreference = "Stop"
196+
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
197+
$dumpbin = & $vswhere -latest -products * -find "VC\Tools\MSVC\**\bin\Hostx64\x64\dumpbin.exe" |
198+
Select-Object -First 1
199+
if (-not $dumpbin) { throw "dumpbin.exe not found" }
200+
foreach ($t in @("x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc")) {
201+
$exe = "target\$t\release\twcore.exe"
202+
$deps = & $dumpbin /nologo /dependents $exe |
203+
ForEach-Object { $_.Trim() } |
204+
Where-Object { $_ -match '\.dll$' }
205+
if ($LASTEXITCODE -ne 0 -or -not $deps) { throw "could not read the imports of $exe" }
206+
Write-Host "${exe}: $($deps -join ', ')"
207+
$redist = @($deps | Where-Object { $_ -match '^(vcruntime|msvcp|concrt|vccorlib|vcomp)\d' })
208+
if ($redist.Count -gt 0) {
209+
throw "$exe needs the Visual C++ runtime ($($redist -join ', ')) -- the static CRT in .cargo/config.toml did not apply"
210+
}
211+
}
212+
188213
- name: Package
189214
shell: pwsh
190215
run: |

0 commit comments

Comments
 (0)