Merge pull request #279487 from bryango/checkpoint-build-polish
checkpointBuildTools: mkCheckpointedBuild -> mkCheckpointBuild
This commit is contained in:
commit
098ffee102
4 changed files with 65 additions and 41 deletions
|
@ -2,35 +2,38 @@
|
|||
|
||||
`pkgs.checkpointBuildTools` provides a way to build derivations incrementally. It consists of two functions to make checkpoint builds using Nix possible.
|
||||
|
||||
For hermeticity, Nix derivations do not allow any state to carry over between builds, making a transparent incremental build within a derivation impossible.
|
||||
For hermeticity, Nix derivations do not allow any state to be carried over between builds, making a transparent incremental build within a derivation impossible.
|
||||
|
||||
However, we can tell Nix explicitly what the previous build state was, by representing that previous state as a derivation output. This allows the passed build state to be used for an incremental build.
|
||||
|
||||
To change a normal derivation to a checkpoint based build, these steps must be taken:
|
||||
- apply `prepareCheckpointBuild` on the desired derivation
|
||||
e.g.:
|
||||
- apply `prepareCheckpointBuild` on the desired derivation, e.g.
|
||||
```nix
|
||||
checkpointArtifacts = (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox);
|
||||
```
|
||||
- change something you want in the sources of the package. (e.g. using a source override)
|
||||
- change something you want in the sources of the package, e.g. use a source override:
|
||||
```nix
|
||||
changedVBox = pkgs.virtualbox.overrideAttrs (old: {
|
||||
src = path/to/vbox/sources;
|
||||
}
|
||||
});
|
||||
```
|
||||
- use `mkCheckpointedBuild changedVBox buildOutput`
|
||||
- use `mkCheckpointBuild changedVBox checkpointArtifacts`
|
||||
- enjoy shorter build times
|
||||
|
||||
## Example {#sec-checkpoint-build-example}
|
||||
```nix
|
||||
{ pkgs ? import <nixpkgs> {} }: with (pkgs) checkpointBuildTools;
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
helloCheckpoint = checkpointBuildTools.prepareCheckpointBuild pkgs.hello;
|
||||
inherit (pkgs.checkpointBuildTools)
|
||||
prepareCheckpointBuild
|
||||
mkCheckpointBuild
|
||||
;
|
||||
helloCheckpoint = prepareCheckpointBuild pkgs.hello;
|
||||
changedHello = pkgs.hello.overrideAttrs (_: {
|
||||
doCheck = false;
|
||||
patchPhase = ''
|
||||
sed -i 's/Hello, world!/Hello, Nix!/g' src/hello.c
|
||||
'';
|
||||
});
|
||||
in checkpointBuildTools.mkCheckpointBuild changedHello helloCheckpoint
|
||||
in mkCheckpointBuild changedHello helloCheckpoint
|
||||
```
|
||||
|
|
|
@ -1,20 +1,33 @@
|
|||
{ pkgs }:
|
||||
{ lib
|
||||
, buildPackages
|
||||
}:
|
||||
|
||||
let
|
||||
# rudimentary support for cross-compiling
|
||||
# see: https://github.com/NixOS/nixpkgs/pull/279487#discussion_r1444449726
|
||||
inherit (buildPackages)
|
||||
mktemp
|
||||
rsync
|
||||
;
|
||||
in
|
||||
|
||||
rec {
|
||||
/* Prepare a derivation for local builds.
|
||||
*
|
||||
* This function prepares checkpoint builds by provinding,
|
||||
* containing the build output and the sources for cross checking.
|
||||
* This function prepares checkpoint builds by storing
|
||||
* the build output and the sources for cross checking.
|
||||
* The build output can be used later to allow checkpoint builds
|
||||
* by passing the derivation output to the `mkCheckpointBuild` function.
|
||||
*
|
||||
* To build a project with checkpoints follow these steps:
|
||||
* - run prepareIncrementalBuild on the desired derivation
|
||||
* e.G `incrementalBuildArtifacts = (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox);`
|
||||
* - change something you want in the sources of the package( e.G using source override)
|
||||
* To build a project with checkpoints, follow these steps:
|
||||
* - run `prepareCheckpointBuild` on the desired derivation, e.g.
|
||||
* checkpointArtifacts = prepareCheckpointBuild virtualbox;
|
||||
* - change something you want in the sources of the package,
|
||||
* e.g. using source override:
|
||||
* changedVBox = pkgs.virtuabox.overrideAttrs (old: {
|
||||
* src = path/to/vbox/sources;
|
||||
* }
|
||||
* - use `mkCheckpointedBuild changedVBox buildOutput`
|
||||
* };
|
||||
* - use `mkCheckpointBuild changedVBox checkpointArtifacts`
|
||||
* - enjoy shorter build times
|
||||
*/
|
||||
prepareCheckpointBuild = drv: drv.overrideAttrs (old: {
|
||||
|
@ -24,17 +37,17 @@ rec {
|
|||
# from an earlier build and a later one we store the state of the build
|
||||
# directory before build, but after patch phases.
|
||||
# This way, the same derivation can be used multiple times and only changes are detected.
|
||||
# Additionally Removed files are handled correctly in later builds.
|
||||
# Additionally, removed files are handled correctly in later builds.
|
||||
preBuild = (old.preBuild or "") + ''
|
||||
mkdir -p $out/sources
|
||||
cp -r ./* $out/sources/
|
||||
'';
|
||||
|
||||
# After the build the build directory is copied again
|
||||
# After the build, the build directory is copied again
|
||||
# to get the output files.
|
||||
# We copy the complete build folder, to take care for
|
||||
# Build tools, building in the source directory, instead of
|
||||
# having a build root directory, e.G the Linux kernel.
|
||||
# We copy the complete build folder, to take care of
|
||||
# build tools that build in the source directory, instead of
|
||||
# having a separate build directory such as the Linux kernel.
|
||||
installPhase = ''
|
||||
runHook preCheckpointInstall
|
||||
mkdir -p $out/outputs
|
||||
|
@ -44,26 +57,34 @@ rec {
|
|||
});
|
||||
|
||||
/* Build a derivation based on the checkpoint output generated by
|
||||
* the `prepareCheckpointBuild function.
|
||||
* the `prepareCheckpointBuild` function.
|
||||
*
|
||||
* Usage:
|
||||
* let
|
||||
* checkpointArtifacts = prepareCheckpointBuild drv
|
||||
* in mkCheckpointedBuild drv checkpointArtifacts
|
||||
* checkpointArtifacts = prepareCheckpointBuild drv;
|
||||
* in mkCheckpointBuild drv checkpointArtifacts
|
||||
*/
|
||||
mkCheckpointedBuild = drv: previousBuildArtifacts: drv.overrideAttrs (old: {
|
||||
mkCheckpointBuild = drv: checkpointArtifacts: drv.overrideAttrs (old: {
|
||||
# The actual checkpoint build phase.
|
||||
# We compare the changed sources from a previous build with the current and create a patch
|
||||
# Afterwards we clean the build directory to copy the previous output files (Including the sources)
|
||||
# The source difference patch is applied to get the latest changes again to allow short build times.
|
||||
# We compare the changed sources from a previous build with the current and create a patch.
|
||||
# Afterwards we clean the build directory and copy the previous output files (including the sources).
|
||||
# The source difference patch is then applied to get the latest changes again to allow short build times.
|
||||
preBuild = (old.preBuild or "") + ''
|
||||
set +e
|
||||
diff -ur ${previousBuildArtifacts}/sources ./ > sourceDifference.patch
|
||||
sourceDifferencePatchFile=$(${mktemp}/bin/mktemp)
|
||||
diff -ur ${checkpointArtifacts}/sources ./ > "$sourceDifferencePatchFile"
|
||||
set -e
|
||||
shopt -s extglob dotglob
|
||||
rm -r !("sourceDifference.patch")
|
||||
${pkgs.rsync}/bin/rsync -cutU --chown=$USER:$USER --chmod=+w -r ${previousBuildArtifacts}/outputs/* .
|
||||
patch -p 1 -i sourceDifference.patch
|
||||
shopt -s dotglob
|
||||
rm -r *
|
||||
${rsync}/bin/rsync \
|
||||
--checksum --times --atimes --chown=$USER:$USER --chmod=+w \
|
||||
-r ${checkpointArtifacts}/outputs/ .
|
||||
patch -p 1 -i "$sourceDifferencePatchFile"
|
||||
rm "$sourceDifferencePatchFile"
|
||||
'';
|
||||
});
|
||||
|
||||
mkCheckpointedBuild = lib.warn
|
||||
"`mkCheckpointedBuild` is deprecated, use `mkCheckpointBuild` instead!"
|
||||
mkCheckpointBuild;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ let
|
|||
patch -p1 < ${./hello.patch}
|
||||
'';
|
||||
});
|
||||
checkpointBuiltHello = checkpointBuildTools.mkCheckpointedBuild patchedHello baseHelloArtifacts;
|
||||
checkpointBuiltHello = checkpointBuildTools.mkCheckpointBuild patchedHello baseHelloArtifacts;
|
||||
|
||||
checkpointBuiltHelloWithCheck = checkpointBuiltHello.overrideAttrs (old: {
|
||||
doCheck = true;
|
||||
|
@ -41,7 +41,7 @@ let
|
|||
'';
|
||||
});
|
||||
|
||||
checkpointBuiltHelloWithRemovedFile = checkpointBuildTools.mkCheckpointedBuild patchedHelloRemoveFile baseHelloRemoveFileArtifacts;
|
||||
checkpointBuiltHelloWithRemovedFile = checkpointBuildTools.mkCheckpointBuild patchedHelloRemoveFile baseHelloRemoveFileArtifacts;
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "patched-hello-returns-correct-output";
|
||||
|
|
|
@ -113,7 +113,7 @@ with pkgs;
|
|||
|
||||
install-shell-files = callPackage ./install-shell-files {};
|
||||
|
||||
checkpoint-build = callPackage ./checkpointBuild {};
|
||||
checkpointBuildTools = callPackage ./checkpointBuild {};
|
||||
|
||||
kernel-config = callPackage ./kernel.nix {};
|
||||
|
||||
|
|
Loading…
Reference in a new issue