Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(libstore): add page size system feature #26

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
12 changes: 12 additions & 0 deletions doc/manual/source/language/advanced-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,18 @@ Derivations can declare some infrequently used optional attributes.

ensures that the derivation can only be built on a machine with the `kvm` feature.

- [`rejectSystemFeatures`]{#adv-attr-rejectSystemFeatures}\

If a derivation has the `rejectSystemFeatures` attribute, then Nix will only build it on a machine that does not have the corresponding features set in its [`system-features` configuration](@docroot@/command-ref/conf-file.md#conf-system-features).

For example, setting

```nix
rejectSystemFeatures = [ "pages-16k" ];
```

ensures that the derivation can only be built on a machine which does not have the `pages-16k` feature.

[xp-feature-ca-derivations]: @docroot@/development/experimental-features.md#xp-feature-ca-derivations
[xp-feature-dynamic-derivations]: @docroot@/development/experimental-features.md#xp-feature-dynamic-derivations
[xp-feature-git-hashing]: @docroot@/development/experimental-features.md#xp-feature-git-hashing
12 changes: 12 additions & 0 deletions src/libstore/derivation-options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ DerivationOptions DerivationOptions::fromParsedDerivation(const ParsedDerivation
.allowLocalNetworking = parsed.getBoolAttr("__darwinAllowLocalNetworking", defaults.allowLocalNetworking),
.requiredSystemFeatures =
parsed.getStringSetAttr("requiredSystemFeatures").value_or(defaults.requiredSystemFeatures),
.rejectSystemFeatures = parsed.getStringSetAttr("rejectSystemFeatures").value_or(defaults.rejectSystemFeatures),
.preferLocalBuild = parsed.getBoolAttr("preferLocalBuild", defaults.preferLocalBuild),
.allowSubstitutes = parsed.getBoolAttr("allowSubstitutes", defaults.allowSubstitutes),
};
Expand All @@ -150,6 +151,15 @@ StringSet DerivationOptions::getRequiredSystemFeatures(const BasicDerivation & d
return res;
}

StringSet DerivationOptions::getRejectSystemFeatures(const BasicDerivation & drv) const
{
// FIXME: cache this?
StringSet res;
for (auto & i : rejectSystemFeatures)
res.insert(i);
return res;
}

bool DerivationOptions::canBuildLocally(Store & localStore, const BasicDerivation & drv) const
{
if (drv.platform != settings.thisSystem.get() && !settings.extraPlatforms.get().count(drv.platform)
Expand Down Expand Up @@ -215,6 +225,7 @@ DerivationOptions adl_serializer<DerivationOptions>::from_json(const json & json
.allowLocalNetworking = getBoolean(valueAt(json, "allowLocalNetworking")),

.requiredSystemFeatures = getStringSet(valueAt(json, "requiredSystemFeatures")),
.rejectSystemFeatures = getStringSet(valueAt(json, "rejectSystemFeatures")),
.preferLocalBuild = getBoolean(valueAt(json, "preferLocalBuild")),
.allowSubstitutes = getBoolean(valueAt(json, "allowSubstitutes")),
};
Expand Down Expand Up @@ -247,6 +258,7 @@ void adl_serializer<DerivationOptions>::to_json(json & json, DerivationOptions o
json["allowLocalNetworking"] = o.allowLocalNetworking;

json["requiredSystemFeatures"] = o.requiredSystemFeatures;
json["rejectSystemFeatures"] = o.rejectSystemFeatures;
json["preferLocalBuild"] = o.preferLocalBuild;
json["allowSubstitutes"] = o.allowSubstitutes;
}
Expand Down
10 changes: 10 additions & 0 deletions src/libstore/derivation-options.hh
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ struct DerivationOptions
*/
StringSet requiredSystemFeatures = {};

/**
* env: rejectSystemFeatures
*/
StringSet rejectSystemFeatures = {};

/**
* env: preferLocalBuild
*/
Expand Down Expand Up @@ -161,6 +166,11 @@ struct DerivationOptions
*/
StringSet getRequiredSystemFeatures(const BasicDerivation & drv) const;

/**
* @param drv See note on `getRequiredSystemFeatures`
*/
StringSet getRejectSystemFeatures(const BasicDerivation & drv) const;

/**
* @param drv See note on `getRequiredSystemFeatures`
*/
Expand Down
10 changes: 10 additions & 0 deletions src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ static bool hasVirt() {
}
#endif

extern "C" const char** nix_libstore_get_default_system_features();

StringSet Settings::getDefaultSystemFeatures()
{
/* For backwards compatibility, accept some "features" that are
Expand All @@ -195,6 +197,14 @@ StringSet Settings::getDefaultSystemFeatures()
features.insert("apple-virt");
#endif

const char** value = nix_libstore_get_default_system_features();
if (value != nullptr) {
for (size_t i = 0; value[i] != nullptr; i++) {
features.insert(value[i]);
}
}
free(value);

return features;
}

Expand Down
2 changes: 1 addition & 1 deletion src/libstore/globals.hh
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ public:

6. A comma-separated list of supported [system features](#conf-system-features).

A machine will only be used to build a derivation if all the features in the derivation's [`requiredSystemFeatures`](@docroot@/language/advanced-attributes.html#adv-attr-requiredSystemFeatures) attribute are supported by that machine.
A machine will only be used to build a derivation if all the features in the derivation's [`requiredSystemFeatures`](@docroot@/language/advanced-attributes.html#adv-attr-requiredSystemFeatures) attribute are supported by that machine and does not have any features in [`rejectSystemFeatures`](@docroot@/language/advanced-attributes.html#adv-attr-rejectSystemFeatures).

7. A comma-separated list of required [system features](#conf-system-features).

Expand Down
23 changes: 23 additions & 0 deletions src/libstore/globals.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const std = @import("std");

pub fn getDefaultSystemFeatures() callconv(.C) ?[*:null]const ?[*:0]const u8 {
var list = std.ArrayList(?[*:0]const u8).init(std.heap.c_allocator);
defer list.deinit();

const pgsize = std.heap.pageSize();

if (pgsize == std.heap.page_size_max) {
list.append(std.fmt.allocPrintZ(std.heap.c_allocator, "pages-{d}k", .{pgsize / 1024}) catch return null) catch return null;
} else {
var i = pgsize;
while (i < std.heap.page_size_max) : (i *= 2) {
list.append(std.fmt.allocPrintZ(std.heap.c_allocator, "pages-{d}k", .{i / 1024}) catch return null) catch return null;
}
}

return list.toOwnedSliceSentinel(null) catch return null;
}

comptime {
@export(&getDefaultSystemFeatures, .{ .name = "nix_libstore_get_default_system_features" });
}
5 changes: 5 additions & 0 deletions src/libstore/libstore.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub const globals = @import("globals.zig");

comptime {
_ = globals;
}
16 changes: 15 additions & 1 deletion src/libstore/meson.build
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
project('nix-store', 'cpp',
project('nix-store', 'cpp', 'c',
version : files('.zix-version'),
default_options : [
'cpp_std=c++2a',
Expand Down Expand Up @@ -132,6 +132,8 @@ if aws_s3.found()
endif
deps_other += aws_s3

subdir('nix-meson-build-support/zig')

subdir('nix-meson-build-support/generate-header')

generated_headers = []
Expand Down Expand Up @@ -424,6 +426,18 @@ endforeach
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')

sources += custom_target(
'zig build-lib',
command: [zig, 'build-lib', '-femit-h=@OUTDIR@/libstore-zig.h', '-femit-bin=@OUTPUT@', '-ofmt=c', '-lc', zig_args, '@INPUT@'],
output: 'libstore-zig.c',
input: 'libstore.zig',
depend_files: [
'globals.zig',
],
)

include_dirs += fs.parent(fs.parent(zig.full_path())) / 'lib' / 'zig'

this_library = library(
'nixstore',
generated_headers,
Expand Down
1 change: 1 addition & 0 deletions src/libstore/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mkMesonLibrary (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "sb") ./.)
(fileset.fileFilter (file: file.hasExt "md") ./.)
(fileset.fileFilter (file: file.hasExt "sql") ./.)
(fileset.fileFilter (file: file.hasExt "zig") ./.)
];

nativeBuildInputs = lib.optional embeddedSandboxShell unixtools.hexdump;
Expand Down
3 changes: 2 additions & 1 deletion src/libstore/unix/build/local-derivation-goal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,10 @@ void LocalDerivationGoal::startBuilder()
if (drv->platform == "x86_64-darwin" && settings.thisSystem == "aarch64-darwin") {
throw Error("run `/usr/sbin/softwareupdate --install-rosetta` to enable your %s to run programs for %s", settings.thisSystem, drv->platform);
} else {
throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}",
throw Error("a '%s' with features {%s} & not {%s} is required to build '%s', but I am a '%s' with features {%s}",
drv->platform,
concatStringsSep(", ", drvOptions->getRequiredSystemFeatures(*drv)),
concatStringsSep(", ", drvOptions->getRejectSystemFeatures(*drv)),
worker.store.printStorePath(drvPath),
settings.thisSystem,
concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
Expand Down
21 changes: 20 additions & 1 deletion tests/functional/build-hook.nix
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,31 @@ let
requiredSystemFeatures = [ "baz" ];
};

input4 = mkDerivation {
shell = busybox;
name = "build-remote-input-4";
buildCommand = ''
echo hi-input3
read x < ${input3}
echo $x BAZ > $out
'';
rejectSystemFeatures = [ "bar" ];
requiredSystemFeatures = [ "foo" ];
};

in

mkDerivation {
shell = busybox;
name = "build-remote";
passthru = { inherit input1 input2 input3; };
passthru = {
inherit
input1
input2
input3
input4
;
};
buildCommand = ''
read x < ${input1}
read y < ${input3}
Expand Down
7 changes: 7 additions & 0 deletions tests/functional/build-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ builders=(
"ssh://localhost?remote-store=$TEST_ROOT/machine1?system-features=$(join_by "%20" foo "${EXTRA_SYSTEM_FEATURES[@]}") - - 1 1 $(join_by "," foo "${EXTRA_SYSTEM_FEATURES[@]}")"
"$TEST_ROOT/machine2 - - 1 1 $(join_by "," bar "${EXTRA_SYSTEM_FEATURES[@]}")"
"ssh-ng://localhost?remote-store=$TEST_ROOT/machine3?system-features=$(join_by "%20" baz "${EXTRA_SYSTEM_FEATURES[@]}") - - 1 1 $(join_by "," baz "${EXTRA_SYSTEM_FEATURES[@]}")"
"$TEST_ROOT/machine4 - - 1 1 $(join_by "," bar foo "${EXTRA_SYSTEM_FEATURES[@]}")"
)

chmod -R +w "$TEST_ROOT/machine"* || true
Expand Down Expand Up @@ -70,6 +71,12 @@ echo "$output" | grepQuietInverse builder-build-remote-input-2.sh
echo "$output" | grepQuiet builder-build-remote-input-3.sh
unset output

# Ensure that input4 was built on store4 due to the required feature.
output=$(nix path-info --store "$TEST_ROOT/machine4" --all)
echo "$output" | grepQuietInverse builder-build-remote-input-1.sh
echo "$output" | grepQuietInverse builder-build-remote-input-2.sh
echo "$output" | grepQuietInverse builder-build-remote-input-3.sh
unset output

for i in input1 input3; do
nix log --store "$TEST_ROOT/machine0" --file "$file" --arg busybox "$busybox" "passthru.$i" | grep hi-$i
Expand Down
Loading