Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cargo/audit.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@ ignore = [
"RUSTSEC-2026-0097",
# glib 0.18.5 unsoundness, fixed by updating to gtk4
"RUSTSEC-2024-0429",
# rkyv 0.7 out-of-bounds read via Rc/Arc archives. Patched only in >= 0.8.17;
# the 0.7 series is unsupported upstream. rkyv reaches Cargo.lock solely as an
# *optional, non-activated* dependency of rust_decimal (rust_decimal ->
# byte-unit -> tauri-plugin-log -> examples/api), so it is never compiled:
# `cargo tree -i rkyv --workspace --target all` resolves to nothing. No
# workspace code deserializes rkyv archives, trusted or otherwise. Removable
# only when rust_decimal moves its optional dep to rkyv 0.8.
"RUSTSEC-2026-0235",
]
6 changes: 6 additions & 0 deletions .changes/exit-with-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'tauri': 'patch:bug'
'tauri-runtime-wry': 'patch:bug'
---

Transfer the exit code from the `window.app_handle().exit(1)` call to the `run_return()` result instead of always returning 0.
5 changes: 5 additions & 0 deletions .changes/fix-deterministic-config-serialization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri-utils': 'patch:bug'
---

Serialize the CSP directive map, header source maps and plugin config with sorted keys so writing the processed config (e.g. the `tauri.conf.json` embedded in Android/iOS projects) is deterministic across builds.
5 changes: 5 additions & 0 deletions .changes/fix-deterministic-embedded-assets-codegen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri-codegen': 'patch:bug'
---

Emit embedded assets and CSP script/style hashes in sorted order so `generate_context!` output no longer depends on the filesystem walk order, which varies across machines and broke reproducible builds.
5 changes: 5 additions & 0 deletions .changes/target-dir-nightly-out-dir.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri-build': 'patch:bug'
---

Resolve the target directory by walking up from `OUT_DIR` to the `build` directory instead of assuming it is exactly three levels up. Recent nightly toolchains add another level to `OUT_DIR`, which made sidecars and resources land in `target/debug/build` instead of `target/debug`.
2 changes: 1 addition & 1 deletion .github/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ It can be configured in [`.changes/config.json`](../.changes/config.json) which

Some packages can't be published directly using `covector` as it requires to be built on a matrix of platforms
such as `tauri-cli` prebuilt binaries which is published using [publish-cli-rs.yml](./workflows/publish-cli-rs.yml)
and `@tauri-apps/cli` native Node.js modules which is published using using [publish-cli-js.yml](./workflows/publish-cli-js.yml)
and `@tauri-apps/cli` native Node.js modules which is published using [publish-cli-js.yml](./workflows/publish-cli-js.yml)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
both of which are triggered after `covector` has created a github release for both of them, see `Trigger @tauri-apps/cli publishing workflow`
and `Trigger tauri-cli publishing workflow` steps in [covector-version-or-publish.yml](./workflows/covector-version-or-publish.yml)

Expand Down
67 changes: 19 additions & 48 deletions Cargo.lock

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

57 changes: 48 additions & 9 deletions crates/tauri-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ use tauri_utils::{

use std::{
collections::HashMap,
env, fs,
env,
ffi::OsStr,
fs,
path::{Path, PathBuf},
};

Expand Down Expand Up @@ -205,6 +207,17 @@ fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
Ok(())
}

// TODO: far from ideal, but there's no other way to get the target dir, see <https://github.com/rust-lang/cargo/issues/5457>
// resolves the target dir from `OUT_DIR`, which is `<target dir>/build/<pkg>-<hash>/out` on stable
// and `<target dir>/build/<pkg>/<hash>/out` on recent nightlies, so we walk up to the `build` dir
// and take its parent instead of assuming a fixed depth.
fn target_dir_from_out_dir(out_dir: &Path) -> Option<&Path> {
out_dir
.ancestors()
.find(|path| path.file_name() == Some(OsStr::new("build")))
.and_then(|build_dir| build_dir.parent())
}
Comment thread
OlympusLedgerOrg marked this conversation as resolved.

// creates a cfg alias if `has_feature` is true.
// `alias` must be a snake case string.
fn cfg_alias(alias: &str, has_feature: bool) {
Expand Down Expand Up @@ -573,14 +586,8 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
// when running codegen in this build script, we need to access the env var directly
env::set_var("TAURI_ENV_TARGET_TRIPLE", &target_triple);

// TODO: far from ideal, but there's no other way to get the target dir, see <https://github.com/rust-lang/cargo/issues/5457>
let target_dir = out_dir
.parent()
.unwrap()
.parent()
.unwrap()
.parent()
.unwrap();
let target_dir = target_dir_from_out_dir(&out_dir)
.with_context(|| format!("failed to resolve the target directory from {out_dir:?}"))?;

if let Some(paths) = &config.bundle.external_bin {
copy_binaries(
Expand Down Expand Up @@ -785,6 +792,38 @@ fn should_static_link_vc_runtime(config: &Config, attributes: &Attributes) -> bo
#[cfg(test)]
mod tests {
use semver::Version;
use std::path::Path;

#[test]
fn target_dir_from_stable_out_dir() {
let out_dir = Path::new("/app/target/debug/build/app-63ba68eead531e35/out");

assert_eq!(
crate::target_dir_from_out_dir(out_dir),
Some(Path::new("/app/target/debug"))
);
}

#[test]
fn target_dir_from_nightly_out_dir() {
let out_dir = Path::new("/app/target/debug/build/app/63ba68eead531e35/out");

assert_eq!(
crate::target_dir_from_out_dir(out_dir),
Some(Path::new("/app/target/debug"))
);
}

#[test]
fn target_dir_from_out_dir_with_triple() {
let out_dir =
Path::new("/app/target/aarch64-apple-darwin/release/build/app/63ba68eead531e35/out");

assert_eq!(
crate::target_dir_from_out_dir(out_dir),
Some(Path::new("/app/target/aarch64-apple-darwin/release"))
);
}

#[test]
fn version_uses_numeric_build_metadata() {
Expand Down
22 changes: 14 additions & 8 deletions crates/tauri-codegen/src/embedded_assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use proc_macro2::TokenStream;
use quote::{quote, ToTokens, TokenStreamExt};
use sha2::{Digest, Sha256};
use std::{
collections::HashMap,
collections::BTreeMap,
fs::File,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -76,7 +76,7 @@ pub type EmbeddedAssetsResult<T> = Result<T, EmbeddedAssetsError>;
/// the compressed assets in that application's binary.
#[derive(Default)]
pub struct EmbeddedAssets {
assets: HashMap<AssetKey, (PathBuf, PathBuf)>,
assets: BTreeMap<AssetKey, (PathBuf, PathBuf)>,
csp_hashes: CspHashes,
}

Expand Down Expand Up @@ -158,7 +158,7 @@ pub struct CspHashes {
/// Scripts that are part of the asset collection (JS or MJS files).
pub(crate) scripts: Vec<String>,
/// Inline scripts (`<script>code</script>`). Maps a HTML path to a list of hashes.
pub(crate) inline_scripts: HashMap<String, Vec<String>>,
pub(crate) inline_scripts: BTreeMap<String, Vec<String>>,
/// A list of hashes of the contents of all `style` elements.
pub(crate) styles: Vec<String>,
}
Expand Down Expand Up @@ -266,13 +266,13 @@ impl EmbeddedAssets {

struct CompressState {
csp_hashes: CspHashes,
assets: HashMap<AssetKey, (PathBuf, PathBuf)>,
assets: BTreeMap<AssetKey, (PathBuf, PathBuf)>,
}

let CompressState { assets, csp_hashes } = paths.into_iter().try_fold(
CompressState {
csp_hashes,
assets: HashMap::new(),
assets: BTreeMap::new(),
},
move |mut state, (prefix, entry)| {
let (key, asset) =
Expand Down Expand Up @@ -302,7 +302,7 @@ impl EmbeddedAssets {
settings
}

/// Compress a file and spit out the information in a [`HashMap`] friendly form.
/// Compress a file and spit out the information in a [`BTreeMap`] friendly form.
fn compress_file(
prefix: &Path,
path: &Path,
Expand Down Expand Up @@ -404,12 +404,18 @@ impl ToTokens for EmbeddedAssets {
}

let mut global_hashes = TokenStream::new();
for script_hash in &self.csp_hashes.scripts {
// Sort the hashes so the generated code does not depend on the filesystem
// walk order the assets were collected in, which varies across machines
let mut script_hashes: Vec<_> = self.csp_hashes.scripts.iter().collect();
script_hashes.sort();
for script_hash in script_hashes {
let hash = script_hash.as_str();
global_hashes.append_all(quote!(CspHash::Script(#hash),));
}

for style_hash in &self.csp_hashes.styles {
let mut style_hashes: Vec<_> = self.csp_hashes.styles.iter().collect();
style_hashes.sort();
for style_hash in style_hashes {
let hash = style_hash.as_str();
global_hashes.append_all(quote!(CspHash::Style(#hash),));
}
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4320,7 +4320,7 @@ fn handle_event_loop<T: UserEvent>(
let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));

if !should_prevent {
*control_flow = ControlFlow::Exit;
*control_flow = ControlFlow::ExitWithCode(code);
}
}
Message::Window(id, WindowMessage::Close) => {
Expand Down
Loading
Loading