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: 0 additions & 8 deletions packages/cli/src/build/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,6 @@ pub(crate) struct BuildRequest {
pub(crate) profile: String,
pub(crate) release: bool,
pub(crate) bundle: BundleFormat,
pub(crate) enabled_renderers: Vec<Renderer>,
pub(crate) triple: Triple,
pub(crate) device: bool,
pub(crate) package: String,
Expand Down Expand Up @@ -619,12 +618,6 @@ impl BuildRequest {
},
};

// Just grab the renderers from the enabled renderers and discard the feature names
let enabled_renderers = enabled_renderers
.into_iter()
.map(|(renderer, _)| renderer)
.collect::<Vec<_>>();

// We usually use the simulator unless --device is passed *or* a device is detected by probing.
// For now, though, since we don't have probing, it just defaults to false
// Tools like xcrun/adb can detect devices
Expand Down Expand Up @@ -808,7 +801,6 @@ impl BuildRequest {
device,
workspace,
config,
enabled_renderers,
target_dir,
custom_linker,
link_args_file,
Expand Down
133 changes: 68 additions & 65 deletions packages/cli/src/cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,41 +40,77 @@ pub struct BuildTargets {
pub server: Option<BuildRequest>,
}

impl BuildArgs {
fn default_client(&self) -> &TargetArgs {
&self.build_arguments
}
impl CommandWithPlatformOverrides<BuildArgs> {
/// We need to decompose the combined `BuildArgs` into the individual targets that we need to build.
///
/// Only in a few cases do we spin out an additional server binary:
/// - the fullstack feature is passed
/// - the fullstack flag is enabled
/// - the server flag is enabled
///
/// The buildtargets configuration comes in two flavors:
/// - implied via the `fullstack` feature
/// - explicit when using `@server and @client`
///
/// We use the client arguments to build the client target, and then make a few changes to make
/// the server target.
///
/// The `--fullstack` feature is basically the same as passing `--features fullstack`
///
/// Some examples:
/// ```shell, ignore
/// dx serve --target wasm32-unknown-unknown --fullstack # serves both client and server
/// dx serve --target wasm32-unknown-unknown --features fullstack # serves both client and server
/// dx serve --target wasm32-unknown-unknown # only serves the client
/// dx serve --target wasm32-unknown-unknown # servers both if `fullstack` is enabled on dioxus
/// dx serve @client --target wasm32-unknown-unknown # only serves the client
/// dx serve @client --target wasm32-unknown-unknown --fullstack # serves both client and server
/// ```
///
/// Currently it is not possible to serve the server without the client, but this could be added in the future.
pub async fn into_targets(self) -> Result<BuildTargets> {
let workspace = Workspace::current().await?;

// do some logging to ensure dx matches the dioxus version since we're not always API compatible
workspace.check_dioxus_version_against_cli();

// The client args are the `@client` arguments, or the shared build arguments if @client is not specified.
let client_args = &self.client.as_ref().unwrap_or(&self.shared).build_arguments;

// Create the client build request
let client = BuildRequest::new(client_args, None, workspace.clone()).await?;

// Create the server build request if needed
// This happens when 1) fullstack is enabled, 2)
let mut server = None;
if matches!(self.shared.fullstack, Some(true))
|| client.fullstack_feature_enabled()
|| self.server.is_some()
{
match self.server.as_ref() {
Some(server_args) => {
server = Some(
BuildRequest::new(
&server_args.build_arguments,
Some(client.main_target.clone()),
workspace.clone(),
)
.await?,
);
}
None => {
let mut args = self.shared.build_arguments.clone();
args.platform = Some(crate::Platform::Server);
args.renderer.renderer = Some(crate::Renderer::Server);
args.target = Some(target_lexicon::Triple::host());
server = Some(BuildRequest::new(&args, None, workspace.clone()).await?);
}
}
}

fn default_server(&self, client: &BuildRequest) -> Option<&TargetArgs> {
// Now resolve the builds that we need to.
// These come from the args, but we'd like them to come from the `TargetCmd` chained object
//
// The process here is as follows:
//
// - Create the BuildRequest for the primary target
// - If that BuildRequest is "fullstack", then add the client features
// - If that BuildRequest is "fullstack", then also create a BuildRequest for the server
// with the server features
//
// This involves modifying the BuildRequest to add the client features and server features
// only if we can properly detect that it's a fullstack build. Careful with this, since
// we didn't build BuildRequest to be generally mutable.
let default_server = client.enabled_renderers.contains(&crate::Renderer::Server);

// Make sure we set the fullstack platform so we actually build the fullstack variant
// Users need to enable "fullstack" in their default feature set.
// todo(jon): fullstack *could* be a feature of the app, but right now we're assuming it's always enabled
//
// Now we need to resolve the client features
let fullstack = ((default_server || client.fullstack_feature_enabled())
|| self.fullstack.unwrap_or(false))
&& self.fullstack != Some(false);

fullstack.then_some(&self.build_arguments)
Ok(BuildTargets { client, server })
}
}

impl CommandWithPlatformOverrides<BuildArgs> {
pub async fn build(self) -> Result<StructuredOutput> {
tracing::info!("Building project...");

Expand Down Expand Up @@ -105,37 +141,4 @@ impl CommandWithPlatformOverrides<BuildArgs> {
server: targets.server.map(|s| s.root_dir()),
})
}

pub async fn into_targets(self) -> Result<BuildTargets> {
let workspace = Workspace::current().await?;

// do some logging to ensure dx matches the dioxus version since we're not always API compatible
workspace.check_dioxus_version_against_cli();

let client_args = match &self.client {
Some(client) => &client.build_arguments,
None => self.shared.default_client(),
};
let client = BuildRequest::new(client_args, None, workspace.clone()).await?;

let server_args = match &self.server {
Some(server) => Some(&server.build_arguments),
None => self.shared.default_server(&client),
};

let mut server = None;
// If there is a server, make sure we output in the same directory as the client build so we use the server
// to serve the web client
if let Some(server_args) = server_args {
// Copy the main target from the client to the server
let main_target = client.main_target.clone();
let mut server_args = server_args.clone();
// The renderer in the server build is always set to Server
server_args.renderer.renderer = Some(crate::Renderer::Server);
server =
Some(BuildRequest::new(&server_args, Some(main_target), workspace.clone()).await?);
}

Ok(BuildTargets { client, server })
}
}
Loading