Merge branch 'yusdacra/fix-nix-build-tag-bug' into 'master'

Improve Nix build files (yet again!)

See merge request veloren/veloren!1571
This commit is contained in:
Marcel 2020-11-30 21:50:15 +00:00
commit e06dd3fe7e
13 changed files with 663 additions and 465 deletions

1
.gitignore vendored
View File

@ -42,6 +42,7 @@ userdata
*.sqlite-shm
# direnv
/.direnv
/.envrc
*.bat

View File

@ -1 +0,0 @@
use nix

View File

@ -2,23 +2,27 @@
# "generate" "-f" "../Cargo.toml"
# See https://github.com/kolloch/crate2nix for more info.
{ nixpkgs ? <nixpkgs>, pkgs ? import nixpkgs { config = { }; }, lib ? pkgs.lib
, stdenv ? pkgs.stdenv, buildRustCrate ? pkgs.buildRustCrate
{ nixpkgs ? <nixpkgs>
, pkgs ? import nixpkgs { config = { }; }
, lib ? pkgs.lib
, stdenv ? pkgs.stdenv
, buildRustCrate ? pkgs.buildRustCrate
# This is used as the `crateOverrides` argument for `buildRustCrate`.
, defaultCrateOverrides ? pkgs.defaultCrateOverrides
# The features to enable for the root_crate or the workspace_members.
, rootFeatures ? [
"default"
]
# If true, throw errors instead of issueing deprecation warnings.
"default"
]
# If true, throw errors instead of issueing deprecation warnings.
, strictDeprecation ? false
# Whether to perform release builds: longer compile times, faster binaries.
, release ? true
# Additional crate2nix configuration if it exists.
, crateConfig ? if builtins.pathExists ./crate-config.nix then
pkgs.callPackage ./crate-config.nix { }
else
{ } }:
pkgs.callPackage ./crate-config.nix { }
else
{ }
}:
rec {
#
@ -125,8 +129,9 @@ rec {
# A derivation that joins the outputs of all workspace members together.
allWorkspaceMembers = pkgs.symlinkJoin {
name = "all-workspace-members";
paths = let members = builtins.attrValues workspaceMembers;
in builtins.map (m: m.build) members;
paths =
let members = builtins.attrValues workspaceMembers;
in builtins.map (m: m.build) members;
};
#
@ -2258,18 +2263,22 @@ rec {
packageId = "smithay-clipboard 0.6.1";
optional = true;
target = { target, features }:
(target."unix" && (!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "ios")
|| (target."os" == "emscripten"))));
(target."unix" && (
!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "ios")
|| (target."os" == "emscripten"))
));
}
{
name = "x11-clipboard";
packageId = "x11-clipboard";
optional = true;
target = { target, features }:
(target."unix" && (!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "ios")
|| (target."os" == "emscripten"))));
(target."unix" && (
!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "ios")
|| (target."os" == "emscripten"))
));
}
];
features = {
@ -10167,7 +10176,7 @@ rec {
target = { target, features }:
(((target."arch" == "aarch64") || (target."arch" == "arm")
|| (target."arch" == "x86") || (target."arch" == "x86_64"))
&& (!(target."os" == "ios")));
&& (!(target."os" == "ios")));
}
{
name = "untrusted";
@ -16391,17 +16400,21 @@ rec {
name = "clipboard_wayland";
packageId = "clipboard_wayland";
target = { target, features }:
(target."unix" && (!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "emscripten")
|| (target."os" == "ios"))));
(target."unix" && (
!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "emscripten")
|| (target."os" == "ios"))
));
}
{
name = "clipboard_x11";
packageId = "clipboard_x11";
target = { target, features }:
(target."unix" && (!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "emscripten")
|| (target."os" == "ios"))));
(target."unix" && (
!((target."os" == "macos")
|| (target."os" == "android") || (target."os" == "emscripten")
|| (target."os" == "ios"))
));
}
{
name = "raw-window-handle";
@ -16817,18 +16830,20 @@ rec {
# This doesn't appear to be officially documented anywhere yet.
# See https://github.com/rust-lang-nursery/rust-forge/issues/101.
os = if stdenv.hostPlatform.isDarwin then
"macos"
else
stdenv.hostPlatform.parsed.kernel.name;
os =
if stdenv.hostPlatform.isDarwin then
"macos"
else
stdenv.hostPlatform.parsed.kernel.name;
arch = stdenv.hostPlatform.parsed.cpu.name;
family = "unix";
env = "gnu";
endian = if stdenv.hostPlatform.parsed.cpu.significantByte.name
== "littleEndian" then
"little"
else
"big";
endian =
if stdenv.hostPlatform.parsed.cpu.significantByte.name
== "littleEndian" then
"little"
else
"big";
pointer_width = toString stdenv.hostPlatform.parsed.cpu.bits;
vendor = stdenv.hostPlatform.parsed.vendor.name;
debug_assertions = false;
@ -16838,31 +16853,33 @@ rec {
# TODO(pkolloch): Substitute with gitignore filter
sourceFilter = name: type:
let baseName = builtins.baseNameOf (builtins.toString name);
in !(
# Filter out git
baseName == ".gitignore" || (type == "directory" && baseName == ".git")
in
!(
# Filter out git
baseName == ".gitignore" || (type == "directory" && baseName == ".git")
# Filter out build results
|| (type == "directory" && (baseName == "target" || baseName == "_site"
# Filter out build results
|| (type == "directory" && (baseName == "target" || baseName == "_site"
|| baseName == ".sass-cache" || baseName == ".jekyll-metadata"
|| baseName == "build-artifacts"))
# Filter out nix-build result symlinks
|| (type == "symlink" && lib.hasPrefix "result" baseName)
# Filter out nix-build result symlinks
|| (type == "symlink" && lib.hasPrefix "result" baseName)
# Filter out IDE config
|| (type == "directory"
# Filter out IDE config
|| (type == "directory"
&& (baseName == ".idea" || baseName == ".vscode"))
|| lib.hasSuffix ".iml" baseName
|| lib.hasSuffix ".iml" baseName
# Filter out nix build files
|| baseName == "Cargo.nix"
# Filter out nix build files
|| baseName == "Cargo.nix"
# Filter out editor backup / swap files.
|| lib.hasSuffix "~" baseName || builtins.match "^\\.sw[a-z]$$" baseName
!= null || builtins.match "^\\..*\\.sw[a-z]$$" baseName != null
|| lib.hasSuffix ".tmp" baseName || lib.hasSuffix ".bak" baseName
|| baseName == "tests.nix");
# Filter out editor backup / swap files.
|| lib.hasSuffix "~" baseName || builtins.match "^\\.sw[a-z]$$" baseName
!= null || builtins.match "^\\..*\\.sw[a-z]$$" baseName != null
|| lib.hasSuffix ".tmp" baseName || lib.hasSuffix ".bak" baseName
|| baseName == "tests.nix"
);
/* Returns a crate which depends on successful test execution
of crate given as the second argument.
@ -16878,42 +16895,46 @@ rec {
# building the actual lib and bin targets We just have to pass `--test`
# to rustc and it will do the right thing. We execute the tests and copy
# their log and the test executables to $out for later inspection.
test = let drv = testCrate.override (_: { buildTests = true; });
in pkgs.runCommand "run-tests-${testCrate.name}" {
inherit testCrateFlags;
buildInputs = testInputs;
} ''
set -ex
test =
let drv = testCrate.override (_: { buildTests = true; });
in
pkgs.runCommand "run-tests-${testCrate.name}"
{
inherit testCrateFlags;
buildInputs = testInputs;
} ''
set -ex
export RUST_BACKTRACE=1
export RUST_BACKTRACE=1
# recreate a file hierarchy as when running tests with cargo
# recreate a file hierarchy as when running tests with cargo
# the source for test data
${pkgs.xorg.lndir}/bin/lndir ${crate.src}
# the source for test data
${pkgs.xorg.lndir}/bin/lndir ${crate.src}
# build outputs
testRoot=target/debug
mkdir -p $testRoot
# build outputs
testRoot=target/debug
mkdir -p $testRoot
# executables of the crate
# we copy to prevent std::env::current_exe() to resolve to a store location
for i in ${crate}/bin/*; do
cp "$i" "$testRoot"
done
chmod +w -R .
# executables of the crate
# we copy to prevent std::env::current_exe() to resolve to a store location
for i in ${crate}/bin/*; do
cp "$i" "$testRoot"
done
chmod +w -R .
# test harness executables are suffixed with a hash, like cargo does
# this allows to prevent name collision with the main
# executables of the crate
hash=$(basename $out)
for file in ${drv}/tests/*; do
f=$testRoot/$(basename $file)-$hash
cp $file $f
$f $testCrateFlags 2>&1 | tee -a $out
done
'';
in crate.overrideAttrs (old: {
# test harness executables are suffixed with a hash, like cargo does
# this allows to prevent name collision with the main
# executables of the crate
hash=$(basename $out)
for file in ${drv}/tests/*; do
f=$testRoot/$(basename $file)-$hash
cp $file $f
$f $testCrateFlags 2>&1 | tee -a $out
done
'';
in
crate.overrideAttrs (old: {
checkPhase = ''
test -e ${test}
'';
@ -16921,21 +16942,28 @@ rec {
});
# A restricted overridable version of builtRustCratesWithFeatures.
buildRustCrateWithFeatures = { packageId, features ? rootFeatures
, crateOverrides ? defaultCrateOverrides, buildRustCrateFunc ? null
, runTests ? false, testCrateFlags ? [ ], testInputs ? [ ] }:
buildRustCrateWithFeatures =
{ packageId
, features ? rootFeatures
, crateOverrides ? defaultCrateOverrides
, buildRustCrateFunc ? null
, runTests ? false
, testCrateFlags ? [ ]
, testInputs ? [ ]
}:
lib.makeOverridable
({ features, crateOverrides, runTests, testCrateFlags, testInputs }:
({ features, crateOverrides, runTests, testCrateFlags, testInputs }:
let
buildRustCrateFuncOverriden = if buildRustCrateFunc != null then
buildRustCrateFunc
else
(if crateOverrides == pkgs.defaultCrateOverrides then
buildRustCrate
buildRustCrateFuncOverriden =
if buildRustCrateFunc != null then
buildRustCrateFunc
else
buildRustCrate.override {
defaultCrateOverrides = crateOverrides;
});
(if crateOverrides == pkgs.defaultCrateOverrides then
buildRustCrate
else
buildRustCrate.override {
defaultCrateOverrides = crateOverrides;
});
builtRustCrates = builtRustCratesWithFeatures {
inherit packageId features;
buildRustCrateFunc = buildRustCrateFuncOverriden;
@ -16948,115 +16976,132 @@ rec {
};
drv = builtRustCrates.${packageId};
testDrv = builtTestRustCrates.${packageId};
derivation = if runTests then
crateWithTest {
crate = drv;
testCrate = testDrv;
inherit testCrateFlags testInputs;
}
else
drv;
in derivation) {
derivation =
if runTests then
crateWithTest
{
crate = drv;
testCrate = testDrv;
inherit testCrateFlags testInputs;
}
else
drv;
in
derivation)
{
inherit features crateOverrides runTests testCrateFlags testInputs;
};
/* Returns an attr set with packageId mapped to the result of buildRustCrateFunc
for the corresponding crate.
*/
builtRustCratesWithFeatures = { packageId, features, crateConfigs ? crates
, buildRustCrateFunc, runTests, target ? defaultTarget }@args:
assert (builtins.isAttrs crateConfigs);
assert (builtins.isString packageId);
assert (builtins.isList features);
assert (builtins.isAttrs target);
assert (builtins.isBool runTests);
let
rootPackageId = packageId;
mergedFeatures = mergePackageFeatures (args // {
inherit rootPackageId;
target = target // { test = runTests; };
});
buildByPackageId = packageId: buildByPackageIdImpl packageId;
# Memoize built packages so that reappearing packages are only built once.
builtByPackageId =
lib.mapAttrs (packageId: value: buildByPackageId packageId)
crateConfigs;
buildByPackageIdImpl = packageId:
let
features = mergedFeatures."${packageId}" or [ ];
crateConfig' = crateConfigs."${packageId}";
crateConfig = builtins.removeAttrs crateConfig' [
"resolvedDefaultFeatures"
"devDependencies"
];
devDependencies =
lib.optionals (runTests && packageId == rootPackageId)
(crateConfig'.devDependencies or [ ]);
dependencies = dependencyDerivations {
inherit builtByPackageId features target;
dependencies = (crateConfig.dependencies or [ ])
++ devDependencies;
};
buildDependencies = dependencyDerivations {
inherit builtByPackageId features target;
dependencies = crateConfig.buildDependencies or [ ];
};
filterEnabledDependenciesForThis = dependencies:
filterEnabledDependencies {
inherit dependencies features target;
};
dependenciesWithRenames = lib.filter (d: d ? "rename")
(filterEnabledDependenciesForThis
((crateConfig.buildDependencies or [ ])
++ (crateConfig.dependencies or [ ]) ++ devDependencies));
# Crate renames have the form:
#
# {
# crate_name = [
# { version = "1.2.3"; rename = "crate_name01"; }
# ];
# # ...
# }
crateRenames = let
grouped = lib.groupBy (dependency: dependency.name)
dependenciesWithRenames;
versionAndRename = dep:
let package = builtByPackageId."${dep.packageId}";
in {
inherit (dep) rename;
version = package.version;
};
in lib.mapAttrs
(name: choices: builtins.map versionAndRename choices) grouped;
in buildRustCrateFunc (crateConfig // {
src = crateConfig.src or (pkgs.fetchurl rec {
name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz";
# https://www.pietroalbini.org/blog/downloading-crates-io/
# Not rate-limited, CDN URL.
url =
"https://static.crates.io/crates/${crateConfig.crateName}/${crateConfig.crateName}-${crateConfig.version}.crate";
sha256 = assert (lib.assertMsg (crateConfig ? sha256)
"Missing sha256 for ${name}");
crateConfig.sha256;
});
inherit features dependencies buildDependencies crateRenames
release;
builtRustCratesWithFeatures =
{ packageId
, features
, crateConfigs ? crates
, buildRustCrateFunc
, runTests
, target ? defaultTarget
}@args:
assert (builtins.isAttrs crateConfigs);
assert (builtins.isString packageId);
assert (builtins.isList features);
assert (builtins.isAttrs target);
assert (builtins.isBool runTests);
let
rootPackageId = packageId;
mergedFeatures = mergePackageFeatures (args // {
inherit rootPackageId;
target = target // { test = runTests; };
});
in builtByPackageId;
buildByPackageId = packageId: buildByPackageIdImpl packageId;
# Memoize built packages so that reappearing packages are only built once.
builtByPackageId =
lib.mapAttrs (packageId: value: buildByPackageId packageId)
crateConfigs;
buildByPackageIdImpl = packageId:
let
features = mergedFeatures."${packageId}" or [ ];
crateConfig' = crateConfigs."${packageId}";
crateConfig = builtins.removeAttrs crateConfig' [
"resolvedDefaultFeatures"
"devDependencies"
];
devDependencies =
lib.optionals (runTests && packageId == rootPackageId)
(crateConfig'.devDependencies or [ ]);
dependencies = dependencyDerivations {
inherit builtByPackageId features target;
dependencies = (crateConfig.dependencies or [ ])
++ devDependencies;
};
buildDependencies = dependencyDerivations {
inherit builtByPackageId features target;
dependencies = crateConfig.buildDependencies or [ ];
};
filterEnabledDependenciesForThis = dependencies:
filterEnabledDependencies {
inherit dependencies features target;
};
dependenciesWithRenames = lib.filter (d: d ? "rename")
(filterEnabledDependenciesForThis
((crateConfig.buildDependencies or [ ])
++ (crateConfig.dependencies or [ ]) ++ devDependencies));
# Crate renames have the form:
#
# {
# crate_name = [
# { version = "1.2.3"; rename = "crate_name01"; }
# ];
# # ...
# }
crateRenames =
let
grouped = lib.groupBy (dependency: dependency.name)
dependenciesWithRenames;
versionAndRename = dep:
let package = builtByPackageId."${dep.packageId}";
in
{
inherit (dep) rename;
version = package.version;
};
in
lib.mapAttrs
(name: choices: builtins.map versionAndRename choices)
grouped;
in
buildRustCrateFunc (crateConfig // {
src = crateConfig.src or (pkgs.fetchurl rec {
name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz";
# https://www.pietroalbini.org/blog/downloading-crates-io/
# Not rate-limited, CDN URL.
url =
"https://static.crates.io/crates/${crateConfig.crateName}/${crateConfig.crateName}-${crateConfig.version}.crate";
sha256 = assert (lib.assertMsg (crateConfig ? sha256)
"Missing sha256 for ${name}");
crateConfig.sha256;
});
inherit features dependencies buildDependencies crateRenames
release;
});
in
builtByPackageId;
# Returns the actual derivations for the given dependencies.
dependencyDerivations =
{ builtByPackageId, features, dependencies, target }:
assert (builtins.isAttrs builtByPackageId);
assert (builtins.isList features);
assert (builtins.isList dependencies);
assert (builtins.isAttrs target);
let
enabledDependencies =
filterEnabledDependencies { inherit dependencies features target; };
depDerivation = dependency: builtByPackageId.${dependency.packageId};
in map depDerivation enabledDependencies;
assert (builtins.isAttrs builtByPackageId);
assert (builtins.isList features);
assert (builtins.isList dependencies);
assert (builtins.isAttrs target);
let
enabledDependencies =
filterEnabledDependencies { inherit dependencies features target; };
depDerivation = dependency: builtByPackageId.${dependency.packageId};
in
map depDerivation enabledDependencies;
/* Returns a sanitized version of val with all values substituted that cannot
be serialized as JSON.
@ -17097,7 +17142,8 @@ rec {
diffedDefaultPackageFeatures =
diffDefaultPackageFeatures { inherit packageId target; };
};
in { internal = debug; };
in
{ internal = debug; };
/* Returns differences between cargo default features and crate2nix default
features.
@ -17120,10 +17166,13 @@ rec {
onlyInCrate2Nix = builtins.attrNames
(lib.filterAttrs (n: v: (v ? "crate2nix") && !(v ? "cargo"))
combined);
differentFeatures = lib.filterAttrs (n: v:
(v ? "crate2nix") && (v ? "cargo") && (v.crate2nix.features or [ ])
!= (v."cargo".resolved_default_features or [ ])) combined;
in builtins.toJSON {
differentFeatures = lib.filterAttrs
(n: v:
(v ? "crate2nix") && (v ? "cargo") && (v.crate2nix.features or [ ])
!= (v."cargo".resolved_default_features or [ ]))
combined;
in
builtins.toJSON {
inherit onlyInCargo onlyInCrate2Nix differentFeatures;
};
@ -17132,66 +17181,78 @@ rec {
If multiple paths to a dependency enable different features, the
corresponding feature sets are merged. Features in rust are additive.
*/
mergePackageFeatures = { crateConfigs ? crates, packageId
, rootPackageId ? packageId, features ? rootFeatures
mergePackageFeatures =
{ crateConfigs ? crates
, packageId
, rootPackageId ? packageId
, features ? rootFeatures
, dependencyPath ? [ crates.${packageId}.crateName ]
, featuresByPackageId ? { }, target
# Adds devDependencies to the crate with rootPackageId.
, runTests ? false, ... }@args:
assert (builtins.isAttrs crateConfigs);
assert (builtins.isString packageId);
assert (builtins.isString rootPackageId);
assert (builtins.isList features);
assert (builtins.isList dependencyPath);
assert (builtins.isAttrs featuresByPackageId);
assert (builtins.isAttrs target);
assert (builtins.isBool runTests);
let
crateConfig = crateConfigs."${packageId}" or (builtins.throw
"Package not found: ${packageId}");
expandedFeatures =
expandFeatures (crateConfig.features or { }) features;
depWithResolvedFeatures = dependency:
let
packageId = dependency.packageId;
features = dependencyFeatures expandedFeatures dependency;
in { inherit packageId features; };
resolveDependencies = cache: path: dependencies:
assert (builtins.isAttrs cache);
assert (builtins.isList dependencies);
let
enabledDependencies = filterEnabledDependencies {
inherit dependencies target;
features = expandedFeatures;
};
directDependencies =
map depWithResolvedFeatures enabledDependencies;
foldOverCache = op: lib.foldl op cache directDependencies;
in foldOverCache (cache:
{ packageId, features }:
, featuresByPackageId ? { }
, target
# Adds devDependencies to the crate with rootPackageId.
, runTests ? false
, ...
}@args:
assert (builtins.isAttrs crateConfigs);
assert (builtins.isString packageId);
assert (builtins.isString rootPackageId);
assert (builtins.isList features);
assert (builtins.isList dependencyPath);
assert (builtins.isAttrs featuresByPackageId);
assert (builtins.isAttrs target);
assert (builtins.isBool runTests);
let
crateConfig = crateConfigs."${packageId}" or (builtins.throw
"Package not found: ${packageId}");
expandedFeatures =
expandFeatures (crateConfig.features or { }) features;
depWithResolvedFeatures = dependency:
let
cacheFeatures = cache.${packageId} or [ ];
combinedFeatures = sortedUnique (cacheFeatures ++ features);
in if cache ? ${packageId} && cache.${packageId}
== combinedFeatures then
cache
else
mergePackageFeatures {
features = combinedFeatures;
featuresByPackageId = cache;
inherit crateConfigs packageId target runTests rootPackageId;
});
cacheWithSelf = let
cacheFeatures = featuresByPackageId.${packageId} or [ ];
combinedFeatures = sortedUnique (cacheFeatures ++ expandedFeatures);
in featuresByPackageId // { "${packageId}" = combinedFeatures; };
cacheWithDependencies = resolveDependencies cacheWithSelf "dep"
(crateConfig.dependencies or [ ]
++ lib.optionals (runTests && packageId == rootPackageId)
(crateConfig.devDependencies or [ ]));
cacheWithAll = resolveDependencies cacheWithDependencies "build"
(crateConfig.buildDependencies or [ ]);
in cacheWithAll;
packageId = dependency.packageId;
features = dependencyFeatures expandedFeatures dependency;
in
{ inherit packageId features; };
resolveDependencies = cache: path: dependencies:
assert (builtins.isAttrs cache);
assert (builtins.isList dependencies);
let
enabledDependencies = filterEnabledDependencies {
inherit dependencies target;
features = expandedFeatures;
};
directDependencies =
map depWithResolvedFeatures enabledDependencies;
foldOverCache = op: lib.foldl op cache directDependencies;
in
foldOverCache (cache:
{ packageId, features }:
let
cacheFeatures = cache.${packageId} or [ ];
combinedFeatures = sortedUnique (cacheFeatures ++ features);
in
if cache ? ${packageId} && cache.${packageId}
== combinedFeatures then
cache
else
mergePackageFeatures {
features = combinedFeatures;
featuresByPackageId = cache;
inherit crateConfigs packageId target runTests rootPackageId;
});
cacheWithSelf =
let
cacheFeatures = featuresByPackageId.${packageId} or [ ];
combinedFeatures = sortedUnique (cacheFeatures ++ expandedFeatures);
in
featuresByPackageId // { "${packageId}" = combinedFeatures; };
cacheWithDependencies = resolveDependencies cacheWithSelf "dep"
(crateConfig.dependencies or [ ]
++ lib.optionals (runTests && packageId == rootPackageId)
(crateConfig.devDependencies or [ ]));
cacheWithAll = resolveDependencies cacheWithDependencies "build"
(crateConfig.buildDependencies or [ ]);
in
cacheWithAll;
# Returns the enabled dependencies given the enabled features.
filterEnabledDependencies = { dependencies, features, target }:
@ -17199,11 +17260,13 @@ rec {
assert (builtins.isList features);
assert (builtins.isAttrs target);
lib.filter (dep:
let targetFunc = dep.target or (features: true);
in targetFunc { inherit features target; } && (!(dep.optional or false)
lib.filter
(dep:
let targetFunc = dep.target or (features: true);
in
targetFunc { inherit features target; } && (!(dep.optional or false)
|| builtins.any (doesFeatureEnableDependency dep) features))
dependencies;
dependencies;
# Returns whether the given feature should enable the given dependency.
doesFeatureEnableDependency = { name, rename ? null, ... }:
@ -17212,7 +17275,8 @@ rec {
prefix = "${name}/";
len = builtins.stringLength prefix;
startsWithPrefix = builtins.substring 0 len feature == prefix;
in (rename == null && feature == name)
in
(rename == null && feature == name)
|| (rename != null && rename == feature) || startsWithPrefix;
/* Returns the expanded features for the given inputFeatures by applying the
@ -17230,7 +17294,8 @@ rec {
[ feature ]
++ (expandFeatures featureMap (featureMap."${feature}" or [ ]));
outFeatures = lib.concatMap expandFeature inputFeatures;
in sortedUnique outFeatures;
in
sortedUnique outFeatures;
/* Returns the actual features for the given dependency.
@ -17243,12 +17308,15 @@ rec {
defaultOrNil =
if dependency.usesDefaultFeatures or true then [ "default" ] else [ ];
explicitFeatures = dependency.features or [ ];
additionalDependencyFeatures = let
dependencyPrefix = (dependency.rename or dependency.name) + "/";
dependencyFeatures =
builtins.filter (f: lib.hasPrefix dependencyPrefix f) features;
in builtins.map (lib.removePrefix dependencyPrefix) dependencyFeatures;
in defaultOrNil ++ explicitFeatures ++ additionalDependencyFeatures;
additionalDependencyFeatures =
let
dependencyPrefix = (dependency.rename or dependency.name) + "/";
dependencyFeatures =
builtins.filter (f: lib.hasPrefix dependencyPrefix f) features;
in
builtins.map (lib.removePrefix dependencyPrefix) dependencyFeatures;
in
defaultOrNil ++ explicitFeatures ++ additionalDependencyFeatures;
# Sorts and removes duplicates from a list of strings.
sortedUnique = features:
@ -17258,7 +17326,8 @@ rec {
outFeaturesSet =
lib.foldl (set: feature: set // { "${feature}" = 1; }) { } features;
outFeaturesUnique = builtins.attrNames outFeaturesSet;
in builtins.sort (a: b: a < b) outFeaturesUnique;
in
builtins.sort (a: b: a < b) outFeaturesUnique;
deprecationWarning = message: value:
if strictDeprecation then

View File

@ -1,5 +1,25 @@
## Important
If you are going to call the derivations with a custom `nixpkgs` argument, make sure that the `nixpkgs` you pass is on at least the same commit or newer than it.
Unexpected errors may pop up if you use an older version. Same goes for the `sources` argument.
### How to use
To enter the development shell (which includes all tools mentioned in this readme + tools you'll need to develop Veloren), run:
```shell
nix-shell nix/shell.nix
```
It is recommended that you enter the dev shell before starting to build using `nix-build` or `nix-env` (anything which build stuff),
since it will setup a Cachix cache for you. (you can configure this for your user's `nix.conf` by running `cachix use veloren-nix` once in the dev shell,
which will make the cache available when you run commands outside of the dev shell).
If you have [direnv](https://direnv.net) setup on your system, it is also recommended to copy the `envrc`
(or `envrc-nvidia`, if you have an Nvidia GPU) file to the root of the repository as `.envrc`:
```shell
cp nix/envrc .envrc
```
This will make your env have the dev env setup automatically.
To build and install Voxygen and the server CLI into user profile, run:
```shell
nix-env -f nix/default.nix -i
@ -10,11 +30,21 @@ nix-env -f nix/default.nix --arg cratesToBuild '["veloren-voxygen"]'
```
For example, this will install Voxygen only.
To enter the development shell (which includes all tools mentioned in this readme + tools you'll need to develop Veloren), run:
You can configure the crates to be built with debug mode (not recommended, equals to `opt-level = 0`):
```shell
nix-shell nix/shell.nix
nix-env -f nix/default.nix --arg release false
```
If you aren't on NixOS, you can run `veloren-voxygen` using the provided `nixGLIntel` in the dev shell:
```shell
nixGLIntel veloren-voxygen
```
If you have an Nvidia GPU, you can enter the dev shell like so:
```shell
nix-shell nix/shell.nix --arg nvidia true
```
And you'll be able to use `nixGLNvidia` and `nixGLNvidiaBumblebee`.
### Managing Cargo.nix
Enter the development shell.
@ -35,9 +65,9 @@ niv update
### Formatting
Use [nixfmt](https://github.com/serokell/nixfmt) to format files.
Use [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt) to format files.
To format every Nix file in current working directory:
To format every Nix file:
```shell
nixfmt *.nix
nixpkgs-fmt nix/*.nix
```

View File

@ -1,22 +1,52 @@
{ pkgs }:
{ system, sources, nixpkgs }:
let
mozPkgs = import "${sources.nixpkgsMoz}/package-set.nix" {
pkgs = import nixpkgs { inherit system; };
};
rustChannel = mozPkgs.rustChannelOf {
rustToolchain = ../rust-toolchain;
sha256 = "sha256-P4FTKRe0nM1FRDV0Q+QY2WcC8M9IR7aPMMLWDfv+rEk=";
};
pkgs = import nixpkgs {
inherit system;
overlays = [
(final: prev: {
rustc = rustChannel.rust;
inherit (rustChannel)
;
crate2nix = prev.callPackage sources.crate2nix { pkgs = prev; };
nixGL = prev.callPackage sources.nixGL { pkgs = prev; };
})
];
};
in
with pkgs;
let
xorgLibraries = with xorg; [ libX11 libXcursor libXrandr libXi ];
otherLibraries = [
libGL
# wayland
/* uncomment above for wayland support (?)
for some reason it doesn't work (triggers `unreachable!()` code in winit!)
so I disabled it by default
*/
];
neededLibPaths = lib.concatStringsSep ":"
(map (p: "${p}/lib") (xorgLibraries ++ otherLibraries));
# deps that crates need (for compiling)
crateDeps = {
libudev-sys = [ pkg-config libudev ];
alsa-sys = [ pkg-config alsaLib ];
veloren-network = [ pkg-config openssl ];
veloren-voxygen = [ atk cairo glib gtk3 pango ];
libudev-sys = {
buildInputs = [ libudev ];
nativeBuildInputs = [ pkg-config ];
};
alsa-sys = {
buildInputs = [ alsaLib ];
nativeBuildInputs = [ pkg-config ];
};
veloren-network = {
buildInputs = [ openssl ];
nativeBuildInputs = [ pkg-config ];
};
veloren-voxygen = {
buildInputs = [ xorg.libxcb ];
nativeBuildInputs = [ ];
};
};
in { inherit neededLibPaths crateDeps; }
# deps that voxygen needs to function
voxygenNeededLibs = (with xorg; [ libX11 libXcursor libXrandr libXi ])
++ [ libGL ];
gitLfsCheckFile = ../assets/voxygen/background/bg_main.png;
in
{ inherit pkgs voxygenNeededLibs crateDeps gitLfsCheckFile; }

View File

@ -1,21 +1,18 @@
{
/* `crate2nix` doesn't support profiles in `Cargo.toml`, so default to release.
Otherwise bad performance (non-release is built with opt level 0)
*/
release ? true, cratesToBuild ? [ "veloren-voxygen" "veloren-server-cli" ]
# `crate2nix` doesn't support profiles in `Cargo.toml`, so default to release.
# Otherwise bad performance (non-release is built with opt level 0)
release ? true
, cratesToBuild ? [ "veloren-voxygen" "veloren-server-cli" ]
, system ? builtins.currentSystem
, sources ? import ./sources.nix { inherit system; } }:
, nixpkgs ? sources.nixpkgs
, nvidia ? false
, sources ? import ./sources.nix { inherit system; }
}:
let
isBuildingCrate = name:
builtins.any (otherName: name == otherName) cratesToBuild;
isBuildingVoxygen = isBuildingCrate "veloren-voxygen";
isBuildingServerCli = isBuildingCrate "veloren-server-cli";
common = import ./common.nix { inherit nixpkgs system sources; };
inherit (common) pkgs;
pkgs = import ./nixpkgs.nix { inherit sources system; };
common = import ./common.nix { inherit pkgs; };
meta = with pkgs; {
meta = with pkgs.stdenv.lib; {
description = "Veloren is a multiplayer voxel RPG written in Rust.";
longDescription = ''
Veloren is a multiplayer voxel RPG written in Rust.
@ -23,37 +20,44 @@ let
'';
homepage = "https://veloren.net";
upstream = "https://gitlab.com/veloren/veloren";
license = lib.licenses.gpl3;
maintainers = [ lib.maintainers.yusdacra ];
platforms = lib.platforms.all;
license = licenses.gpl3;
maintainers = [ maintainers.yusdacra ];
platforms = platforms.all;
};
makeGitCommand = subcommands: name:
# Check if git-lfs is working. This is a partial check only,
# the actual check is done in `common/build.rs`. We do this
# so that the build fails early.
if builtins.pathExists ../assets/voxygen/background/bg_main.png then
builtins.readFile (pkgs.runCommand name { } ''
cd ${
# Only copy the `.git` directory to nix store, anything else is a waste.
builtins.path {
path = ../.git;
# Nix store path names don't accept names that start with a dot.
name = "git";
}
}
${pkgs.git}/bin/git ${subcommands} > $out
'')
isGitLfsSetup =
let
gitLfsCheckOutput = with common;
builtins.readFile (pkgs.runCommand "gitLfsCheck" { } ''
[ "$(${pkgs.file}/bin/file --mime-type ${gitLfsCheckFile})" = "${gitLfsCheckFile}: image/png" ]
printf $? > $out
'');
in
if gitLfsCheckOutput == "0" then
true
else
abort ''
Git Large File Storage (git-lfs) has not been set up correctly.
Git Large File Storage (`git-lfs`) has not been set up correctly.
Most common reasons:
- git-lfs was not installed before cloning this repository
- this repository was not cloned from the primary gitlab mirror.
- The github mirror does not support lfs.
- `git-lfs` was not installed before cloning this repository.
- This repository was not cloned from the primary GitLab mirror.
- The GitHub mirror does not support LFS.
See the book at https://book.veloren.net/ for details.
'';
makeGitCommand = subcommands: name:
builtins.readFile (pkgs.runCommand name { } ''
cd ${
# Only copy the `.git` directory to nix store, anything else is a waste.
builtins.path {
path = ../.git;
# Nix store path names don't accept names that start with a dot.
name = "veloren-git-dir";
}
}
(${pkgs.git}/bin/git ${subcommands}) > $out
'');
gitHash = makeGitCommand
"log -n 1 --pretty=format:%h/%cd --date=format:%Y-%m-%d-%H:%M --abbrev=8"
"getGitHash";
@ -61,73 +65,87 @@ let
gitTag =
# If the git command errors out we feed an empty string
makeGitCommand "describe --exact-match --tags HEAD || printf ''"
"getGitTag";
"getGitTag";
# If gitTag has a tag (meaning the commit we are on is a *release*), use it as version, else:
# Just use the prettified hash we have, if we don't have it the build fails
version = if gitTag != "" then gitTag else gitHash;
# Sanitize version string since it might contain illegal characters for a Nix store path
# Used in the derivation(s) name
sanitizedVersion = pkgs.stdenv.lib.strings.sanitizeDerivationName version;
veloren-assets = pkgs.runCommand "makeAssetsDir" { } ''
mkdir $out
ln -sf ${../assets} $out/assets
'';
velorenVoxygenDesktopFile = pkgs.makeDesktopItem rec {
name = "veloren-voxygen";
exec = name;
icon = ../assets/voxygen/logo.ico;
comment =
"Official client for Veloren - the open-world, open-source multiplayer voxel RPG";
desktopName = "Voxygen";
genericName = "Veloren Client";
categories = "Game;";
};
veloren-crates = with pkgs;
callPackage ./Cargo.nix {
defaultCrateOverrides = with common;
defaultCrateOverrides // {
libudev-sys = _: { buildInputs = crateDeps.libudev-sys; };
alsa-sys = _: { buildInputs = crateDeps.alsa-sys; };
veloren-common = _:
(if isBuildingServerCli then {
DISABLE_GIT_LFS_CHECK = true;
} else
{ }) // {
# Declare env values here so that `common/build.rs` sees them
NIX_GIT_HASH = gitHash;
NIX_GIT_TAG = gitTag;
};
veloren-network = _: { buildInputs = crateDeps.veloren-network; };
veloren-server-cli = _: { VELOREN_USERDATA_STRATEGY = "system"; };
veloren-voxygen = _: {
libudev-sys = _: crateDeps.libudev-sys;
alsa-sys = _: crateDeps.alsa-sys;
veloren-network = _: crateDeps.veloren-network;
veloren-common = _: {
# Disable `git-lfs` check here since we check it ourselves
# We have to include the command output here, otherwise Nix won't run it
DISABLE_GIT_LFS_CHECK = isGitLfsSetup;
# Declare env values here so that `common/build.rs` sees them
NIX_GIT_HASH = gitHash;
NIX_GIT_TAG = gitTag;
};
veloren-server-cli = _: {
name = "veloren-server-cli_${sanitizedVersion}";
inherit version;
VELOREN_USERDATA_STRATEGY = "system";
buildInputs = crateDeps.veloren-voxygen;
nativeBuildInputs = [ makeWrapper ];
postInstall = ''
wrapProgram $out/bin/veloren-voxygen --set LD_LIBRARY_PATH ${neededLibPaths}
wrapProgram $out/bin/veloren-server-cli --set VELOREN_ASSETS ${veloren-assets}
'';
meta = meta // {
longDescription = ''
${meta.longDescription}
"This package includes the server CLI."
'';
};
};
veloren-voxygen = _: {
name = "veloren-voxygen_${sanitizedVersion}";
inherit version;
VELOREN_USERDATA_STRATEGY = "system";
inherit (crateDeps.veloren-voxygen) buildInputs;
nativeBuildInputs = crateDeps.veloren-voxygen.nativeBuildInputs
++ [ makeWrapper copyDesktopItems ];
desktopItems = [ velorenVoxygenDesktopFile ];
postInstall = ''
wrapProgram $out/bin/veloren-voxygen\
--set VELOREN_ASSETS ${veloren-assets}\
--set LD_LIBRARY_PATH ${
lib.makeLibraryPath common.voxygenNeededLibs
}
'';
meta = meta // {
longDescription = ''
${meta.longDescription}
"This package includes the official client, Voxygen."
'';
};
};
};
inherit release pkgs;
};
veloren-assets = pkgs.symlinkJoin {
inherit version;
name = "veloren-assets_${version}";
paths = [
(pkgs.runCommand "mkVelorenAssetsDir" { } ''
mkdir -p $out/share/veloren
ln -sf ${../assets} $out/share/veloren/assets
'')
];
meta = meta // {
longDescription = ''
${meta.longDescription}
This package includes the assets.
'';
};
};
makePkg = name:
pkgs.symlinkJoin {
inherit version;
name = "${name}_${version}";
paths = [ veloren-crates.workspaceMembers."${name}".build ];
meta = meta // {
longDescription = ''
${meta.longDescription}
${if isBuildingVoxygen then
"This package includes the client, Voxygen."
else
""}
${if isBuildingServerCli then
"This package includes the server CLI."
else
""}
'';
};
};
in (pkgs.lib.genAttrs cratesToBuild makePkg) // { inherit veloren-assets; }
makePkg = name: veloren-crates.workspaceMembers."${name}".build;
in
(pkgs.lib.genAttrs cratesToBuild makePkg)

2
nix/envrc Normal file
View File

@ -0,0 +1,2 @@
source_env nix/envrc-common
use nix nix/shell.nix

4
nix/envrc-common Normal file
View File

@ -0,0 +1,4 @@
watch_file nix/shell.nix
watch_file nix/common.nix
watch_file nix/sources.nix
watch_file nix/sources.json

2
nix/envrc-nvidia Normal file
View File

@ -0,0 +1,2 @@
source_env nix/envrc-common
use nix nix/shell.nix --arg nvidia true

View File

@ -1,21 +0,0 @@
{ system, sources ? import ./sources.nix { inherit system; }
, nixpkgs ? sources.nixpkgs }:
let
mozPkgs = import "${sources.nixpkgsMoz}/package-set.nix" {
pkgs = import nixpkgs { inherit system; };
};
rustChannel = mozPkgs.rustChannelOf {
rustToolchain = ../rust-toolchain;
hash = "sha256-P4FTKRe0nM1FRDV0Q+QY2WcC8M9IR7aPMMLWDfv+rEk=";
};
in import nixpkgs {
inherit system;
overlays = [
(self: super: {
rustc = rustChannel.rust;
inherit (rustChannel)
;
})
];
}

View File

@ -1,15 +1,51 @@
{ nixpkgs ? <nixpkgs>, sources ? import ./sources.nix { }
, system ? builtins.currentSystem }:
{ nixpkgs ? <nixpkgs>
, sources ? import ./sources.nix { }
, system ? builtins.currentSystem
, nvidia ? false
}:
let common = import ./common.nix { inherit nixpkgs system sources; };
in
with common.pkgs;
let
pkgs = import ./nixpkgs.nix { inherit sources nixpkgs system; };
common = import ./common.nix { inherit pkgs; };
crate2nix = pkgs.callPackage sources.crate2nix { inherit pkgs; };
in with pkgs;
nixGLPackages = ((with nixGL; [ nixGLIntel ]) ++ (lib.optional nvidia
(with nixGL; [ nixGLNvidia nixGLNvidiaBumblebee ])));
getAllCratesDeps = name:
(lib.concatLists
(map (attrset: attrset."${name}") (lib.attrValues common.crateDeps)));
bundleCrate = writeScriptBin "bundleCrate" ''
#!${stdenv.shell}
${nix-bundle}/bin/nix-bundle "(pkgs.callPackage ./nix/default.nix { cratesToBuild = [ \"$1\" ]; }).$1" /bin/$1
'';
in
with common;
mkShell {
name = "veloren-shell";
nativeBuildInputs = [ git git-lfs niv nixfmt crate2nix cargo rustc ];
buildInputs = lib.concatLists (lib.attrValues common.crateDeps);
nativeBuildInputs = [
bundleCrate
git
git-lfs
niv
nixpkgs-fmt
crate2nix
cargo
rustc
rustfmt
clippy
cachix
] ++ nixGLPackages ++ (getAllCratesDeps "nativeBuildInputs");
buildInputs = getAllCratesDeps "buildInputs";
shellHook = ''
export LD_LIBRARY_PATH=${common.neededLibPaths}
# Setup our cachix "substituter"
export NIX_CONFIG="
substituters = https://cache.nixos.org https://veloren-nix.cachix.org
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= veloren-nix.cachix.org-1:zokfKJqVsNV6kI/oJdLF6TYBdNPYGSb+diMVQPn/5Rc=
"
# We need this so that Voxygen runs
export LD_LIBRARY_PATH=${lib.makeLibraryPath voxygenNeededLibs}
# No need to install git-lfs and run fetch / checkout commands if we have it setup
[ "$(${file}/bin/file --mime-type ${gitLfsCheckFile})" = "${gitLfsCheckFile}: image/png" ] || (git lfs install --local && git lfs fetch && git lfs checkout)
'';
}

View File

@ -5,10 +5,22 @@
"homepage": "",
"owner": "kolloch",
"repo": "crate2nix",
"rev": "df3e4e6570c1058d947d70876712209a1eca6731",
"sha256": "1kn98ckf2h4j3xmc50n6904p5g226qa1c1jgha511d9l6lgks24r",
"rev": "3701179c8aef0677dab1915457ca0f367f2dc523",
"sha256": "0z5vz3dcbx53a7q6xrm8qjrn62zlvzvaxdisv2axfh70qq4lx4n2",
"type": "tarball",
"url": "https://github.com/kolloch/crate2nix/archive/df3e4e6570c1058d947d70876712209a1eca6731.tar.gz",
"url": "https://github.com/kolloch/crate2nix/archive/3701179c8aef0677dab1915457ca0f367f2dc523.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixGL": {
"branch": "master",
"description": "A wrapper tool for nix OpenGL application",
"homepage": null,
"owner": "guibou",
"repo": "nixGL",
"rev": "7d6bc1b21316bab6cf4a6520c2639a11c25a220e",
"sha256": "02y38zmdplk7a9ihsxvnrzhhv7324mmf5g8hmxqizaid5k5ydpr3",
"type": "tarball",
"url": "https://github.com/guibou/nixGL/archive/7d6bc1b21316bab6cf4a6520c2639a11c25a220e.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixpkgs": {
@ -17,10 +29,10 @@
"homepage": "",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6625284c397b44bc9518a5a1567c1b5aae455c08",
"sha256": "1w0czzv53sg35gp7sr506facbmzd33jm34p6cg23fb9kz5rf5c89",
"rev": "b6bca3d80619f1565ba0ea635b0d38234e41c6bd",
"sha256": "09d4f6h98rmxnxzm1x07jxgrc81k6mz7fjigq375fkmb41j2kdsi",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/6625284c397b44bc9518a5a1567c1b5aae455c08.tar.gz",
"url": "https://github.com/NixOS/nixpkgs/archive/b6bca3d80619f1565ba0ea635b0d38234e41c6bd.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixpkgsMoz": {

View File

@ -1,18 +1,18 @@
# This file has been generated by Niv.
let
#
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: name: spec:
let name' = sanitizeName name + "-src";
in if spec.builtin or true then
builtins_fetchurl {
inherit (spec) url sha256;
name = name';
}
in
if spec.builtin or true then
builtins_fetchurl
{
inherit (spec) url sha256;
name = name';
}
else
pkgs.fetchurl {
inherit (spec) url sha256;
@ -21,11 +21,13 @@ let
fetch_tarball = pkgs: name: spec:
let name' = sanitizeName name + "-src";
in if spec.builtin or true then
builtins_fetchTarball {
name = name';
inherit (spec) url sha256;
}
in
if spec.builtin or true then
builtins_fetchTarball
{
name = name';
inherit (spec) url sha256;
}
else
pkgs.fetchzip {
name = name';
@ -34,16 +36,18 @@ let
fetch_git = name: spec:
let
ref = if spec ? ref then
spec.ref
else if spec ? branch then
"refs/heads/${spec.branch}"
else if spec ? tag then
"refs/tags/${spec.tag}"
else
abort
"In git source '${name}': Please specify `ref`, `tag` or `branch`!";
in builtins.fetchGit {
ref =
if spec ? ref then
spec.ref
else if spec ? branch then
"refs/heads/${spec.branch}"
else if spec ? tag then
"refs/tags/${spec.tag}"
else
abort
"In git source '${name}': Please specify `ref`, `tag` or `branch`!";
in
builtins.fetchGit {
url = spec.repo;
inherit (spec) rev;
inherit ref;
@ -75,12 +79,14 @@ let
mkPkgs = sources: system:
let
sourcesNixpkgs = import
(builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {
(builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; })
{
inherit system;
};
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
in if builtins.hasAttr "nixpkgs" sources then
in
if builtins.hasAttr "nixpkgs" sources then
sourcesNixpkgs
else if hasNixpkgsPath && !hasThisAsNixpkgsPath then
import <nixpkgs> { }
@ -109,26 +115,30 @@ let
fetch_builtin-url name
else
abort
"ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
"ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# If the environment variable NIV_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
replace = name: drv:
let
saneName = stringAsChars
(c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
(c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c)
name;
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
in if ersatz == "" then drv else ersatz;
in
if ersatz == "" then drv else ersatz;
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (f: set:
with builtins;
listToAttrs (map (attr: {
name = attr;
value = f attr set.${attr};
}) (attrNames set)));
listToAttrs (map
(attr: {
name = attr;
value = f attr set.${attr};
})
(attrNames set)));
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
range = first: last:
@ -152,39 +162,44 @@ let
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
let inherit (builtins) lessThan nixVersion fetchTarball;
in if lessThan nixVersion "1.12" then
in
if lessThan nixVersion "1.12" then
fetchTarball
({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
let inherit (builtins) lessThan nixVersion fetchurl;
in if lessThan nixVersion "1.12" then
in
if lessThan nixVersion "1.12" then
fetchurl
({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs (name: spec:
if builtins.hasAttr "outPath" spec then
abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = replace name (fetch config.pkgs name spec); })
config.sources;
mapAttrs
(name: spec:
if builtins.hasAttr "outPath" spec then
abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = replace name (fetch config.pkgs name spec); })
config.sources;
# The "config" used by the fetchers
mkConfig = { sourcesFile ?
if builtins.pathExists ./sources.json then ./sources.json else null
mkConfig =
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
, sources ? if isNull sourcesFile then
{ }
else
builtins.fromJSON (builtins.readFile sourcesFile)
, system ? builtins.currentSystem, pkgs ? mkPkgs sources system }: rec {
{ }
else
builtins.fromJSON (builtins.readFile sourcesFile)
, system ? builtins.currentSystem
, pkgs ? mkPkgs sources system
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
@ -192,6 +207,7 @@ let
inherit pkgs;
};
in mkSources (mkConfig { }) // {
in
mkSources (mkConfig { }) // {
__functor = _: settings: mkSources (mkConfig settings);
}