This is a project structure I’ve found useful. Looking for any
thoughts/comments/feedback. Roughly, I found a tension between the style
nixpkgs expects and the style conducive to development, so I extracted the
common portion into a derivation.nix
which is used by the remaining .nix
files. This setup allows me to use nix build
, nix-shell
, overlays, Hydra,
alternate packaging schemes, cross-compiling, etc.
================================================================================
used to pin nixpkgs to a specific version. If this is not needed, you may import in subsequent files instead.
let
baseUrl = "https://github.com/NixOS/nixpkgs/archive";
stable = {
tag = "20.03";
# sha256 is optional for builtins.fetchTarball
};
unstable = {
tag = "fce7562cf46727fdaf801b232116bc9ce0512049";
};
nixpkgsStable = builtins.fetchTarball {
url = "${baseUrl}/${stable.tag}.tar.gz";
};
nixpkgsUnstable = builtins.fetchTarball {
url = "${baseUrl}/${unstable.tag}.tar.gz";
};
in nixpkgsStable
This is a nixpkgs compatible derivation, ready to be added as a PR and used via callPackage.
{stdenv, pkgconfig, meson, ninja, boost, ... }:
stdenv.mkDerivation rec {
name = "my-project-${version}";
version = "0.0.1";
src = ./. ;
nativeBuildInputs = [ pkgconfig meson ninja ];
buildInputs = [ boost ];
enableParallelBuilding = true;
releaseName = name;
meta = with stdenv.lib; {
description = "Some Project in C++";
homepage = https://example.org/my-project;
license = licenses.gpl3Plus;
platforms = platforms.linux;
maintainers = [ "me@example.org" ];
};
}
This allows for easy inclusion into a custom nixpkgs via the overlay system. Sometimes I add multiple versions here with different options or inputs.
self: super: {
my-project = self.callPackage ./derivation.nix{ };
}
This allows for nix-build and nix-shell to automatically do TheRightThing. This can also allow importing other overlays and custom nixpkgs. This file will NOT work for inclusion into the Nixpkgs repo as default.nix, use the derivation.nix for that instead.
let
nixpkgs = import ./pin-nixpkgs.nix;
pkgs = import nixpkgs {
config = {};
overlays = [
(import ./overlay.nix)
# (import /other/overlays/too/)
];
};
in pkgs.my-project
This is for additional build and packaging as needed. Also used by hydra to
specify builds. This allows me to build specific releases, for example nix
build -f release.nix nix-build-arm
or nix build -f release.nix
deb-installer
.
{ nixpkgs ? (import ./nixpkgs.nix), ... } :
let
pkgs = import nixpkgs {config={};};
pkgs-arm = import nixpkgs {system="armv7l-linux";config={};};
nixBuild = drv : extraAttrs :drv.overrideAttrs (old:{
initPhase = ''
mkdir -p $out/nix-support
echo "$system" > $out/nix-support/system
'';
prePhases = ["initPhase"] ++ (if builtins.hasAttr "prePhases" old then old.prePhases else []);
postPhases = (if builtins.hasAttr "postPhases" old then old.postPhases else []) ++ ["finalPhase"];
finalPhase = ''
if test -e $src/nix-support/hydra-release-name; then
cp $src/nix-support/hydra-release-name $out/nix-support/hydra-release-name
fi
'';
}//extraAttrs);
jobs = rec {
nix-build = { system ? builtins.currentSystem }:
nixBuild (pkgs.callPackage ./derivation.nix {}) {};
nix-build-arm = { system ? builtins.currentSystem }:
with pkgs-arm;
(nixBuild (pkgs-arm.callPackage ./derivation.nix {
stdenv = pkgs-arm.stdenv;
system = "armv7l-linux";
}){});
};
in
jobs
used by hydra to specify build sets. TODO: should probably refactor the nixpkgs pin in a DRY way with nixpkgs.nix above.
{ nixpkgs ? (import ./nixpkgs.nix), declInput }:
let pkgs = import nixpkgs {config = {};}; in {
jobsets = pkgs.runCommand "spec.json" {} ''
cat <<EOF
${builtins.toXML declInput}
EOF
cat > $out <<EOF
{
"master": {
"enabled": 1,
"hidden": false,
"description": "my-project",
"nixexprinput": "src",
"nixexprpath": "release.nix",
"checkinterval": 90,
"schedulingshares": 100,
"enableemail": true,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"src": { "type": "git", "value": "file:///repo.git", "emailresponsible": true },
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git e797e0091356c25282fba4d19690666d4b6f6d0b", "emailresponsible": false }
}
},
"staging": {
"enabled": 1,
"hidden": false,
"description": "my-project",
"nixexprinput": "src",
"nixexprpath": "release.nix",
"checkinterval": 90,
"schedulingshares": 100,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"src": { "type": "git", "value": "file:///repo.git", "emailresponsible": true },
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git e797e0091356c25282fba4d19690666d4b6f6d0b", "emailresponsible": false }
}
}
}
EOF
'';
}
declarative jobset used in hydra, basically just points to the above spec.nix. TODO: refactor nixpkgs reference to nixpkgs.nix (or have nixpkgs.nix refer to this one)
{
"enabled": 1,
"hidden": true,
"description": "Jobsets",
"nixexprinput": "src",
"nixexprpath": "spec.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 3,
"inputs": {
"src": { "type": "git", "value": "file:///repo.git", "emailresponsible": true },
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git e797e0091356c25282fba4d19690666d4b6f6d0b", "emailresponsible": false }
}
}
if a custom shell environment is needed, override the default.nix
here