EDIT: Version 2 has been released. Now 50% less hacky.
When you build a Windows application using the MSVC toolchain, by default it will produce a .exe
that dynamically links to vcruntime140.dll
. This dll will then need to be deployed when distributing the application. The static_vcruntime
crate makes it so when you build your application in release mode, the vcruntime is statically linked instead.
Usage
Add it as a build dependency:
[build-dependencies]
static_vcruntime = "2.0"
Then put this in your build.rs
:
fn main() {
static_vcruntime::metabuild();
}
That is all. Then when you build in release mode the vcruntime library will be statically linked instead of dynamically:
cargo build --release
FAQ
How is this different to +crt-static
?
Using +crt-static
does statically link the vcruntime but it also statically links the universal C runtime (ucrt). This is entirely unnecessary because the ucrt is included with Windows already.
Can I do this manually instead?
You can! But it requires making a special configuration file. To do so create a folder in your project called .cargo
. In that folder make a file called config.toml
. So the directory structure is like this:
.cargo
| config.toml
Then copy this into config.toml
:
# Statically link the vcruntime.
# This should go in `.cargo/config.toml`. It will not work in `cargo.toml`.
[target.'cfg(all(windows, target_env = "msvc"))']
rustflags = [
"-C", "target-feature=+crt-static"
"-C", "link-args=/DEFAULTLIB:ucrt.lib /DEFAULTLIB:libvcruntime.lib libcmt.lib",
"-C", "link-args=/NODEFAULTLIB:libvcruntimed.lib /NODEFAULTLIB:vcruntime.lib /NODEFAULTLIB:vcruntimed.lib"
"-C", "link-args=/NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcrtd.lib"
"-C", "link-args=/NODEFAULTLIB:libucrt.lib /NODEFAULTLIB:libucrtd.lib /NODEFAULTLIB:ucrtd.lib"
]
One issue with doing it manually is there's no way I know of to only apply it to release versions other than to abuse the way cargo looks for configuration files.
Alternatives
Instead of statically linking you can deploy the vcruntime in one of two ways. In either case, from the start menu open "Developer Powershell". Then type:
cd $env:VCToolsRedistDir
This will put you in the directory with redistributable files. You can then either redistribute the installers found there (typically either vcredist_x64.exe
or vcredist_x86.exe
) or you can only distribute the dll itself. The dll is found in the following sub-directories:
x64\Microsoft.VC142.CRT\vcruntime140.dll
Or:
x86\Microsoft.VC142.CRT\vcruntime140.dll