From c56bac04f4442d51a2d409e90b960da54cf5fda6 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 3 Oct 2025 23:11:05 -0500 Subject: [PATCH] Look for strip settings in inherited profiles and global configs (#4645) * Look for strip settings in inherited profiles and global configs * fix clippy * use cargo home env var if it exists * fix cargo home config path * small stylistic changes --------- Co-authored-by: Jonathan Kelley --- packages/cli/src/build/request.rs | 24 ++++- packages/cli/src/cargo_toml.rs | 160 ++++++++++++++++++++++++++++++ packages/cli/src/main.rs | 1 + packages/cli/src/workspace.rs | 7 +- 4 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 packages/cli/src/cargo_toml.rs diff --git a/packages/cli/src/build/request.rs b/packages/cli/src/build/request.rs index f5ba458ab..9da5c260b 100644 --- a/packages/cli/src/build/request.rs +++ b/packages/cli/src/build/request.rs @@ -326,6 +326,7 @@ use crate::{ }; use anyhow::{bail, Context}; use cargo_metadata::diagnostic::Diagnostic; +use cargo_toml::{Profile, Profiles, StripSetting}; use depinfo::RustcDepInfo; use dioxus_cli_config::{format_base_path_meta_element, PRODUCT_NAME_ENV}; use dioxus_cli_config::{APP_TITLE_ENV, ASSET_ROOT_ENV}; @@ -3509,9 +3510,28 @@ impl BuildRequest { (_, false) => ("dev", cargo_toml.profile.dev.as_ref()), }; - let Some(profile) = profile else { return }; + let Some(profile) = profile else { + return; + }; - let Some(strip) = profile.strip.as_ref() else { + // Get the strip setting from the profile or the profile it inherits from + fn get_strip(profile: &Profile, profiles: &Profiles) -> Option { + profile.strip.clone().or_else(|| { + // If we can't find the strip setting, check if we inherit from another profile + profile.inherits.as_ref().and_then(|inherits| { + let profile = match inherits.as_str() { + "dev" => profiles.dev.as_ref(), + "release" => profiles.release.as_ref(), + "test" => profiles.test.as_ref(), + "bench" => profiles.bench.as_ref(), + other => profiles.custom.get(other), + }; + profile.and_then(|p| get_strip(p, profiles)) + }) + }) + } + + let Some(strip) = get_strip(profile, &cargo_toml.profile) else { // If the profile doesn't have a strip option, we don't need to warn return; }; diff --git a/packages/cli/src/cargo_toml.rs b/packages/cli/src/cargo_toml.rs new file mode 100644 index 000000000..d96064864 --- /dev/null +++ b/packages/cli/src/cargo_toml.rs @@ -0,0 +1,160 @@ +//! The cargo_toml crate contains some logic for resolving Cargo.toml files with workspace inheritance, but it +//! doesn't handle global configs like ~/.cargo/config.toml. This module handles extending the manifest with those +//! settings if they exist. + +use std::path::{Path, PathBuf}; + +use cargo_toml::{Manifest, Profile, Profiles}; + +/// Load the manifest from a path inheriting from the global config where needed +pub fn load_manifest_from_path(path: &Path) -> Result { + let mut original = Manifest::from_path(path)?; + + // Merge the .cargo/config.toml if it exists + extend_manifest_config_toml(&mut original, &path.join(".cargo").join("config.toml")); + + // Merge the global cargo config if it exists + if let Some(global_config) = global_cargo_config_path() { + extend_manifest_config_toml(&mut original, &global_config); + } + + Ok(original) +} + +/// Get the path to cargo home +fn cargo_home() -> Option { + // If the cargo home env var is set, use that + if let Some(cargo_home) = std::env::var_os("CARGO_HOME") { + return Some(PathBuf::from(cargo_home)); + } + + // Otherwise, use the default location + if cfg!(windows) { + std::env::var_os("USERPROFILE") + .map(|user_profile| PathBuf::from(user_profile).join(".cargo")) + } else if cfg!(unix) { + dirs::home_dir().map(|home_dir| home_dir.join(".cargo")) + } else { + None + } +} + +/// Get the global cargo config path if it exists +fn global_cargo_config_path() -> Option { + cargo_home().map(|cargo_home| cargo_home.join("config.toml")) +} + +// Extend a manifest with a config.toml if it exists +fn extend_manifest_config_toml(manifest: &mut Manifest, path: &Path) { + // Read the config.toml if it exists + let Ok(config) = std::fs::read_to_string(path) else { + return; + }; + + let Ok(config) = config.parse::() else { + return; + }; + + // Try to parse profiles + if let Some(profiles) = config.get("profile").and_then(|p| p.as_table()) { + merge_profiles( + &mut manifest.profile, + toml::from_str::(&profiles.to_string()).unwrap_or_default(), + ); + } +} + +/// Merge the new profiles into the target profiles. Keep the existing values if they exist. +fn merge_profiles(target: &mut Profiles, new: Profiles) { + if let Some(new_release) = new.release { + if target.release.is_none() { + target.release = Some(new_release); + } else { + merge_profile(target.release.as_mut().unwrap(), new_release); + } + } + + if let Some(new_dev) = new.dev { + if target.dev.is_none() { + target.dev = Some(new_dev); + } else { + merge_profile(target.dev.as_mut().unwrap(), new_dev); + } + } + + if let Some(new_test) = new.test { + if target.test.is_none() { + target.test = Some(new_test); + } else { + merge_profile(target.test.as_mut().unwrap(), new_test); + } + } + + if let Some(new_bench) = new.bench { + if target.bench.is_none() { + target.bench = Some(new_bench); + } else { + merge_profile(target.bench.as_mut().unwrap(), new_bench); + } + } + + if let Some(new_doc) = new.doc { + if target.doc.is_none() { + target.doc = Some(new_doc); + } else { + merge_profile(target.doc.as_mut().unwrap(), new_doc); + } + } + + for (profile_name, profile) in new.custom { + if let Some(target_profile) = target.custom.get_mut(&profile_name) { + merge_profile(target_profile, profile); + } else { + target.custom.insert(profile_name, profile); + } + } +} + +/// Merge the new profile into the target profile. Keep the existing values if they exist. +fn merge_profile(target: &mut Profile, new: Profile) { + if target.opt_level.is_none() { + target.opt_level = new.opt_level; + } + if target.debug.is_none() { + target.debug = new.debug; + } + if target.split_debuginfo.is_none() { + target.split_debuginfo = new.split_debuginfo; + } + if target.rpath.is_none() { + target.rpath = new.rpath; + } + if target.lto.is_none() { + target.lto = new.lto; + } + if target.debug_assertions.is_none() { + target.debug_assertions = new.debug_assertions; + } + if target.codegen_units.is_none() { + target.codegen_units = new.codegen_units; + } + if target.panic.is_none() { + target.panic = new.panic; + } + if target.incremental.is_none() { + target.incremental = new.incremental; + } + if target.overflow_checks.is_none() { + target.overflow_checks = new.overflow_checks; + } + if target.strip.is_none() { + target.strip = new.strip; + } + if target.build_override.is_none() { + target.build_override = new.build_override; + } + if target.inherits.is_none() { + target.inherits = new.inherits; + } + target.package.extend(new.package); +} diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index a406873cf..aadc1c100 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -6,6 +6,7 @@ mod build; mod bundle_utils; +mod cargo_toml; mod cli; mod config; mod devcfg; diff --git a/packages/cli/src/workspace.rs b/packages/cli/src/workspace.rs index ac3cb28ae..58aa2f46c 100644 --- a/packages/cli/src/workspace.rs +++ b/packages/cli/src/workspace.rs @@ -96,9 +96,10 @@ impl Workspace { let ignore = Self::workspace_gitignore(krates.workspace_root().as_std_path()); - let cargo_toml = - cargo_toml::Manifest::from_path(krates.workspace_root().join("Cargo.toml")) - .context("Failed to load Cargo.toml")?; + let cargo_toml = crate::cargo_toml::load_manifest_from_path( + krates.workspace_root().join("Cargo.toml").as_std_path(), + ) + .context("Failed to load Cargo.toml")?; let android_tools = crate::build::get_android_tools();