Skip to content

Commit

Permalink
refactor(core): statically link vcruntime, closes #4122 (#4227)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed May 27, 2022
1 parent 62ce02f commit bb06150
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 49 deletions.
8 changes: 8 additions & 0 deletions .changes/static-vcruntime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"tauri-build": patch
"tauri-bundler": patch
"cli.rs": patch
"cli.js": patch
---

Statically link the Visual C++ runtime instead of using a merge module on the installer.
5 changes: 5 additions & 0 deletions core/tauri-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use std::path::{Path, PathBuf};

#[cfg(feature = "codegen")]
mod codegen;
#[cfg(windows)]
mod static_vcruntime;

#[cfg(feature = "codegen")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "codegen")))]
Expand Down Expand Up @@ -184,6 +186,9 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
)?)?
};

#[cfg(windows)]
static_vcruntime::build();

cfg_alias("dev", !has_feature("custom-protocol"));

let mut manifest = Manifest::from_path("Cargo.toml")?;
Expand Down
63 changes: 63 additions & 0 deletions core/tauri-build/src/static_vcruntime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

// taken from https://github.com/ChrisDenton/static_vcruntime/
// we're not using static_vcruntime directly because we want this for debug builds too

use std::{env, fs, io::Write, path::Path};

pub fn build() {
// Early exit if not msvc or release
if env::var("CARGO_CFG_TARGET_ENV").as_deref() != Ok("msvc") {
return;
}

override_msvcrt_lib();

// Disable conflicting libraries that aren't hard coded by Rust.
println!("cargo:rustc-link-arg=/NODEFAULTLIB:libvcruntimed.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:vcruntime.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:vcruntimed.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:libcmtd.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:msvcrt.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:msvcrtd.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:libucrt.lib");
println!("cargo:rustc-link-arg=/NODEFAULTLIB:libucrtd.lib");
// Set the libraries we want.
println!("cargo:rustc-link-arg=/DEFAULTLIB:libcmt.lib");
println!("cargo:rustc-link-arg=/DEFAULTLIB:libvcruntime.lib");
println!("cargo:rustc-link-arg=/DEFAULTLIB:ucrt.lib");
}

/// Override the hard-coded msvcrt.lib by replacing it with a (mostly) empty object file.
fn override_msvcrt_lib() {
// Get the right machine type for the empty library.
let arch = std::env::var("CARGO_CFG_TARGET_ARCH");
let machine: &[u8] = if arch.as_deref() == Ok("x86_64") {
&[0x64, 0x86]
} else if arch.as_deref() == Ok("x86") {
&[0x4C, 0x01]
} else {
return;
};
let bytes: &[u8] = &[
1, 0, 94, 3, 96, 98, 60, 0, 0, 0, 1, 0, 0, 0, 0, 0, 132, 1, 46, 100, 114, 101, 99, 116, 118,
101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10, 16, 0, 46, 100, 114, 101, 99, 116, 118, 101, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 4, 0, 0, 0,
];

// Write the empty "msvcrt.lib" to the output directory.
let out_dir = env::var("OUT_DIR").unwrap();
let path = Path::new(&out_dir).join("msvcrt.lib");
let f = fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(&path);
if let Ok(mut f) = f {
f.write_all(machine).unwrap();
f.write_all(bytes).unwrap();
}
// Add the output directory to the native library path.
println!("cargo:rustc-link-search=native={}", out_dir);
}
4 changes: 1 addition & 3 deletions core/tests/app-updater/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

fn main() {
tauri_build::build()
}
fn main() {}
3 changes: 1 addition & 2 deletions core/tests/app-updater/tests/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ fn get_cli_bin_path(cli_dir: &Path, debug: bool) -> Option<PathBuf> {
fn build_app(cli_bin_path: &Path, cwd: &Path, config: &Config, bundle_updater: bool) {
let mut command = Command::new(&cli_bin_path);
command
.arg("build")
.arg("--debug")
.args(["build", "--debug", "--verbose"])
.arg("--config")
.arg(serde_json::to_string(config).unwrap())
.current_dir(&cwd);
Expand Down
32 changes: 28 additions & 4 deletions examples/updater/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions tooling/bundler/src/bundle/windows/templates/main.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
SummaryCodepage="!(loc.TauriCodepage)"/>

<!-- https://docs.microsoft.com/en-us/windows/win32/msi/reinstallmode -->
<!-- reinstall if the file is missing or a different version is present; rewrite all registry entries; reinstall all shortcuts -->
<Property Id="REINSTALLMODE" Value="dmus" />
<!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts -->
<Property Id="REINSTALLMODE" Value="amus" />

{{#if allow_downgrades}}
<MajorUpgrade AllowDowngrades="yes" Schedule="afterInstallValidate" />
Expand Down
1 change: 1 addition & 0 deletions tooling/cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion tooling/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ description = "Command line interface for building Tauri apps"
include = [
"src/",
"/templates",
"MergeModules/",
"scripts/",
"*.json",
"*.rs",
Expand Down
Binary file removed tooling/cli/MergeModules/Microsoft_VC142_CRT_x64.msm
Binary file not shown.
Binary file removed tooling/cli/MergeModules/Microsoft_VC142_CRT_x86.msm
Binary file not shown.
37 changes: 0 additions & 37 deletions tooling/cli/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,43 +240,6 @@ pub fn command(options: Options) -> Result<()> {
}

if config_.tauri.bundle.active {
// move merge modules to the out dir so the bundler can load it
#[cfg(windows)]
{
let target = options
.target
.clone()
.unwrap_or_else(|| std::env::consts::ARCH.into());
let arch = if target.starts_with("x86_64") {
"x86_64"
} else if target.starts_with('i') || target.starts_with("x86") {
"x86"
} else if target.starts_with("arm") {
"arm"
} else if target.starts_with("aarch64") {
"aarch64"
} else {
panic!(
"Unexpected target architecture {}",
target.split('_').next().unwrap()
)
};
let (filename, vcruntime_msm) = if arch == "x86" {
let _ = std::fs::remove_file(out_dir.join("Microsoft_VC142_CRT_x64.msm"));
(
"Microsoft_VC142_CRT_x86.msm",
include_bytes!("../MergeModules/Microsoft_VC142_CRT_x86.msm").to_vec(),
)
} else {
let _ = std::fs::remove_file(out_dir.join("Microsoft_VC142_CRT_x86.msm"));
(
"Microsoft_VC142_CRT_x64.msm",
include_bytes!("../MergeModules/Microsoft_VC142_CRT_x64.msm").to_vec(),
)
};
std::fs::write(out_dir.join(filename), vcruntime_msm)?;
}

let package_types = if let Some(names) = options.bundles {
let mut types = vec![];
for name in names {
Expand Down

0 comments on commit bb06150

Please sign in to comment.