|
@@ -541,10 +541,14 @@ impl BuildRequest {
|
|
|
})?
|
|
|
.clone();
|
|
|
|
|
|
+ // Recursively resolve features into a flattened, deduplicated list of all features enabled
|
|
|
+ // for the top-level crate being compiled.
|
|
|
+ let enabled_features =
|
|
|
+ Self::resolve_enabled_features(main_package, &args.features, !args.no_default_features);
|
|
|
+
|
|
|
// The crate might enable multiple platforms or no platforms at
|
|
|
// We collect all the platforms it enables first and then select based on the --platform arg
|
|
|
- let enabled_platforms =
|
|
|
- Self::enabled_cargo_toml_platforms(main_package, args.no_default_features);
|
|
|
+ let enabled_platforms = Self::enabled_cargo_toml_platforms(main_package, &enabled_features);
|
|
|
let using_dioxus_explicitly = main_package
|
|
|
.dependencies
|
|
|
.iter()
|
|
@@ -560,7 +564,7 @@ impl BuildRequest {
|
|
|
// The user passed --platform XYZ but already has `default = ["ABC"]` in their Cargo.toml or dioxus = { features = ["abc"] }
|
|
|
// We want to strip out the default platform and use the one they passed, setting no-default-features
|
|
|
_ => {
|
|
|
- features.extend(Self::platformless_features(main_package));
|
|
|
+ features.extend(Self::platformless_features(main_package, &enabled_features));
|
|
|
no_default_features = true;
|
|
|
Platform::from(platform_arg)
|
|
|
}
|
|
@@ -2904,12 +2908,48 @@ impl BuildRequest {
|
|
|
.map(|krate| krate.krate.version.to_string())
|
|
|
}
|
|
|
|
|
|
+ // Recursively resolve enabled features starting with:
|
|
|
+ // - Default features if enabled
|
|
|
+ // - Those enabled with an explicit `--features` CLI argument
|
|
|
+ pub(crate) fn resolve_enabled_features(
|
|
|
+ package: &krates::cm::Package,
|
|
|
+ cli_arg_features: &[String],
|
|
|
+ default_features_enabled: bool,
|
|
|
+ ) -> Vec<String> {
|
|
|
+ let mut enabled_features = cli_arg_features.to_vec();
|
|
|
+ if default_features_enabled {
|
|
|
+ enabled_features.push(String::from("default"));
|
|
|
+ }
|
|
|
+
|
|
|
+ let mut pointer = 0;
|
|
|
+ let mut len = enabled_features.len();
|
|
|
+ loop {
|
|
|
+ for i in pointer..len {
|
|
|
+ let feature = &enabled_features[i];
|
|
|
+ if let Some(subfeatures) = package.features.get(feature) {
|
|
|
+ enabled_features.extend(subfeatures.iter().cloned());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if enabled_features.len() == len {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ pointer = len;
|
|
|
+ len = enabled_features.len();
|
|
|
+ }
|
|
|
+
|
|
|
+ enabled_features.sort();
|
|
|
+ enabled_features.dedup();
|
|
|
+
|
|
|
+ enabled_features
|
|
|
+ }
|
|
|
+
|
|
|
/// Return the platforms that are enabled for the package
|
|
|
///
|
|
|
/// Ideally only one platform is enabled but we need to be able to
|
|
|
pub(crate) fn enabled_cargo_toml_platforms(
|
|
|
package: &krates::cm::Package,
|
|
|
- no_default_features: bool,
|
|
|
+ enabled_features: &[String],
|
|
|
) -> Vec<Platform> {
|
|
|
let mut platforms = vec![];
|
|
|
|
|
@@ -2926,27 +2966,13 @@ impl BuildRequest {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Start searching through the default features
|
|
|
- //
|
|
|
- // [features]
|
|
|
- // default = ["dioxus/web"]
|
|
|
- //
|
|
|
- // or
|
|
|
- //
|
|
|
- // [features]
|
|
|
- // default = ["web"]
|
|
|
- // web = ["dioxus/web"]
|
|
|
- if no_default_features {
|
|
|
+ // Recursively resolve all enabled features
|
|
|
+ if enabled_features.is_empty() {
|
|
|
return platforms;
|
|
|
}
|
|
|
|
|
|
- let Some(default) = package.features.get("default") else {
|
|
|
- return platforms;
|
|
|
- };
|
|
|
-
|
|
|
- // we only trace features 1 level deep..
|
|
|
- // TODO: trace all enabled features, not just default features
|
|
|
- for feature in default.iter() {
|
|
|
+ // Check for any enabled features which enable a dioxus platform
|
|
|
+ for feature in enabled_features.iter() {
|
|
|
// If the user directly specified a platform we can just use that.
|
|
|
if feature.starts_with("dioxus/") {
|
|
|
let dx_feature = feature.trim_start_matches("dioxus/");
|
|
@@ -2955,20 +2981,6 @@ impl BuildRequest {
|
|
|
platforms.push(auto);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // If the user is specifying an internal feature that points to a platform, we can use that
|
|
|
- let internal_feature = package.features.get(feature);
|
|
|
- if let Some(internal_feature) = internal_feature {
|
|
|
- for feature in internal_feature {
|
|
|
- if feature.starts_with("dioxus/") {
|
|
|
- let dx_feature = feature.trim_start_matches("dioxus/");
|
|
|
- let auto = Platform::autodetect_from_cargo_feature(dx_feature);
|
|
|
- if let Some(auto) = auto {
|
|
|
- platforms.push(auto);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
platforms.sort();
|
|
@@ -2978,41 +2990,37 @@ impl BuildRequest {
|
|
|
}
|
|
|
|
|
|
/// Gather the features that are enabled for the package
|
|
|
- fn platformless_features(package: &krates::cm::Package) -> Vec<String> {
|
|
|
- let Some(default) = package.features.get("default") else {
|
|
|
- return Vec::new();
|
|
|
- };
|
|
|
-
|
|
|
- let mut kept_features = vec![];
|
|
|
-
|
|
|
- // Only keep the top-level features in the default list that don't point to a platform directly
|
|
|
- // IE we want to drop `web` if default = ["web"]
|
|
|
- 'top: for feature in default {
|
|
|
- // Don't keep features that point to a platform via dioxus/blah
|
|
|
- if feature.starts_with("dioxus/") {
|
|
|
- let dx_feature = feature.trim_start_matches("dioxus/");
|
|
|
- if Platform::autodetect_from_cargo_feature(dx_feature).is_some() {
|
|
|
- continue 'top;
|
|
|
+ fn platformless_features(
|
|
|
+ package: &krates::cm::Package,
|
|
|
+ enabled_features: &[String],
|
|
|
+ ) -> Vec<String> {
|
|
|
+ enabled_features
|
|
|
+ .iter()
|
|
|
+ .filter(|feature| {
|
|
|
+ // Don't keep features that point to a platform via dioxus/blah
|
|
|
+ if feature.starts_with("dioxus/") {
|
|
|
+ let dx_feature = feature.trim_start_matches("dioxus/");
|
|
|
+ if Platform::autodetect_from_cargo_feature(dx_feature).is_some() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- // Don't keep features that point to a platform via an internal feature
|
|
|
- if let Some(internal_feature) = package.features.get(feature) {
|
|
|
- for feature in internal_feature {
|
|
|
- if feature.starts_with("dioxus/") {
|
|
|
- let dx_feature = feature.trim_start_matches("dioxus/");
|
|
|
- if Platform::autodetect_from_cargo_feature(dx_feature).is_some() {
|
|
|
- continue 'top;
|
|
|
+ // Don't keep features that point to a platform via an internal feature
|
|
|
+ if let Some(internal_feature) = package.features.get(*feature) {
|
|
|
+ for feature in internal_feature {
|
|
|
+ if feature.starts_with("dioxus/") {
|
|
|
+ let dx_feature = feature.trim_start_matches("dioxus/");
|
|
|
+ if Platform::autodetect_from_cargo_feature(dx_feature).is_some() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // Otherwise we can keep it
|
|
|
- kept_features.push(feature.to_string());
|
|
|
- }
|
|
|
|
|
|
- kept_features
|
|
|
+ true
|
|
|
+ })
|
|
|
+ .cloned()
|
|
|
+ .collect()
|
|
|
}
|
|
|
|
|
|
pub(crate) fn bundled_app_name(&self) -> String {
|