fix: flakes now obey --eval-system

This required changing an excessive number of places since flakes code
is a delicious bowl of copy pasta.

I didn't change all of the usage sites since some of them run things on
the local machine and you actually want it to be the real system there.

Nevertheless, we probably should have the daemon do something much
different when it receives a `system` setting:
https://git.lix.systems/lix-project/lix/issues/694

Fixes: https://git.lix.systems/lix-project/lix/issues/692
Fixes: https://git.lix.systems/lix-project/lix/issues/673
Fixes: https://github.com/NixOS/nix/issues/11359
Change-Id: I55e696c09794d2520b60238a84829c98fcad7ccc
This commit is contained in:
Jade Lovelace
2025-02-26 12:05:07 -08:00
parent 596ffc290e
commit 29f5ce07db
11 changed files with 56 additions and 12 deletions
+18
View File
@@ -0,0 +1,18 @@
---
synopsis: 'Flakes follow `--eval-system` where it makes sense'
issues: [fj#673, fj#692, gh#11359]
cls: [2657]
category: Fixes
credits: [jade]
---
Most flake commands now follow `--eval-system` when choosing attributes to build/evaluate/etc.
The exceptions are commands that actually run something on the local machine:
- nix develop
- nix run
- nix upgrade-nix
- nix fmt
- nix bundle
This is not a principled approach to cross compilation or anything, flakes still impede rather than support cross compilation, but this unbreaks many remote build use cases.
+4 -4
View File
@@ -185,8 +185,8 @@ MixReadOnlyOption::MixReadOnlyOption()
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
{
return {
"packages." + settings.thisSystem.get() + ".default",
"defaultPackage." + settings.thisSystem.get()
"packages." + evalSettings.getCurrentSystem() + ".default",
"defaultPackage." + evalSettings.getCurrentSystem()
};
}
@@ -195,10 +195,10 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
return {
// As a convenience, look for the attribute in
// 'outputs.packages'.
"packages." + settings.thisSystem.get() + ".",
"packages." + evalSettings.getCurrentSystem() + ".",
// As a temporary hack until Nixpkgs is properly converted
// to provide a clean 'packages' set, look in 'legacyPackages'.
"legacyPackages." + settings.thisSystem.get() + "."
"legacyPackages." + evalSettings.getCurrentSystem() + "."
};
}
+7 -3
View File
@@ -1,5 +1,6 @@
#include "lix/libcmd/installable-flake.hh"
#include "lix/libcmd/command.hh"
#include "lix/libexpr/eval-settings.hh"
#include "lix/libmain/common-args.hh"
#include "lix/libmain/shared.hh"
#include "lix/libstore/store-api.hh"
@@ -54,9 +55,10 @@ struct CmdBundle : InstallableCommand
// FIXME: cut&paste from CmdRun.
Strings getDefaultFlakeAttrPaths() override
{
// eval-system, since the app could be remote built and then bundled locally
Strings res{
"apps." + settings.thisSystem.get() + ".default",
"defaultApp." + settings.thisSystem.get()
"apps." + evalSettings.getCurrentSystem() + ".default",
"defaultApp." + evalSettings.getCurrentSystem()
};
for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths())
res.push_back(s);
@@ -65,7 +67,8 @@ struct CmdBundle : InstallableCommand
Strings getDefaultFlakeAttrPathPrefixes() override
{
Strings res{"apps." + settings.thisSystem.get() + "."};
// eval-system, since the app could be remote built and then bundled locally
Strings res{"apps." + evalSettings.getCurrentSystem() + "."};
for (auto & s : SourceExprCommand::getDefaultFlakeAttrPathPrefixes())
res.push_back(s);
return res;
@@ -82,6 +85,7 @@ struct CmdBundle : InstallableCommand
auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] = parseFlakeRefWithFragmentAndExtendedOutputsSpec(bundler, absPath("."));
const flake::LockFlags lockFlags{ .writeLockFile = false };
// Current system, since it needs to run locally
InstallableFlake bundler{this,
evaluator, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec),
{"bundlers." + settings.thisSystem.get() + ".default",
+2
View File
@@ -427,6 +427,7 @@ struct Common : InstallableCommand, MixProfile
Strings getDefaultFlakeAttrPaths() override
{
// These are current system since they have to run locally from inside the shell
Strings paths{
"devShells." + settings.thisSystem.get() + ".default",
"devShell." + settings.thisSystem.get(),
@@ -621,6 +622,7 @@ struct CmdDevelop : Common, MixEnvironment
"bashInteractive",
ExtendedOutputsSpec::Default(),
Strings{},
// `system` not `eval-system` since we are actually executing it on the local machine
Strings{"legacyPackages." + settings.thisSystem.get() + "."},
nixpkgsLockFlags);
+3 -3
View File
@@ -365,7 +365,7 @@ struct CmdFlakeCheck : FlakeCommand
lockFlags.applyNixConfig = true;
auto flake = lockFlake(*state);
auto localSystem = std::string(settings.thisSystem.get());
auto localSystem = std::string(evalSettings.getCurrentSystem());
bool hasErrors = false;
auto reportError = [&](const Error & e) {
@@ -613,7 +613,7 @@ struct CmdFlakeCheck : FlakeCommand
auto drvPath = checkDerivation(
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
*attr2.value, attr2.pos);
if (drvPath && attr_name == settings.thisSystem.get()) {
if (drvPath && attr_name == evalSettings.getCurrentSystem()) {
drvPaths.push_back(DerivedPath::Built {
.drvPath = makeConstantStorePathRef(*drvPath),
.outputs = OutputsSpec::All { },
@@ -1129,7 +1129,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
auto evaluator = getEvaluator();
auto state = evaluator->begin(aio());
auto flake = std::make_shared<LockedFlake>(lockFlake(*state));
auto localSystem = std::string(settings.thisSystem.get());
auto localSystem = std::string(evalSettings.getCurrentSystem());
std::function<bool(
eval_cache::AttrCursor & visitor,
+1
View File
@@ -22,6 +22,7 @@ struct CmdFmt : SourceExprCommand {
Category category() override { return catSecondary; }
Strings getDefaultFlakeAttrPaths() override {
// We are running it locally so it should be the actual system
return Strings{"formatter." + settings.thisSystem.get()};
}
+2
View File
@@ -188,6 +188,7 @@ struct CmdRun : InstallableCommand
Strings getDefaultFlakeAttrPaths() override
{
// We are running it locally so it should be the actual system
Strings res{
"apps." + settings.thisSystem.get() + ".default",
"defaultApp." + settings.thisSystem.get(),
@@ -199,6 +200,7 @@ struct CmdRun : InstallableCommand
Strings getDefaultFlakeAttrPathPrefixes() override
{
// We are running it locally so it should be the actual system
Strings res{"apps." + settings.thisSystem.get() + "."};
for (auto & s : SourceExprCommand::getDefaultFlakeAttrPathPrefixes())
res.push_back(s);
+2 -2
View File
@@ -57,8 +57,8 @@ struct CmdSearch : InstallableCommand, MixJSON
Strings getDefaultFlakeAttrPaths() override
{
return {
"packages." + settings.thisSystem.get(),
"legacyPackages." + settings.thisSystem.get()
"packages." + evalSettings.getCurrentSystem(),
"legacyPackages." + evalSettings.getCurrentSystem()
};
}
+5
View File
@@ -107,6 +107,11 @@ cat > $flakeDir/flake.nix <<EOF
EOF
nix flake check $flakeDir
# --eval-system should be considered for which the local system is for flake
# purposes, and thus it should fail checking that attr
(! nix flake check --eval-system system-1 $flakeDir)
# likewise with --system
(! nix flake check --system system-1 $flakeDir)
checkRes=$(nix flake check --all-systems --keep-going $flakeDir 2>&1 && fail "nix flake check --all-systems should have failed" || true)
echo "$checkRes" | grepQuiet "packages.system-1.default"
+5
View File
@@ -126,6 +126,11 @@ nix build -o $TEST_ROOT/result git+file://$flake1Dir
nix build -o $flake1Dir/result git+file://$flake1Dir
nix path-info $flake1Dir/result
# Ensure that eval-system affects the chosen attribute
cp -r "$flake1Dir" "$flake1Dir.kittified"
sed -i "s#$system#kitty-kitty#" "$flake1Dir.kittified/flake.nix"
nix build --eval-system kitty-kitty "$flake1Dir.kittified"
# 'getFlake' on an unlocked flakeref should fail in pure mode, but
# succeed in impure mode.
(! nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default")
+7
View File
@@ -7,6 +7,8 @@ writeSimpleFlake "$flakeDir"
cd "$flakeDir"
# FIXME(jade): the following is rather absurd. we have jq!
# By default: Only show the packages content for the current system and no
# legacyPackages at all
nix flake show --json > show-output.json
@@ -19,6 +21,11 @@ assert show_output.legacyPackages.${builtins.currentSystem} == {};
true
'
# Follow --eval-system for determining the system for flakes
nix flake show --eval-system someOtherSystem --json > show-output.json
drvTitle=$(jq -r '.packages.someOtherSystem.default.name' show-output.json)
[[ $drvTitle == 'simple' ]]
# With `--all-systems`, show the packages for all systems
nix flake show --json --all-systems > show-output.json
nix eval --impure --expr '