Skip to content

Use different release profiles for desktop and server builds #3693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion packages/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ hyper-rustls = { workspace = true }
rustls = { workspace = true }
rayon = { workspace = true }
futures-channel = { workspace = true }
cargo-config2 = { workspace = true, optional = true }
cargo-config2 = { workspace = true }
krates = { version = "0.17.5" }
regex = "1.11.1"
console = "0.15.11"
Expand Down
31 changes: 11 additions & 20 deletions packages/cli/src/build/request.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{progress::ProgressTx, BuildArtifacts};
use crate::dioxus_crate::DioxusCrate;
use crate::{get_profile_for_platform, AppBundle, Platform, Result, TraceSrc};
use crate::{link::LinkAction, BuildArgs};
use crate::{AppBundle, Platform, Result, TraceSrc};
use anyhow::Context;
use dioxus_cli_config::{APP_TITLE_ENV, ASSET_ROOT_ENV};
use dioxus_cli_opt::AssetManifest;
Expand Down Expand Up @@ -266,32 +266,23 @@ impl BuildRequest {
// Set the target, profile and features that vary between the app and server builds
if self.build.platform() == Platform::Server {
cargo_args.push("--profile".to_string());
match self.build.release {
true => cargo_args.push("release".to_string()),
false => cargo_args.push(self.build.server_profile.to_string()),
};
let profile = self.build.server_profile.as_deref().unwrap_or_else(|| {
get_profile_for_platform(self.build.platform(), self.build.release)
});
cargo_args.push(profile.to_string());

// If the user provided a server target, use it, otherwise use the default host target.
if let Some(target) = self.build.target_args.server_target.as_deref() {
cargo_args.push("--target".to_string());
cargo_args.push(target.to_string());
}
} else {
// Add required profile flags. --release overrides any custom profiles.
let custom_profile = &self.build.profile.as_ref();
if custom_profile.is_some() || self.build.release {
cargo_args.push("--profile".to_string());
match self.build.release {
true => cargo_args.push("release".to_string()),
false => {
cargo_args.push(
custom_profile
.expect("custom_profile should have been checked by is_some")
.to_string(),
);
}
};
}
// Add required profile flags. If a profile wasn't set manually, use the default one
cargo_args.push("--profile".to_string());
let profile = self.build.profile.as_deref().unwrap_or_else(|| {
get_profile_for_platform(self.build.platform(), self.build.release)
});
cargo_args.push(profile.to_string());

// todo: use the right arch based on the current arch
let custom_target = match self.build.platform() {
Expand Down
30 changes: 12 additions & 18 deletions packages/cli/src/cli/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::*;
use crate::{Builder, DioxusCrate, Platform, PROFILE_SERVER};
use crate::{get_profile_for_platform, Builder, DioxusCrate, Platform};

/// Build the Rust Dioxus app and all of its assets.
///
Expand All @@ -21,8 +21,8 @@ pub(crate) struct BuildArgs {
pub(crate) profile: Option<String>,

/// Build with custom profile for the fullstack server
#[clap(long, default_value_t = PROFILE_SERVER.to_string())]
pub(crate) server_profile: String,
#[clap(long)]
pub(crate) server_profile: Option<String>,

/// Build platform: support Web & Desktop [default: "default_platform"]
#[clap(long, value_enum)]
Expand Down Expand Up @@ -147,21 +147,15 @@ impl BuildArgs {
return Err(anyhow::anyhow!("Fullstack builds require a server feature on the target crate. Add a `server` feature to the crate and try again.").into());
}

// Set the profile of the build if it's not already set
// We do this for android/wasm since they require
if self.profile.is_none() && !self.release {
match self.platform {
Some(Platform::Android) => {
self.profile = Some(crate::dioxus_crate::PROFILE_ANDROID.to_string());
}
Some(Platform::Web) => {
self.profile = Some(crate::dioxus_crate::PROFILE_WASM.to_string());
}
Some(Platform::Server) => {
self.profile = Some(crate::dioxus_crate::PROFILE_SERVER.to_string());
}
_ => {}
}
// Set the profile of the build if it's not already set. Every platform gets a different profile so they builds don't
// conflict. This both lets the builds happen in parallel and makes sure they don't overwrite each other's output
if self.profile.is_none() {
self.profile =
Some(get_profile_for_platform(self.platform.unwrap(), self.release).to_string());
}
if self.server_profile.is_none() {
self.server_profile =
Some(get_profile_for_platform(Platform::Server, self.release).to_string());
}

// Determine arch if android
Expand Down
5 changes: 3 additions & 2 deletions packages/cli/src/cli/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ impl Bundle {
pub(crate) async fn bundle(mut self) -> Result<StructuredOutput> {
tracing::info!("Bundling project...");

// We always use `release` mode for bundling
self.build_arguments.release = true;

let krate = DioxusCrate::new(&self.build_arguments.target_args)
.context("Failed to load Dioxus workspace")?;

// We always use `release` mode for bundling
self.build_arguments.release = true;
self.build_arguments.resolve(&krate).await?;

tracing::info!("Building app...");
Expand Down
71 changes: 51 additions & 20 deletions packages/cli/src/dioxus_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{config::DioxusConfig, TargetArgs};
use crate::{Arch, CliSettings};
use crate::{Platform, Result};
use anyhow::Context;
use cargo_config2::cargo_home_with_cwd;
use itertools::Itertools;
use krates::{cm::Target, KrateDetails};
use krates::{cm::TargetKind, Cmd, Krates, NodeId};
Expand All @@ -22,9 +23,28 @@ pub(crate) struct DioxusCrate {
pub(crate) settings: Arc<CliSettings>,
}

pub(crate) static PROFILE_WASM: &str = "wasm-dev";
pub(crate) static PROFILE_ANDROID: &str = "android-dev";
pub(crate) static PROFILE_SERVER: &str = "server-dev";
const PROFILE_MATRIX: [(Platform, [&str; 2]); 8] = [
(Platform::Web, ["wasm-dev", "wasm-release"]),
(Platform::Server, ["server-dev", "server-release"]),
(Platform::Ios, ["ios-dev", "ios-release"]),
(Platform::Android, ["android-dev", "android-release"]),
(Platform::Windows, ["windows-dev", "windows-release"]),
(Platform::MacOS, ["macos-dev", "macos-release"]),
(Platform::Linux, ["linux-dev", "linux-release"]),
(Platform::Liveview, ["liveview-dev", "liveview-release"]),
];

pub(crate) fn get_profile_for_platform(platform: Platform, release: bool) -> &'static str {
PROFILE_MATRIX
.iter()
.find_map(|(p, profiles)| {
if *p == platform {
return Some(profiles[release as usize]);
}
None
})
.unwrap_or_else(|| panic!("No profile for platform {platform:?}. This is a bug in the dioxus-cli. Please open an issue at https://github.com/DioxusLabs/dioxus/issues/new/choose"))
}

impl DioxusCrate {
pub(crate) fn new(target: &TargetArgs) -> Result<Self> {
Expand Down Expand Up @@ -218,6 +238,19 @@ impl DioxusCrate {
.to_path_buf()
}

/// Get the directory where cargo stores its data
pub(crate) fn cargo_home(&self) -> Result<PathBuf> {
Ok(cargo_home_with_cwd(&self.workspace_dir())
.ok_or_else(|| anyhow::anyhow!("Failed to find cargo home. Please set CARGO_HOME."))?)
}

/// Get the path to the global cargo config
pub(crate) fn cargo_config(&self) -> Result<PathBuf> {
let cargo_home = self.cargo_home()?;
let config_path = cargo_home.join("config.toml");
Ok(config_path)
}

/// Get the main source file of the target
pub(crate) fn main_source_file(&self) -> PathBuf {
self.target.src_path.as_std_path().to_path_buf()
Expand Down Expand Up @@ -378,7 +411,7 @@ impl DioxusCrate {
// Find or create the client and server profiles in the top-level Cargo.toml file
// todo(jon): we should/could make these optional by placing some defaults somewhere
pub(crate) fn initialize_profiles(&self) -> crate::Result<()> {
let config_path = self.workspace_dir().join("Cargo.toml");
let config_path = self.cargo_config()?;
let mut config = match std::fs::read_to_string(&config_path) {
Ok(config) => config.parse::<toml_edit::DocumentMut>().map_err(|e| {
crate::Error::Other(anyhow::anyhow!("Failed to parse Cargo.toml: {}", e))
Expand All @@ -391,23 +424,21 @@ impl DioxusCrate {
.entry("profile")
.or_insert(Item::Table(Default::default()))
{
if let toml_edit::Entry::Vacant(entry) = table.entry(PROFILE_WASM) {
let mut client = toml_edit::Table::new();
client.insert("inherits", Item::Value("dev".into()));
client.insert("opt-level", Item::Value(1.into()));
entry.insert(Item::Table(client));
}

if let toml_edit::Entry::Vacant(entry) = table.entry(PROFILE_SERVER) {
let mut server = toml_edit::Table::new();
server.insert("inherits", Item::Value("dev".into()));
entry.insert(Item::Table(server));
}
for (platform, [debug_profile, release_profile]) in PROFILE_MATRIX.iter() {
if let toml_edit::Entry::Vacant(entry) = table.entry(debug_profile) {
let mut client = toml_edit::Table::new();
client.insert("inherits", Item::Value("dev".into()));
if platform == &Platform::Web {
client.insert("opt-level", Item::Value(1.into()));
}
entry.insert(Item::Table(client));
}

if let toml_edit::Entry::Vacant(entry) = table.entry(PROFILE_ANDROID) {
let mut android = toml_edit::Table::new();
android.insert("inherits", Item::Value("dev".into()));
entry.insert(Item::Table(android));
if let toml_edit::Entry::Vacant(entry) = table.entry(release_profile) {
let mut client = toml_edit::Table::new();
client.insert("inherits", Item::Value("release".into()));
entry.insert(Item::Table(client));
}
}
}

Expand Down
Loading