1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-13 17:10:47 +02:00

build-cores: detect cores automatically if set to 0

This changes makes nix detect a machines available cores automatically whenever build-cores is set to 0.

So far, nix simply passed NIX_BUILD_CORES=0 whenever build-cores is set to 0. (only when build-cores is unset it was detecting cores automatically)

The behavior of passing NIX_BUILD_CORES=0 leads to a performance penalty when sourcing nixpkgs' generic builder's `setup.sh`, as setup.sh has to execute `nproc`. This significantly slows down sourcing of setup.sh
This commit is contained in:
DavHau 2025-06-27 15:35:46 +07:00
parent df2d5f276a
commit fb5e22e318
8 changed files with 58 additions and 10 deletions

View file

@ -0,0 +1,6 @@
---
synopsis: "`build-cores = 0` now auto-detects CPU cores"
prs: [13402]
---
When `build-cores` is set to `0`, nix now automatically detects the number of available CPU cores and passes this value via `NIX_BUILD_CORES`, instead of passing `0` directly. This matches the behavior when `build-cores` is unset. This prevents the builder from having to detect the number of cores.

View file

@ -140,7 +140,7 @@ std::vector<Path> getUserConfigFiles()
return files;
}
unsigned int Settings::getDefaultCores()
unsigned int Settings::getDefaultCores() const
{
const unsigned int concurrency = std::max(1U, std::thread::hardware_concurrency());
const unsigned int maxCPU = getMaxCPU();

View file

@ -43,8 +43,6 @@ const uint32_t maxIdsPerBuild =
class Settings : public Config {
unsigned int getDefaultCores();
StringSet getDefaultSystemFeatures();
StringSet getDefaultExtraPlatforms();
@ -57,6 +55,8 @@ public:
Settings();
unsigned int getDefaultCores() const;
Path nixPrefix;
/**
@ -153,7 +153,7 @@ public:
Setting<unsigned int> buildCores{
this,
getDefaultCores(),
0,
"cores",
R"(
Sets the value of the `NIX_BUILD_CORES` environment variable in the [invocation of the `builder` executable](@docroot@/language/derivations.md#builder-execution) of a derivation.
@ -166,15 +166,13 @@ public:
-->
For instance, in Nixpkgs, if the attribute `enableParallelBuilding` for the `mkDerivation` build helper is set to `true`, it passes the `-j${NIX_BUILD_CORES}` flag to GNU Make.
The value `0` means that the `builder` should use all available CPU cores in the system.
If set to `0`, nix will detect the number of CPU cores and pass this number via NIX_BUILD_CORES.
> **Note**
>
> The number of parallel local Nix build jobs is independently controlled with the [`max-jobs`](#conf-max-jobs) setting.
)",
{"build-cores"},
// Don't document the machine-specific default value
false};
{"build-cores"}};
/**
* Read-only mode. Don't copy stuff to the store, don't change

View file

@ -1083,7 +1083,7 @@ void DerivationBuilderImpl::initEnv()
env["NIX_STORE"] = store.storeDir;
/* The maximum number of cores to utilize for parallel building. */
env["NIX_BUILD_CORES"] = fmt("%d", settings.buildCores);
env["NIX_BUILD_CORES"] = fmt("%d", settings.buildCores ? settings.buildCores : settings.getDefaultCores());
/* In non-structured mode, set all bindings either directory in the
environment or via a file, as specified by

View file

@ -542,7 +542,7 @@ static void main_nix_build(int argc, char * * argv)
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path().string();
env["NIX_STORE"] = store->storeDir;
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);
env["NIX_BUILD_CORES"] = fmt("%d", settings.buildCores ? settings.buildCores : settings.getDefaultCores());
auto parsedDrv = StructuredAttrs::tryParse(drv.env);
DerivationOptions drvOptions;

View file

@ -0,0 +1,11 @@
with import ./config.nix;
{
# Test derivation that checks the NIX_BUILD_CORES environment variable
testCores = mkDerivation {
name = "test-build-cores";
buildCommand = ''
echo "$NIX_BUILD_CORES" > $out
'';
};
}

32
tests/functional/build-cores.sh Executable file
View file

@ -0,0 +1,32 @@
#!/usr/bin/env bash
source common.sh
clearStoreIfPossible
echo "Testing build-cores configuration behavior..."
# Test 1: When build-cores is set to a non-zero value, NIX_BUILD_CORES should have that value
echo "Testing build-cores=4..."
rm -f "$TEST_ROOT"/build-cores-output
nix-build --cores 4 build-cores.nix -A testCores -o "$TEST_ROOT"/build-cores-output
result=$(cat "$(readlink "$TEST_ROOT"/build-cores-output)")
if [[ "$result" != "4" ]]; then
echo "FAIL: Expected NIX_BUILD_CORES=4, got $result"
exit 1
fi
echo "PASS: build-cores=4 correctly sets NIX_BUILD_CORES=4"
rm -f "$TEST_ROOT"/build-cores-output
# Test 2: When build-cores is set to 0, NIX_BUILD_CORES should be resolved to getDefaultCores()
echo "Testing build-cores=0..."
nix-build --cores 0 build-cores.nix -A testCores -o "$TEST_ROOT"/build-cores-output
result=$(cat "$(readlink "$TEST_ROOT"/build-cores-output)")
if [[ "$result" == "0" ]]; then
echo "FAIL: NIX_BUILD_CORES should not be 0 when build-cores=0"
exit 1
fi
echo "PASS: build-cores=0 resolves to NIX_BUILD_CORES=$result (should be > 0)"
rm -f "$TEST_ROOT"/build-cores-output
echo "All build-cores tests passed!"

View file

@ -145,6 +145,7 @@ suites = [
'placeholders.sh',
'ssh-relay.sh',
'build.sh',
'build-cores.sh',
'build-delete.sh',
'output-normalization.sh',
'selfref-gc.sh',