Skip to content

Commit

Permalink
fix build-dependencies resolution when cross-compiling
Browse files Browse the repository at this point in the history
  • Loading branch information
pnmadelaine committed Dec 4, 2024
1 parent 9ff208c commit 9351292
Show file tree
Hide file tree
Showing 19 changed files with 276 additions and 173 deletions.
110 changes: 58 additions & 52 deletions crate2nix/Cargo.nix

Large diffs are not rendered by default.

27 changes: 14 additions & 13 deletions crate2nix/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,7 @@ fn cfg_to_nix_expr_filter(
})?;
Ok(tera::Value::String(cfg_to_nix_expr(&expr)))
} else {
let condition = format!(
"(stdenv.hostPlatform.rust.rustcTarget == {})",
escape_nix_string(key)
);
let condition = format!("(target == {})", escape_nix_string(key));
Ok(tera::Value::String(condition))
}
}
Expand All @@ -207,7 +204,7 @@ fn cfg_to_nix_expr(cfg: &CfgExpr) -> String {
fn render(result: &mut String, cfg: &CfgExpr) {
match cfg {
CfgExpr::Value(Cfg::Name(name)) => {
result.push_str(&format!("(target.{} or false)", target(name)));
result.push_str(&format!("(targetSpec.{} or false)", target(name)));
}
CfgExpr::Value(Cfg::KeyPair(key, value)) => {
let escaped_value = escape_nix_string(value);
Expand All @@ -216,9 +213,13 @@ fn cfg_to_nix_expr(cfg: &CfgExpr) -> String {
} else if key == "target_feature" {
format!("(builtins.elem {} targetFeatures)", escaped_value)
} else if key == "target_family" {
format!("(builtins.elem {} target.{})", escaped_value, target(key))
format!(
"(builtins.elem {} targetSpec.{})",
escaped_value,
target(key)
)
} else {
format!("({} == target.{} or null)", escaped_value, target(key))
format!("({} == targetSpec.{} or null)", escaped_value, target(key))
});
}
CfgExpr::Not(expr) => {
Expand Down Expand Up @@ -271,7 +272,7 @@ fn test_render_cfg_to_nix_expr() {
}

assert_eq!(
"(target.\"unix\" or false)",
"(targetSpec.\"unix\" or false)",
&cfg_to_nix_expr(&name("unix"))
);
assert_eq!(
Expand All @@ -282,23 +283,23 @@ fn test_render_cfg_to_nix_expr() {
]))
);
assert_eq!(
"(builtins.elem \"unix\" target.\"family\")",
"(builtins.elem \"unix\" targetSpec.\"family\")",
&cfg_to_nix_expr(&kv("target_family", "unix"))
);
assert_eq!(
"(\"linux\" == target.\"os\" or null)",
"(\"linux\" == targetSpec.\"os\" or null)",
&cfg_to_nix_expr(&kv("target_os", "linux"))
);
assert_eq!(
"(!(\"linux\" == target.\"os\" or null))",
"(!(\"linux\" == targetSpec.\"os\" or null))",
&cfg_to_nix_expr(&CfgExpr::Not(Box::new(kv("target_os", "linux"))))
);
assert_eq!(
"((target.\"unix\" or false) || (\"linux\" == target.\"os\" or null))",
"((targetSpec.\"unix\" or false) || (\"linux\" == targetSpec.\"os\" or null))",
&cfg_to_nix_expr(&CfgExpr::Any(vec![name("unix"), kv("target_os", "linux")]))
);
assert_eq!(
"((target.\"unix\" or false) && (\"linux\" == target.\"os\" or null))",
"((targetSpec.\"unix\" or false) && (\"linux\" == targetSpec.\"os\" or null))",
&cfg_to_nix_expr(&CfgExpr::All(vec![name("unix"), kv("target_os", "linux")]))
);
assert_eq!("true", &cfg_to_nix_expr(&CfgExpr::All(vec![])));
Expand Down
6 changes: 3 additions & 3 deletions crate2nix/templates/Cargo.nix.tera
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ rec {
usesDefaultFeatures = false;
{%- endif -%}
{%- if dependency.target %}
target = { target, features }: {{dependency.target | cfg_to_nix_expr | safe }};
target = {target, targetSpec, features}: {{dependency.target | cfg_to_nix_expr | safe}};
{%- endif %}
{%- if dependency.features %}
features = [ {% for feature in dependency.features %}{{feature}} {% endfor %}];
Expand All @@ -221,7 +221,7 @@ rec {
usesDefaultFeatures = false;
{%- endif -%}
{%- if dependency.target %}
target = {target, features}: {{dependency.target | cfg_to_nix_expr | safe }};
target = {target, targetSpec, features}: {{dependency.target | cfg_to_nix_expr | safe}};
{%- endif %}
{%- if dependency.features %}
features = [ {% for feature in dependency.features %}{{feature}} {% endfor %}];
Expand All @@ -246,7 +246,7 @@ rec {
usesDefaultFeatures = false;
{%- endif -%}
{%- if dependency.target %}
target = {target, features}: {{dependency.target | cfg_to_nix_expr | safe }};
target = {target, targetSpec, features}: {{dependency.target | cfg_to_nix_expr | safe}};
{%- endif %}
{%- if dependency.features %}
features = [ {% for feature in dependency.features %}{{feature}} {% endfor %}];
Expand Down
48 changes: 27 additions & 21 deletions crate2nix/templates/nix/crate2nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ rec {
/* Target (platform) data for conditional dependencies.
This corresponds roughly to what buildRustCrate is setting.
*/
makeDefaultTarget = platform: {
makeDefaultTargetSpec = platform: {
unix = platform.isUnix;
windows = platform.isWindows;
fuchsia = true;
Expand Down Expand Up @@ -241,20 +241,21 @@ rec {
, crateConfigs ? crates
, buildRustCrateForPkgsFunc
, runTests
, makeTarget ? makeDefaultTarget
, makeTargetSpec ? makeDefaultTargetSpec
} @ args:
assert (builtins.isAttrs crateConfigs);
assert (builtins.isString packageId);
assert (builtins.isList features);
assert (builtins.isAttrs (makeTarget stdenv.hostPlatform));
assert (builtins.isAttrs (makeTargetSpec stdenv.hostPlatform));
assert (builtins.isBool runTests);
let
rootPackageId = packageId;
mergedFeatures = mergePackageFeatures
(
args // {
inherit rootPackageId;
target = makeTarget stdenv.hostPlatform // { test = runTests; };
target = stdenv.hostPlatform.rust.rustcTarget;
targetSpec = makeTargetSpec stdenv.hostPlatform // { test = runTests; };
}
);
# Memoize built packages so that reappearing packages are only built once.
Expand All @@ -263,7 +264,8 @@ rec {
let
self = {
crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs;
target = makeTarget stdenv.hostPlatform;
target = pkgs.stdenv.hostPlatform.rust.rustcTarget;
targetSpec = makeTargetSpec pkgs.stdenv.hostPlatform;
build = mkBuiltByPackageIdByPkgs pkgs.buildPackages;
};
in
Expand All @@ -281,7 +283,7 @@ rec {
dependencies =
dependencyDerivations {
inherit features;
inherit (self) target;
inherit (self) target targetSpec;
buildByPackageId = depPackageId:
# proc_macro crates must be compiled for the build architecture
if crateConfigs.${depPackageId}.procMacro or false
Expand All @@ -294,7 +296,7 @@ rec {
buildDependencies =
dependencyDerivations {
inherit features;
inherit (self.build) target;
inherit (self.build) target targetSpec;
buildByPackageId = depPackageId:
self.build.crates.${depPackageId};
dependencies = crateConfig.buildDependencies or [ ];
Expand All @@ -303,12 +305,12 @@ rec {
let
buildDeps = filterEnabledDependencies {
inherit features;
inherit (self) target;
inherit (self) target targetSpec;
dependencies = crateConfig.dependencies or [ ] ++ devDependencies;
};
hostDeps = filterEnabledDependencies {
inherit features;
inherit (self.build) target;
inherit (self.build) target targetSpec;
dependencies = crateConfig.buildDependencies or [ ];
};
in
Expand Down Expand Up @@ -362,13 +364,14 @@ rec {
, features
, dependencies
, target
, targetSpec
}:
assert (builtins.isList features);
assert (builtins.isList dependencies);
assert (builtins.isAttrs target);
assert (builtins.isAttrs targetSpec);
let
enabledDependencies = filterEnabledDependencies {
inherit dependencies features target;
inherit dependencies features target targetSpec;
};
depDerivation = dependency: buildByPackageId dependency.packageId;
in
Expand All @@ -387,7 +390,7 @@ rec {
else val;

/* Returns various tools to debug a crate. */
debugCrate = { packageId, target ? makeDefaultTarget stdenv.hostPlatform }:
debugCrate = { packageId, target ? stdenv.hostPlatform.rust.rustcTarget, targetSpec ? makeDefaultTargetSpec stdenv.hostPlatform }:
assert (builtins.isString packageId);
let
debug = rec {
Expand All @@ -410,10 +413,10 @@ rec {
);
mergedPackageFeatures = mergePackageFeatures {
features = rootFeatures;
inherit packageId target;
inherit packageId target targetSpec;
};
diffedDefaultPackageFeatures = diffDefaultPackageFeatures {
inherit packageId target;
inherit packageId target targetSpec;
};
};
in
Expand All @@ -428,14 +431,15 @@ rec {
{ crateConfigs ? crates
, packageId
, target
, targetSpec
}:
assert (builtins.isAttrs crateConfigs);
let
prefixValues = prefix: lib.mapAttrs (n: v: { "${prefix}" = v; });
mergedFeatures =
prefixValues
"crate2nix"
(mergePackageFeatures { inherit crateConfigs packageId target; features = [ "default" ]; });
(mergePackageFeatures { inherit crateConfigs packageId target targetSpec; features = [ "default" ]; });
configs = prefixValues "cargo" crateConfigs;
combined = lib.foldAttrs (a: b: a // b) { } [ mergedFeatures configs ];
onlyInCargo =
Expand Down Expand Up @@ -470,6 +474,7 @@ rec {
, dependencyPath ? [ crates.${packageId}.crateName ]
, featuresByPackageId ? { }
, target
, targetSpec
# Adds devDependencies to the crate with rootPackageId.
, runTests ? false
, ...
Expand All @@ -480,7 +485,7 @@ rec {
assert (builtins.isList features);
assert (builtins.isList dependencyPath);
assert (builtins.isAttrs featuresByPackageId);
assert (builtins.isAttrs target);
assert (builtins.isAttrs targetSpec);
assert (builtins.isBool runTests);
let
crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}");
Expand All @@ -497,7 +502,7 @@ rec {
assert (builtins.isList dependencies);
let
enabledDependencies = filterEnabledDependencies {
inherit dependencies target;
inherit dependencies target targetSpec;
features = enabledFeatures;
};
directDependencies = map depWithResolvedFeatures enabledDependencies;
Expand All @@ -516,7 +521,7 @@ rec {
mergePackageFeatures {
features = combinedFeatures;
featuresByPackageId = cache;
inherit crateConfigs packageId target runTests rootPackageId;
inherit crateConfigs packageId target targetSpec runTests rootPackageId;
}
);
cacheWithSelf =
Expand All @@ -543,18 +548,19 @@ rec {
cacheWithAll;

/* Returns the enabled dependencies given the enabled features. */
filterEnabledDependencies = { dependencies, features, target }:
filterEnabledDependencies = { dependencies, features, target, targetSpec }:
assert (builtins.isList dependencies);
assert (builtins.isList features);
assert (builtins.isAttrs target);
assert (builtins.isString target);
assert (builtins.isAttrs targetSpec);

lib.filter
(
dep:
let
targetFunc = dep.target or (features: true);
in
targetFunc { inherit features target; }
targetFunc { inherit features target targetSpec; }
&& (
!(dep.optional or false)
|| builtins.any (doesFeatureEnableDependency dep) features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ let
dependencyDerivations = features: dependencies:
crate2nix.dependencyDerivations {
buildByPackageId = p: fakeCrates.${p};
target = crate2nix.makeDefaultTarget stdenv.hostPlatform;
target = stdenv.hostPlatform.rust.rustcTarget;
targetSpec = crate2nix.makeDefaultTargetSpec stdenv.hostPlatform;
inherit features dependencies;
};
in
Expand Down
3 changes: 2 additions & 1 deletion crate2nix/templates/nix/crate2nix/tests/packageFeatures.nix
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ let
packageId: features:
crate2nix.mergePackageFeatures
{
target = crate2nix.makeDefaultTarget stdenv.hostPlatform;
target = stdenv.hostPlatform.rust.rustcTarget;
targetSpec = crate2nix.makeDefaultTargetSpec stdenv.hostPlatform;
runTests = false;
rootPackageId = packageId;
inherit crateConfigs packageId features;
Expand Down
Loading

0 comments on commit 9351292

Please sign in to comment.