From 3f498522db863e62acb381644ce812c38cfde2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20B=C3=B6klin?= Date: Fri, 11 Dec 2020 12:00:04 +0000 Subject: [PATCH] flake-compat (unify flake and non-flake build process/environment) The only user-facing changes is the process for version pinning, which will be slightly less convenient without access to the `nix flake` feature. This is justified by it rarely being necessary, for the benefit of relying on an upcoming built-in nix feature rather than a non-standard third-party tool. - deprecate `niv` for version pinning - legacy nix now uses the flake via `flake-compat` - remove `sources.{nix,json}` (versions now pinned in `flake.lock`) - move contents of `nix/default.nix` to `nix/veloren.nix` - make `nix-build nix/default.nix` produce the same output as `flake build` - move contents of `nix/shell.nix` into `nix/devShell.nix` - make `nix-shell nix/shell.nix` produce the same environment as `flake develop` - Move `tag` parameter into `sourceInfo` - Tidy up and autoformat with `nixpkgs-fmt` - update README to reflect new usage - revert input versions to match those previously specified in nix/sources.json --- flake.lock | 96 +++++++++++++++++++++ flake.nix | 68 +++++++++++++++ nix/Cargo.nix | 55 ++++++++++++ nix/README.md | 82 +++++++++++++++++- nix/common.nix | 32 +++---- nix/default.nix | 157 ++-------------------------------- nix/devShell.nix | 51 ++++++++++++ nix/envrc | 9 +- nix/envrc-nvidia | 9 +- nix/rustPkgs.nix | 15 ++++ nix/shell.nix | 57 ++----------- nix/sources.json | 50 ----------- nix/sources.nix | 213 ----------------------------------------------- nix/utils.nix | 75 +++++++++++++++++ nix/veloren.nix | 130 +++++++++++++++++++++++++++++ 15 files changed, 604 insertions(+), 495 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/devShell.nix create mode 100644 nix/rustPkgs.nix delete mode 100644 nix/sources.json delete mode 100644 nix/sources.nix create mode 100644 nix/utils.nix create mode 100644 nix/veloren.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..5c2ef22ba0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,96 @@ +{ + "nodes": { + "crate2nix": { + "flake": false, + "locked": { + "lastModified": 1606659997, + "narHash": "sha256-wpJOCcbgQNeV2Dq2rvbf9Atjs8So5m7wUaP0xdr4u3w=", + "owner": "kolloch", + "repo": "crate2nix", + "rev": "3701179c8aef0677dab1915457ca0f367f2dc523", + "type": "github" + }, + "original": { + "owner": "kolloch", + "repo": "crate2nix", + "rev": "3701179c8aef0677dab1915457ca0f367f2dc523", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1605370193, + "narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5021eac20303a61fafe17224c087f5519baed54d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixGL": { + "flake": false, + "locked": { + "lastModified": 1604138361, + "narHash": "sha256-I9/myywtqh9xrxC94molYpwN4c92dw1jUmfS2+pHwws=", + "owner": "guibou", + "repo": "nixGL", + "rev": "7d6bc1b21316bab6cf4a6520c2639a11c25a220e", + "type": "github" + }, + "original": { + "owner": "guibou", + "repo": "nixGL", + "rev": "7d6bc1b21316bab6cf4a6520c2639a11c25a220e", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1606744648, + "narHash": "sha256-/sBYrKS4uNFeX3cX1qmQ/viyqiDz7Eq/XoX4v2qSVgk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c00959877fb06b09468562518b408acda886c79e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c00959877fb06b09468562518b408acda886c79e", + "type": "github" + } + }, + "nixpkgsMoz": { + "flake": false, + "locked": { + "lastModified": 1603906276, + "narHash": "sha256-RsNPnEKd7BcogwkqhaV5kI/HuNC4flH/OQCC/4W5y/8=", + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "rev": "8c007b60731c07dd7a052cce508de3bb1ae849b4", + "type": "github" + }, + "original": { + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "type": "github" + } + }, + "root": { + "inputs": { + "crate2nix": "crate2nix", + "flake-utils": "flake-utils", + "nixGL": "nixGL", + "nixpkgs": "nixpkgs", + "nixpkgsMoz": "nixpkgsMoz" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..979e7d5b52 --- /dev/null +++ b/flake.nix @@ -0,0 +1,68 @@ +{ + description = "Flake providing Veloren, a multiplayer voxel RPG written in Rust."; + + inputs = { + crate2nix = { + url = "github:kolloch/crate2nix?rev=3701179c8aef0677dab1915457ca0f367f2dc523"; + flake = false; + }; + flake-utils.url = "github:numtide/flake-utils"; + nixpkgsMoz = { + url = "github:mozilla/nixpkgs-mozilla"; + flake = false; + }; + nixGL = { + url = "github:guibou/nixGL?rev=7d6bc1b21316bab6cf4a6520c2639a11c25a220e"; + flake = false; + }; + nixpkgs.url = "github:NixOS/nixpkgs?rev=c00959877fb06b09468562518b408acda886c79e"; + }; + + outputs = inputs: with inputs; + flake-utils.lib.eachSystem [ "x86_64-linux" ] (system: + let + pkgs = inputs.nixpkgs.legacyPackages."${system}"; + + sources = { + inherit + crate2nix + nixGL + nixpkgs + nixpkgsMoz + ; + }; + + veloren = import ./nix/veloren.nix { + inherit + nixpkgs + sources + system + ; + sourceInfo = + if self.sourceInfo ? rev then self.sourceInfo // { + # Tag would have to be set manually for stable releases flake + # because there's currently no way to get the tag via the interface. + # tag = v0.8.0; + } else (throw "Can't get revision because the git tree is dirty"); + }; + + in + with flake-utils; rec { + apps = builtins.mapAttrs + (name: value: lib.mkApp { inherit name; drv = value; }) + packages; + defaultApp = apps.veloren-voxygen; + + packages = veloren; + defaultPackage = packages.veloren-voxygen; + + devShell = import ./nix/devShell.nix { + inherit + nixpkgs + sources + system + ; + }; + } + ); +} diff --git a/nix/Cargo.nix b/nix/Cargo.nix index 5c8b46ac23..f5cf9d09b7 100644 --- a/nix/Cargo.nix +++ b/nix/Cargo.nix @@ -11693,6 +11693,31 @@ rec { ]; }; + "slotmap" = rec { + crateName = "slotmap"; + version = "0.4.0"; + edition = "2018"; + sha256 = "1kajcjwbs1amxripbrp6ash4q5nf7rlq7mv4wib7j94gvf138sn4"; + authors = [ + "Orson Peters " + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + optional = true; + features = [ "derive" ]; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "serde" "unstable" ]; + }; "smallvec 0.6.13" = rec { crateName = "smallvec"; version = "0.6.13"; @@ -12558,6 +12583,23 @@ rec { }; resolvedDefaultFeatures = [ "default" "xattr" ]; }; + "termcolor" = rec { + crateName = "termcolor"; + version = "1.1.2"; + edition = "2018"; + sha256 = "1x65i1ny4m6z1by62ra6wdcrd557p2ysm866x0pg60zby2cxizid"; + authors = [ + "Andrew Gallant " + ]; + dependencies = [ + { + name = "winapi-util"; + packageId = "winapi-util"; + target = { target, features }: target."windows"; + } + ]; + + }; "textwrap" = rec { crateName = "textwrap"; version = "0.11.0"; @@ -14493,6 +14535,11 @@ rec { name = "slab"; packageId = "slab"; } + { + name = "slotmap"; + packageId = "slotmap"; + features = [ "serde" "unstable" ]; + } { name = "specs"; packageId = "specs"; @@ -14740,6 +14787,10 @@ rec { name = "signal-hook"; packageId = "signal-hook"; } + { + name = "termcolor"; + packageId = "termcolor"; + } { name = "tracing"; packageId = "tracing"; @@ -14970,6 +15021,10 @@ rec { name = "specs-idvs"; packageId = "specs-idvs"; } + { + name = "termcolor"; + packageId = "termcolor"; + } { name = "tracing"; packageId = "tracing"; diff --git a/nix/README.md b/nix/README.md index 3c38bd63d6..12069ca79a 100644 --- a/nix/README.md +++ b/nix/README.md @@ -45,6 +45,67 @@ nix-shell nix/shell.nix --arg nvidia true ``` And you'll be able to use `nixGLNvidia` and `nixGLNvidiaBumblebee`. +#### Using the flake + +Due to the nature of flakes' reliance on git and the way `git-lfs` is configured for this repo, you must already have `git-lfs` in your environment when running nix commands on a local checkout. Run this to enter a shell environment with `git-lfs` in your path: +```shell +nix shell nixpkgs#git-lfs +``` + +To enter a shell environment with the necessary tools: +```shell +nix develop +``` + +If you simply want to run the latest version without necessarily installing it, you can do so with +```shell +# Voxygen (the default): +nix run gitlab:veloren/veloren +# Server CLI: +nix run gitlab:veloren/veloren#veloren-server-cli +``` + +To install (for example) the game client on your system, the configuration could look something like this: +```nix +{ description = "NixOS configuration with flakes"; + + inputs.veloren.url = gitlab:veloren/veloren; + + outputs = { self, nixpkgs, veloren }: { + nixosConfigurations. = nixpkgs.lib.nixosSystem rec { + system = ; + # ... + modules = [ + # add to your overlay so that the packages appear in pkgs + # for subsequent modules + ({...}: { + nixpkgs.overlays = [ + # ... + (final: prev: { + inherit (veloren.packages."${system}") veloren-voxygen; + }) + ]; + + # You can also add the flake to your registry + nix.registry.veloren.flake = veloren; + # with this, you can run latest master + # regardless of version installed like this: + # nix run veloren/master + }) + + # some module + ({ pkgs, ... }: { + environment.systemPackages = [ + pkgs.veloren-voxygen + ]; + }) + # ... + ]; + }; + }; +} +``` + ### Managing Cargo.nix Enter the development shell. @@ -56,18 +117,31 @@ crate2nix generate -f ../Cargo.toml ### Managing dependencies -We use [niv](https://github.com/nmattia/niv) to manage dependencies. +#### Nix with flakes enabled -To update the dependencies, run (from repository root): +If a specific revision is specified in `flake.nix`, you will have to update that first, either by specifying a new desired revision or by removing it. + +You can update the dependencies individually or all at once from the root of the project: ```shell -niv update +# only nixpkgs +nix flake update --update-input nixpkgs +# everything +nix flake update --recreate-lock-file ``` +See the [NixOS wiki](https://nixos.wiki/wiki/Flakes) for more information on how to use flakes. + +#### Legacy nix + +It is inadvised to update revisions without the use of `nix flake update` as it's both tedious and error-prone to attempt setting all fields to their correct values in both `flake.nix` and `flake.lock`, but if you need to do it for testing, `flake.lock` is where legacy nix commands get the input revisions from (through `flake-compat`), regardless of what is specified in `flake.nix` (see https://github.com/edolstra/flake-compat/issues/10). + +Modify the relevant `rev` field in `flake.lock` to what you need - you can use `nix-prefetch-git` to find an up-to-date revision. Leave the `narHash` entry as is and attempt a rebuild to find out what its value should be. + ### Formatting Use [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt) to format files. To format every Nix file: ```shell -nixpkgs-fmt nix/*.nix +nixpkgs-fmt flake.nix nix/*.nix ``` diff --git a/nix/common.nix b/nix/common.nix index 5fb7e19f96..755b0e2663 100644 --- a/nix/common.nix +++ b/nix/common.nix @@ -1,36 +1,21 @@ -{ system, sources, nixpkgs }: +{ nixpkgs, sources, system }: let - mozPkgs = import "${sources.nixpkgsMoz}/package-set.nix" { + rustChannel = import ./rustPkgs.nix { pkgs = import nixpkgs { inherit system; }; + inherit (sources) nixpkgsMoz; }; - rustChannel = - let - channel = mozPkgs.rustChannelOf { - rustToolchain = ../rust-toolchain; - sha256 = "sha256-P4FTKRe0nM1FRDV0Q+QY2WcC8M9IR7aPMMLWDfv+rEk="; - }; - flip = f: a: b: f b a; - mapAttrs = builtins.mapAttrs; - in - flip mapAttrs channel (name: value: - (if name == "rust" then - value.override { extensions = [ "rust-src" ]; } - else - value)); - 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 @@ -61,4 +46,11 @@ let gitLfsCheckFile = ../assets/voxygen/background/bg_main.png; in -{ inherit pkgs voxygenNeededLibs crateDeps gitLfsCheckFile; } +{ + inherit + crateDeps + gitLfsCheckFile + pkgs + voxygenNeededLibs + ; +} diff --git a/nix/default.nix b/nix/default.nix index c02f920505..29d4c3807f 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,151 +1,6 @@ -{ - # `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 -, nixpkgs ? sources.nixpkgs -, sources ? import ./sources.nix { inherit system; } -}: -let - common = import ./common.nix { inherit nixpkgs system sources; }; - inherit (common) 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. - It is inspired by games such as Cube World, Legend of Zelda: Breath of the Wild, Dwarf Fortress and Minecraft. - ''; - homepage = "https://veloren.net"; - upstream = "https://gitlab.com/veloren/veloren"; - license = licenses.gpl3; - maintainers = [ maintainers.yusdacra ]; - # TODO: Make this work on BSD and Mac OS - platforms = platforms.linux; - }; - - 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. - 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. - 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"; - - gitTag = - # If the git command errors out we feed an empty string - makeGitCommand "describe --exact-match --tags HEAD || printf ''" - "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 = _: 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"; - nativeBuildInputs = [ makeWrapper ]; - postInstall = '' - 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; - }; - - makePkg = name: veloren-crates.workspaceMembers."${name}".build; -in -(pkgs.lib.genAttrs cratesToBuild makePkg) +(import + (fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; + sha256 = "sha256:0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; + }) + { src = ../.; }).defaultNix diff --git a/nix/devShell.nix b/nix/devShell.nix new file mode 100644 index 0000000000..4e12fd817e --- /dev/null +++ b/nix/devShell.nix @@ -0,0 +1,51 @@ +{ nixpkgs, sources, system, nvidia ? false }: +with import ./common.nix +{ + inherit + nixpkgs + sources + system + ; +}; +with pkgs; +let + nixGLPackages = ((with nixGL; [ nixGLIntel ]) ++ (lib.optional nvidia + (with nixGL; [ nixGLNvidia nixGLNvidiaBumblebee ]))); + + getAllCratesDeps = name: + (lib.concatLists + (map (attrset: attrset."${name}") (lib.attrValues crateDeps))); + + bundleCrate = writeScriptBin "bundleCrate" '' + #!${stdenv.shell} + ${nix-bundle}/bin/nix-bundle "(pkgs.callPackage ./nix/veloren.nix { cratesToBuild = [ \"$1\" ]; }).$1" /bin/$1 + ''; +in +mkShell { + name = "veloren-shell"; + nativeBuildInputs = [ + bundleCrate + cachix + cargo + clippy + crate2nix + git + git-lfs + nixpkgs-fmt + rustc + rustfmt + ] ++ nixGLPackages ++ (getAllCratesDeps "nativeBuildInputs"); + buildInputs = getAllCratesDeps "buildInputs"; + shellHook = '' + # 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= + " + # Add libraries Voxygen needs so that it 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) + ''; +} diff --git a/nix/envrc b/nix/envrc index 0d450b32fe..94613c39c5 100644 --- a/nix/envrc +++ b/nix/envrc @@ -1,5 +1,8 @@ -watch_file nix/shell.nix +watch_file flake.lock +watch_file flake.nix watch_file nix/common.nix -watch_file nix/sources.nix -watch_file nix/sources.json +watch_file nix/devShell.nix +watch_file nix/rustPkgs.nix +watch_file nix/shell.nix +watch_file nix/utils.nix use nix nix/shell.nix diff --git a/nix/envrc-nvidia b/nix/envrc-nvidia index 5fcdbc823b..41a023e85c 100644 --- a/nix/envrc-nvidia +++ b/nix/envrc-nvidia @@ -1,5 +1,8 @@ -watch_file nix/shell.nix +watch_file flake.lock +watch_file flake.nix watch_file nix/common.nix -watch_file nix/sources.nix -watch_file nix/sources.json +watch_file nix/devShell.nix +watch_file nix/rustPkgs.nix +watch_file nix/shell.nix +watch_file nix/utils.nix use nix nix/shell.nix --arg nvidia true diff --git a/nix/rustPkgs.nix b/nix/rustPkgs.nix new file mode 100644 index 0000000000..9bb7d1074a --- /dev/null +++ b/nix/rustPkgs.nix @@ -0,0 +1,15 @@ +{ nixpkgsMoz, pkgs }: +let + mozPkgs = import "${nixpkgsMoz}/package-set.nix" { + inherit pkgs; + }; + + channel = mozPkgs.rustChannelOf { + rustToolchain = ../rust-toolchain; + sha256 = "sha256-P4FTKRe0nM1FRDV0Q+QY2WcC8M9IR7aPMMLWDfv+rEk="; + }; + +in +channel // { + rust = channel.rust.override { extensions = [ "rust-src" ]; }; +} diff --git a/nix/shell.nix b/nix/shell.nix index 653f668129..c68e85b60e 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -1,51 +1,6 @@ -{ nixpkgs ? -, sources ? import ./sources.nix { } -, system ? builtins.currentSystem -, nvidia ? false -}: -let common = import ./common.nix { inherit nixpkgs system sources; }; -in -with common.pkgs; -let - 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 = [ - bundleCrate - git - git-lfs - niv - nixpkgs-fmt - crate2nix - cargo - rustc - rustfmt - clippy - cachix - ] ++ nixGLPackages ++ (getAllCratesDeps "nativeBuildInputs"); - buildInputs = getAllCratesDeps "buildInputs"; - shellHook = '' - # 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= - " - # Add libraries Voxygen needs so that it 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) - ''; -} +(import + (fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; + sha256 = "sha256:0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; + }) + { src = ../.; }).shellNix diff --git a/nix/sources.json b/nix/sources.json deleted file mode 100644 index 375b4e2adb..0000000000 --- a/nix/sources.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "crate2nix": { - "branch": "master", - "description": "nix build file generator for rust crates", - "homepage": "", - "owner": "kolloch", - "repo": "crate2nix", - "rev": "3701179c8aef0677dab1915457ca0f367f2dc523", - "sha256": "0z5vz3dcbx53a7q6xrm8qjrn62zlvzvaxdisv2axfh70qq4lx4n2", - "type": "tarball", - "url": "https://github.com/kolloch/crate2nix/archive/3701179c8aef0677dab1915457ca0f367f2dc523.tar.gz", - "url_template": "https://github.com///archive/.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///archive/.tar.gz" - }, - "nixpkgs": { - "branch": "nixpkgs-unstable", - "description": "Nix Packages collection", - "homepage": "", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c00959877fb06b09468562518b408acda886c79e", - "sha256": "02anj9mbzy45bszlmv7k42mb5y7yj2lxc5vpbxgd3f5qljn5ih7y", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/c00959877fb06b09468562518b408acda886c79e.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "nixpkgsMoz": { - "branch": "master", - "description": "mozilla related nixpkgs (extends nixos/nixpkgs repo)", - "homepage": null, - "owner": "mozilla", - "repo": "nixpkgs-mozilla", - "rev": "8c007b60731c07dd7a052cce508de3bb1ae849b4", - "sha256": "1zybp62zz0h077zm2zmqs2wcg3whg6jqaah9hcl1gv4x8af4zhs6", - "type": "tarball", - "url": "https://github.com/mozilla/nixpkgs-mozilla/archive/8c007b60731c07dd7a052cce508de3bb1ae849b4.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - } -} diff --git a/nix/sources.nix b/nix/sources.nix deleted file mode 100644 index 9d57ba63e9..0000000000 --- a/nix/sources.nix +++ /dev/null @@ -1,213 +0,0 @@ -# This file has been generated by Niv. -let - # - # The fetchers. fetch_ fetches specs of 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'; - } - else - pkgs.fetchurl { - inherit (spec) url sha256; - name = name'; - }; - - 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; - } - else - pkgs.fetchzip { - name = name'; - inherit (spec) url sha256; - }; - - 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 { - url = spec.repo; - inherit (spec) rev; - inherit ref; - }; - - fetch_local = spec: spec.path; - - fetch_builtin-tarball = name: - throw '' - [${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=tarball -a builtin=true''; - - fetch_builtin-url = name: - throw '' - [${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=file -a builtin=true''; - - # - # Various helpers - # - - # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 - sanitizeName = name: - (concatMapStrings (s: if builtins.isList s then "-" else s) - (builtins.split "[^[:alnum:]+._?=-]+" - ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name))); - - # The set of packages used when specs are fetched using non-builtins. - mkPkgs = sources: system: - let - sourcesNixpkgs = import - (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) - { - inherit system; - }; - hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; - hasThisAsNixpkgsPath = == ./.; - in - if builtins.hasAttr "nixpkgs" sources then - sourcesNixpkgs - else if hasNixpkgsPath && !hasThisAsNixpkgsPath then - import { } - else - abort '' - Please specify either (through -I or NIX_PATH=nixpkgs=...) or - add a package called "nixpkgs" to your sources.json. - ''; - - # The actual fetching function. - fetch = pkgs: name: spec: - - if !builtins.hasAttr "type" spec then - abort "ERROR: niv spec ${name} does not have a 'type' attribute" - else if spec.type == "file" then - fetch_file pkgs name spec - else if spec.type == "tarball" then - fetch_tarball pkgs name spec - else if spec.type == "git" then - fetch_git name spec - else if spec.type == "local" then - fetch_local spec - else if spec.type == "builtin-tarball" then - fetch_builtin-tarball name - else if spec.type == "builtin-url" then - fetch_builtin-url name - else - abort - "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; - ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; - 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))); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 - range = first: last: - if first > last then - [ ] - else - builtins.genList (n: first + n) (last - first + 1); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 - stringToCharacters = s: - map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 - stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); - concatMapStrings = f: list: concatStrings (map f list); - concatStrings = builtins.concatStringsSep ""; - - # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 - optionalAttrs = cond: as: if cond then as else { }; - - # 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 - fetchTarball - ({ 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 - fetchurl - ({ 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; - - # The "config" used by the fetchers - 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 { - # The sources, i.e. the attribute set of spec name to spec - inherit sources; - - # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers - inherit pkgs; - }; - -in -mkSources (mkConfig { }) // { - __functor = _: settings: mkSources (mkConfig settings); -} diff --git a/nix/utils.nix b/nix/utils.nix new file mode 100644 index 0000000000..2bd844affb --- /dev/null +++ b/nix/utils.nix @@ -0,0 +1,75 @@ +{ pkgs }: { + + isGitLfsSetup = checkFile: + let + gitLfsCheckOutput = + builtins.readFile (pkgs.runCommand "gitLfsCheck" { } '' + ([ "$(${pkgs.file}/bin/file --mime-type ${checkFile})" = "${checkFile}: image/png" ] && printf "0" || printf "1") > $out + ''); + in + if gitLfsCheckOutput == "0" then + true + else + abort '' + 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. + See the book at https://book.veloren.net/ for details. + ''; + + # Format number of seconds in the Unix epoch as %Y-%m-%d-%H:%M. + dateTimeFormat = t: + let + rem = x: y: x - x / y * y; + days = t / 86400; + secondsInDay = rem t 86400; + hours = secondsInDay / 3600; + minutes = (rem secondsInDay 3600) / 60; + seconds = rem t 60; + + # Courtesy of https://stackoverflow.com/a/32158604. + z = days + 719468; + era = (if z >= 0 then z else z - 146096) / 146097; + doe = z - era * 146097; + yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + y = yoe + era * 400; + doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + mp = (5 * doy + 2) / 153; + d = doy - (153 * mp + 2) / 5 + 1; + m = mp + (if mp < 10 then 3 else -9); + y' = y + (if m <= 2 then 1 else 0); + + pad = s: if builtins.stringLength s < 2 then "0" + s else s; + in + "${toString y'}-${pad (toString m)}-${pad (toString d)}-${pad (toString hours)}:${pad (toString minutes)}"; + + getGitInfo = dotGitPath: + let + 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 = "dotgit-dir"; + } + } + (${pkgs.git}/bin/git ${subcommands}) > $out + ''); + + in + { + gitHash = makeGitCommand + "log -n 1 --pretty=format:%h/%cd --date=format:%Y-%m-%d-%H:%M --abbrev=8" + "getGitHash"; + + gitTag = + # If the git command errors out we feed an empty string + makeGitCommand "describe --exact-match --tags HEAD || printf ''" + "getGitTag"; + }; + +} diff --git a/nix/veloren.nix b/nix/veloren.nix new file mode 100644 index 0000000000..116c370df8 --- /dev/null +++ b/nix/veloren.nix @@ -0,0 +1,130 @@ +{ + # `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" ] +, disableGitLfsCheck ? false +, nixpkgs +, sources +, system +, sourceInfo ? { } +}: +let + common = import ./common.nix { + inherit + nixpkgs + sources + system + ; + }; + inherit (common) pkgs; + utils = import ./utils.nix { inherit 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. + It is inspired by games such as Cube World, Legend of Zelda: Breath of the Wild, Dwarf Fortress and Minecraft. + ''; + homepage = "https://veloren.net"; + upstream = "https://gitlab.com/veloren/veloren"; + license = licenses.gpl3; + maintainers = [ maintainers.yusdacra ]; + # TODO: Make this work on BSD and Mac OS + platforms = platforms.linux; + }; + + prettyRev = with sourceInfo; + if sourceInfo ? rev && sourceInfo ? lastModified + then builtins.substring 0 8 rev + "/" + utils.dateTimeFormat lastModified + else (utils.getGitInfo ../.git).gitHash; + # 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. + # Must be in format f4987672/2020-12-10-12:00 + version = + if sourceInfo ? tag then sourceInfo.tag + else if prettyRev != "" then prettyRev + else throw "Need a tag or at least revision + lastModified in order to determine version"; + # 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 = _: 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 = utils.isGitLfsSetup common.gitLfsCheckFile; + # Declare env values here so that `common/build.rs` sees them + NIX_GIT_HASH = prettyRev; + # if we have a tag (meaning the commit we are on is a *release*), + # use it as version, else use the prettified hash we have; + # if we don't have it the build fails + NIX_GIT_TAG = version; + }; + veloren-server-cli = _: { + name = "veloren-server-cli_${sanitizedVersion}"; + inherit version; + VELOREN_USERDATA_STRATEGY = "system"; + nativeBuildInputs = [ makeWrapper ]; + postInstall = '' + 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; + }; + + makePkg = name: veloren-crates.workspaceMembers."${name}".build; +in +(pkgs.lib.genAttrs cratesToBuild makePkg)