aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-03-04 07:21:01 +0100
committereldritch horrors <pennae@lix.systems>2024-03-04 07:21:01 +0100
commit7614aa97975f3e6e36b6ffbd9fec34462021ab39 (patch)
treeebb2521607d7b5a30fadcc13e0af889159d5af2e
parent64a269ef73b111d49037812bd899b5cb883158ef (diff)
Merge pull request #4093 from matthewbauer/eval-system
Add eval-system option (cherry picked from commit 071dbbee33af9f27338c3e53e4ea067dbfa14010) Change-Id: Ia81358c8cfb60241da07a4d0e84b9ee62a18a53f
-rw-r--r--doc/manual/rl-next/eval-system.md12
-rw-r--r--src/libexpr/eval-settings.cc6
-rw-r--r--src/libexpr/eval-settings.hh20
-rw-r--r--src/libexpr/primops.cc11
-rw-r--r--src/libstore/globals.hh6
-rw-r--r--tests/functional/impure-eval.sh35
-rw-r--r--tests/functional/local.mk1
-rw-r--r--tests/unit/libexpr/primops.cc4
8 files changed, 89 insertions, 6 deletions
diff --git a/doc/manual/rl-next/eval-system.md b/doc/manual/rl-next/eval-system.md
new file mode 100644
index 000000000..a4696a56c
--- /dev/null
+++ b/doc/manual/rl-next/eval-system.md
@@ -0,0 +1,12 @@
+---
+synopsis: Add new `eval-system` setting
+prs: 4093
+---
+
+Add a new `eval-system` option.
+Unlike `system`, it just overrides the value of `builtins.currentSystem`.
+This is more useful than overriding `system`, because you can build these derivations on remote builders which can work on the given system.
+In contrast, `system` also effects scheduling which will cause Nix to build those derivations locally even if that doesn't make sense.
+
+`eval-system` only takes effect if it is non-empty.
+If empty (the default) `system` is used as before, so there is no breakage.
diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc
index 93b4a5289..89ca198d8 100644
--- a/src/libexpr/eval-settings.cc
+++ b/src/libexpr/eval-settings.cc
@@ -88,6 +88,12 @@ std::string EvalSettings::resolvePseudoUrl(std::string_view url)
return std::string(url);
}
+const std::string & EvalSettings::getCurrentSystem()
+{
+ const auto & evalSystem = currentSystem.get();
+ return evalSystem != "" ? evalSystem : settings.thisSystem.get();
+}
+
EvalSettings evalSettings;
static GlobalConfig::Register rEvalSettings(&evalSettings);
diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh
index 19122bc31..049f42e70 100644
--- a/src/libexpr/eval-settings.hh
+++ b/src/libexpr/eval-settings.hh
@@ -25,6 +25,26 @@ struct EvalSettings : Config
[`builtins.nixPath`](@docroot@/language/builtin-constants.md#builtins-nixPath).
)"};
+ Setting<std::string> currentSystem{
+ this, "", "eval-system",
+ R"(
+ This option defines
+ [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem)
+ in the Nix language if it is set as a non-empty string.
+ Otherwise, if it is defined as the empty string (the default), the value of the
+ [`system` ](#conf-system)
+ configuration setting is used instead.
+
+ Unlike `system`, this setting does not change what kind of derivations can be built locally.
+ This is useful for evaluating Nix code on one system to produce derivations to be built on another type of system.
+ )"};
+
+ /**
+ * Implements the `eval-system` vs `system` defaulting logic
+ * described for `eval-system`.
+ */
+ const std::string & getCurrentSystem();
+
Setting<bool> restrictEval{
this, false, "restrict-eval",
R"(
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index b906e7747..005a38319 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -4288,13 +4288,16 @@ void EvalState::createBaseEnv()
.impureOnly = true,
});
- if (!evalSettings.pureEval) {
- v.mkString(settings.thisSystem.get());
- }
+ if (!evalSettings.pureEval)
+ v.mkString(evalSettings.getCurrentSystem());
addConstant("__currentSystem", v, {
.type = nString,
.doc = R"(
- The value of the [`system` configuration option](@docroot@/command-ref/conf-file.md#conf-pure-eval).
+ The value of the
+ [`eval-system`](@docroot@/command-ref/conf-file.md#conf-eval-system)
+ or else
+ [`system`](@docroot@/command-ref/conf-file.md#conf-system)
+ configuration option.
It can be used to set the `system` attribute for [`builtins.derivation`](@docroot@/language/derivations.md) such that the resulting derivation can be built on the same system that evaluates the Nix expression:
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 229f1a96a..1fb9ec746 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -210,7 +210,11 @@ public:
In general, you do not have to modify this setting.
While you can force Nix to run a Darwin-specific `builder` executable on a Linux machine, the result would obviously be wrong.
- This value is available in the Nix language as [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem).
+ This value is available in the Nix language as
+ [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem)
+ if the
+ [`eval-system`](#conf-eval-system)
+ configuration option is set as the empty string.
)"};
Setting<time_t> maxSilentTime{
diff --git a/tests/functional/impure-eval.sh b/tests/functional/impure-eval.sh
new file mode 100644
index 000000000..6c72f01d7
--- /dev/null
+++ b/tests/functional/impure-eval.sh
@@ -0,0 +1,35 @@
+source common.sh
+
+export REMOTE_STORE="dummy://"
+
+simpleTest () {
+ local expr=$1; shift
+ local result=$1; shift
+ # rest, extra args
+
+ [[ "$(nix eval --impure --raw "$@" --expr "$expr")" == "$result" ]]
+}
+
+# `builtins.storeDir`
+
+## Store dir follows `store` store setting
+simpleTest 'builtins.storeDir' '/foo' --store "$REMOTE_STORE?store=/foo"
+simpleTest 'builtins.storeDir' '/bar' --store "$REMOTE_STORE?store=/bar"
+
+# `builtins.currentSystem`
+
+## `system` alone affects by default
+simpleTest 'builtins.currentSystem' 'foo' --system 'foo'
+simpleTest 'builtins.currentSystem' 'bar' --system 'bar'
+
+## `system` affects if `eval-system` is an empty string
+simpleTest 'builtins.currentSystem' 'foo' --system 'foo' --eval-system ''
+simpleTest 'builtins.currentSystem' 'bar' --system 'bar' --eval-system ''
+
+## `eval-system` alone affects
+simpleTest 'builtins.currentSystem' 'foo' --eval-system 'foo'
+simpleTest 'builtins.currentSystem' 'bar' --eval-system 'bar'
+
+## `eval-system` overrides `system`
+simpleTest 'builtins.currentSystem' 'bar' --system 'foo' --eval-system 'bar'
+simpleTest 'builtins.currentSystem' 'baz' --system 'foo' --eval-system 'baz'
diff --git a/tests/functional/local.mk b/tests/functional/local.mk
index 6b79020fc..9d69c925b 100644
--- a/tests/functional/local.mk
+++ b/tests/functional/local.mk
@@ -68,6 +68,7 @@ nix_tests = \
build-remote-trustless-should-pass-3.sh \
build-remote-trustless-should-fail-0.sh \
nar-access.sh \
+ impure-eval.sh \
pure-eval.sh \
eval.sh \
repl.sh \
diff --git a/tests/unit/libexpr/primops.cc b/tests/unit/libexpr/primops.cc
index ce3b5d11f..71e838b32 100644
--- a/tests/unit/libexpr/primops.cc
+++ b/tests/unit/libexpr/primops.cc
@@ -1,6 +1,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "eval-settings.hh"
+
#include "tests/libexpr.hh"
namespace nix {
@@ -614,7 +616,7 @@ namespace nix {
TEST_F(PrimOpTest, currentSystem) {
auto v = eval("builtins.currentSystem");
- ASSERT_THAT(v, IsStringEq(settings.thisSystem.get()));
+ ASSERT_THAT(v, IsStringEq(evalSettings.getCurrentSystem()));
}
TEST_F(PrimOpTest, derivation) {