Skip to content

Commit

Permalink
Fix outdir not work when run dx bundle --platform web --outdir mydir (#…
Browse files Browse the repository at this point in the history
…3572)

* Make legacy asset dir optional
* properly implement outdir

---------

Co-authored-by: Jonathan Kelley <[email protected]>
Co-authored-by:  Nathy-bajo <[email protected]>
  • Loading branch information
3 people authored Jan 16, 2025
1 parent db16de1 commit 19d5fae
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 143 deletions.
35 changes: 35 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions packages/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ tauri-bundler = { workspace = true }
include_dir = "0.7.4"
flate2 = "1.0.35"
tar = "0.4.43"
dircpy = "0.3.19"

[build-dependencies]
built = { version = "=0.7.4", features = ["git2"] }
Expand Down
10 changes: 7 additions & 3 deletions packages/cli/src/build/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,12 @@ impl BuildRequest {
// If the path is absolute, make it relative to the current directory before we join it
// The path is actually a web path which is relative to the root of the website
let path = path.strip_prefix("/").unwrap_or(path);
let asset_dir_path = self.krate.legacy_asset_dir().join(path);
if let Ok(absolute_path) = asset_dir_path.canonicalize() {
let asset_dir_path = self
.krate
.legacy_asset_dir()
.map(|dir| dir.join(path).canonicalize());

if let Some(Ok(absolute_path)) = asset_dir_path {
let absolute_crate_root = self.krate.crate_dir().canonicalize().unwrap();
PathBuf::from("./")
.join(absolute_path.strip_prefix(absolute_crate_root).unwrap())
Expand All @@ -179,7 +183,7 @@ impl BuildRequest {
ResourceType::Script => "web.resource.script",
};

tracing::debug!(
tracing::warn!(
"{RESOURCE_DEPRECATION_MESSAGE}\nTo migrate to head components, remove `{section_name}` and include the following rsx in your root component:\n```rust\n{replacement_components}\n```"
);
}
Expand Down
121 changes: 65 additions & 56 deletions packages/cli/src/cli/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{AppBundle, BuildArgs, Builder, DioxusCrate, Platform};
use anyhow::Context;
use path_absolutize::Absolutize;
use std::collections::HashMap;
use tauri_bundler::{BundleBinary, BundleSettings, PackageSettings, SettingsBuilder};

Expand All @@ -25,12 +26,13 @@ pub struct Bundle {

/// The directory in which the final bundle will be placed.
///
/// Relative paths will be placed relative to the current working directory.
/// Relative paths will be placed relative to the current working directory if specified.
/// Otherwise, the out_dir path specified in Dioxus.toml will be used (relative to the crate root).
///
/// We will flatten the artifacts into this directory - there will be no differentiation between
/// artifacts produced by different platforms.
#[clap(long)]
pub outdir: Option<PathBuf>,
pub out_dir: Option<PathBuf>,

/// The arguments for the dioxus build
#[clap(flatten)]
Expand All @@ -54,86 +56,93 @@ impl Bundle {
.finish()
.await?;

tracing::info!("Copying app to output directory...");

// If we're building for iOS, we need to bundle the iOS bundle
if self.build_arguments.platform() == Platform::Ios && self.package_types.is_none() {
self.package_types = Some(vec![crate::PackageType::IosBundle]);
}

let mut cmd_result = StructuredOutput::Success;
let mut bundles = vec![];

// Copy the server over if it exists
if bundle.build.build.fullstack {
bundles.push(bundle.server_exe().unwrap());
}

// Create a list of bundles that we might need to copy
match self.build_arguments.platform() {
// By default, mac/win/linux work with tauri bundle
Platform::MacOS | Platform::Linux | Platform::Windows => {
let bundles = self.bundle_desktop(krate, bundle)?;

tracing::info!("Bundled app successfully!");
tracing::info!("App produced {} outputs:", bundles.len());
tracing::debug!("Bundling produced bundles: {:#?}", bundles);

// Copy the bundles to the output directory and log their locations
let mut bundle_paths = vec![];
for bundle in bundles {
for src in bundle.bundle_paths {
let src = if let Some(outdir) = &self.outdir {
let dest = outdir.join(src.file_name().expect("Filename to exist"));
crate::fastfs::copy_asset(&src, &dest)
.context("Failed to copy or compress optimized asset")?;
dest
} else {
src.clone()
};

tracing::info!(
"{} - [{}]",
bundle.package_type.short_name(),
src.display()
);

bundle_paths.push(src);
}
tracing::info!("Running desktop bundler...");
for bundle in self.bundle_desktop(&krate, &bundle)? {
bundles.extend(bundle.bundle_paths);
}

cmd_result = StructuredOutput::BundleOutput {
bundles: bundle_paths,
};
}

Platform::Web => {
tracing::info!("App available at: {}", bundle.build.root_dir().display());
}

// Web/ios can just use their root_dir
Platform::Web => bundles.push(bundle.build.root_dir()),
Platform::Ios => {
tracing::warn!("Signed iOS bundles are not yet supported");
tracing::info!(
"The bundle is available at: {}",
bundle.build.root_dir().display()
);
}

Platform::Server => {
tracing::info!("Server available at: {}", bundle.build.root_dir().display())
tracing::warn!("iOS bundles are not currently codesigned! You will need to codesign the app before distributing.");
bundles.push(bundle.build.root_dir())
}
Platform::Liveview => tracing::info!(
"Liveview server available at: {}",
bundle.build.root_dir().display()
),
Platform::Server => bundles.push(bundle.build.root_dir()),
Platform::Liveview => bundles.push(bundle.build.root_dir()),

// todo(jon): we can technically create apks (already do...) just need to expose it
Platform::Android => {
return Err(Error::UnsupportedFeature(
"Android bundles are not yet supported".into(),
));
}
};

Ok(cmd_result)
// Copy the bundles to the output directory if one was specified
let crate_outdir = bundle.build.krate.crate_out_dir();
if let Some(outdir) = self.out_dir.clone().or(crate_outdir) {
let outdir = outdir
.absolutize()
.context("Failed to absolutize output directory")?;

tracing::info!("Copying bundles to output directory: {}", outdir.display());

std::fs::create_dir_all(&outdir)?;

for bundle_path in bundles.iter_mut() {
let destination = outdir.join(bundle_path.file_name().unwrap());

tracing::debug!(
"Copying from {} to {}",
bundle_path.display(),
destination.display()
);

if bundle_path.is_dir() {
dircpy::CopyBuilder::new(&bundle_path, &destination)
.overwrite(true)
.run_par()
.context("Failed to copy the app to output directory")?;
} else {
std::fs::copy(&bundle_path, &destination)
.context("Failed to copy the app to output directory")?;
}

*bundle_path = destination;
}
}

for bundle_path in bundles.iter() {
tracing::info!(
"Bundled app at: {}",
bundle_path.absolutize().unwrap().display()
);
}

Ok(StructuredOutput::BundleOutput { bundles })
}

fn bundle_desktop(
&self,
krate: DioxusCrate,
bundle: AppBundle,
krate: &DioxusCrate,
bundle: &AppBundle,
) -> Result<Vec<tauri_bundler::Bundle>, Error> {
_ = std::fs::remove_dir_all(krate.bundle_dir(self.build_arguments.platform()));

Expand Down
9 changes: 4 additions & 5 deletions packages/cli/src/config/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ use std::path::PathBuf;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct ApplicationConfig {
#[serde(default = "asset_dir_default")]
pub(crate) asset_dir: PathBuf,
#[serde(default)]
pub(crate) asset_dir: Option<PathBuf>,

#[serde(default)]
pub(crate) sub_package: Option<String>,
}

pub(crate) fn asset_dir_default() -> PathBuf {
PathBuf::from("assets")
#[serde(default)]
pub(crate) out_dir: Option<PathBuf>,
}
3 changes: 2 additions & 1 deletion packages/cli/src/config/dioxus_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ impl Default for DioxusConfig {
fn default() -> Self {
Self {
application: ApplicationConfig {
asset_dir: asset_dir_default(),
asset_dir: None,
sub_package: None,
out_dir: None,
},
web: WebConfig {
app: WebAppConfig {
Expand Down
37 changes: 29 additions & 8 deletions packages/cli/src/dioxus_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,28 @@ impl DioxusCrate {
})
}

/// Compose an asset directory. Represents the typical "public" directory
/// with publicly available resources (configurable in the `Dioxus.toml`).
pub(crate) fn legacy_asset_dir(&self) -> PathBuf {
self.crate_dir().join(&self.config.application.asset_dir)
/// The asset dir we used to support before manganis became the default.
/// This generally was just a folder in your Dioxus.toml called "assets" or "public" where users
/// would store their assets.
///
/// With manganis you now use `asset!()` and we pick it up automatically.
pub(crate) fn legacy_asset_dir(&self) -> Option<PathBuf> {
self.config
.application
.asset_dir
.clone()
.map(|dir| self.crate_dir().join(dir))
}

/// Get the list of files in the "legacy" asset directory
pub(crate) fn legacy_asset_dir_files(&self) -> Vec<PathBuf> {
let mut files = vec![];

let Ok(read_dir) = self.legacy_asset_dir().read_dir() else {
let Some(legacy_asset_dir) = self.legacy_asset_dir() else {
return files;
};

let Ok(read_dir) = legacy_asset_dir.read_dir() else {
return files;
};

Expand All @@ -136,10 +147,20 @@ impl DioxusCrate {
files
}

/// Get the outdir specified by the Dioxus.toml, relative to the crate directory.
/// We don't support workspaces yet since that would cause a collision of bundles per project.
pub(crate) fn crate_out_dir(&self) -> Option<PathBuf> {
self.config
.application
.out_dir
.as_ref()
.map(|out_dir| self.crate_dir().join(out_dir))
}

/// Compose an out directory. Represents the typical "dist" directory that
/// is "distributed" after building an application (configurable in the
/// `Dioxus.toml`).
fn out_dir(&self) -> PathBuf {
fn internal_out_dir(&self) -> PathBuf {
let dir = self.workspace_dir().join("target").join("dx");
std::fs::create_dir_all(&dir).unwrap();
dir
Expand All @@ -153,7 +174,7 @@ impl DioxusCrate {
/// target/dx/build/app/web/public/
/// target/dx/build/app/web/server.exe
pub(crate) fn build_dir(&self, platform: Platform, release: bool) -> PathBuf {
self.out_dir()
self.internal_out_dir()
.join(self.executable_name())
.join(if release { "release" } else { "debug" })
.join(platform.build_folder_name())
Expand All @@ -164,7 +185,7 @@ impl DioxusCrate {
/// target/dx/bundle/app/blah.exe
/// target/dx/bundle/app/public/
pub(crate) fn bundle_dir(&self, platform: Platform) -> PathBuf {
self.out_dir()
self.internal_out_dir()
.join(self.executable_name())
.join("bundle")
.join(platform.build_folder_name())
Expand Down
Loading

0 comments on commit 19d5fae

Please sign in to comment.