@smbcloud / cli / commits / fccb7ea

Link the C runtime statically on Windows

smb.exe imported VCRUNTIME140.dll, so a machine without the Visual C++ Redistributable failed at load with 0xC0000135 (this is what the winget validation hit on 0.7.2). Build with +crt-static on windows-msvc and have the release workflow fail if dumpbin still lists a VC++ runtime DLL. Also add PrivacyUrl to the winget locale template. ci.yml has no Windows job, so the check runs only in release-github.yml. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Seto Elkahfi committed Oct 19, 2026 at 23:34 UTC fccb7ea0484246043f93190f945338c0b6e815d0
5 files changed +50
.cargo/config.toml new
+7
@@ -0,0 +1,7 @@
1 +# Link the MSVC C runtime statically on Windows. Without this the binary
2 +# imports VCRUNTIME140.dll and the UCRT api-ms-win-crt-*.dll set, and on a
3 +# machine without the Visual C++ Redistributable it dies at load time with
4 +# STATUS_DLL_NOT_FOUND (0xC0000135) before main runs. winget ships smb as a
5 +# portable exe, so there is no installer to bring the runtime along.
6 +[target.'cfg(all(windows, target_env = "msvc"))']
7 +rustflags = ["-C", "target-feature=+crt-static"]
.github/workflows/release-github.yml
+5
@@ -88,6 +88,11 @@ jobs:
88 shell: bash
89 run: cargo build --locked --release --target ${{ matrix.target }} --package smbcloud-cli
90
91 + - name: Check Windows binary has no VC++ runtime dependency
92 + if: contains(matrix.target, 'windows')
93 + shell: pwsh
94 + run: ./packaging/windows/check-static-crt.ps1 -Path target/${{ matrix.target }}/release/${{ env.PROJECT_NAME }}.exe
95 +
96 - name: Package binary
97 shell: bash
98 run: |
packaging/windows/check-static-crt.ps1 new
+35
@@ -0,0 +1,35 @@
1 +# Fails if a Windows binary depends on the Visual C++ runtime DLLs.
2 +#
3 +# smb is linked with +crt-static (see .cargo/config.toml) so it runs on a
4 +# clean Windows install. If RUSTFLAGS overrides that, or a native dependency
5 +# drags in the DLL runtime, the exe still builds and passes tests on a runner
6 +# that has the redistributable installed, then fails to load on users'
7 +# machines. This check catches it before release.
8 +param(
9 + [Parameter(Mandatory = $true)]
10 + [string]$Path
11 +)
12 +
13 +$ErrorActionPreference = 'Stop'
14 +
15 +$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
16 +$dumpbin = & $vswhere -latest -products * -find 'VC\Tools\MSVC\*\bin\Hostx64\x64\dumpbin.exe' |
17 + Select-Object -First 1
18 +if (-not $dumpbin) {
19 + throw 'dumpbin.exe not found; is the MSVC toolset installed?'
20 +}
21 +
22 +$output = & $dumpbin /nologo /dependents $Path
23 +if ($LASTEXITCODE -ne 0) {
24 + throw "dumpbin failed on $Path"
25 +}
26 +$output | Write-Host
27 +
28 +$runtime = $output |
29 + Where-Object { $_ -match '^\s+(vcruntime|msvcp|concrt|ucrtbase|api-ms-win-crt-)\S*\.dll\s*$' } |
30 + ForEach-Object { $_.Trim() }
31 +if ($runtime) {
32 + Write-Host "::error::$Path depends on the Visual C++ runtime: $($runtime -join ', ')"
33 + exit 1
34 +}
35 +Write-Host "$Path does not depend on the Visual C++ runtime."
packaging/winget/smbCloudXYZ.smbcloud-cli.installer.yaml.in
+2
@@ -2,6 +2,8 @@
2 PackageIdentifier: smbCloudXYZ.smbcloud-cli
3 PackageVersion: @VERSION@
4 InstallerType: portable
5 +# No VCRedist dependency: the exe links the C runtime statically
6 +# (.cargo/config.toml), and CI rejects a build that imports it.
7 # `Commands` is what winget names the shim it drops on PATH. The release
8 # assets are smb-win-<arch>.exe, but the command has to be `smb`.
9 Commands:
packaging/winget/smbCloudXYZ.smbcloud-cli.locale.en-US.yaml.in
+1
@@ -7,6 +7,7 @@ PublisherUrl: https://smbcloud.xyz/
7 PublisherSupportUrl: https://github.com/@REPO@/issues
8 PackageName: smbCloud CLI
9 PackageUrl: https://smbcloud.xyz/
10 +PrivacyUrl: https://smbcloud.xyz/privacy-policy
11 License: Apache-2.0
12 LicenseUrl: https://github.com/@REPO@/blob/main/LICENSE
13 ShortDescription: smbCloud command line interface.