mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-22 06:53:01 +00:00
Merge pull request #279487 from bryango/checkpoint-build-polish
checkpointBuildTools: mkCheckpointedBuild -> mkCheckpointBuild
This commit is contained in:
commit
098ffee102
@ -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.
|
`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.
|
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:
|
To change a normal derivation to a checkpoint based build, these steps must be taken:
|
||||||
- apply `prepareCheckpointBuild` on the desired derivation
|
- apply `prepareCheckpointBuild` on the desired derivation, e.g.
|
||||||
e.g.:
|
|
||||||
```nix
|
```nix
|
||||||
checkpointArtifacts = (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox);
|
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
|
```nix
|
||||||
changedVBox = pkgs.virtualbox.overrideAttrs (old: {
|
changedVBox = pkgs.virtualbox.overrideAttrs (old: {
|
||||||
src = path/to/vbox/sources;
|
src = path/to/vbox/sources;
|
||||||
}
|
});
|
||||||
```
|
```
|
||||||
- use `mkCheckpointedBuild changedVBox buildOutput`
|
- use `mkCheckpointBuild changedVBox checkpointArtifacts`
|
||||||
- enjoy shorter build times
|
- enjoy shorter build times
|
||||||
|
|
||||||
## Example {#sec-checkpoint-build-example}
|
## Example {#sec-checkpoint-build-example}
|
||||||
```nix
|
```nix
|
||||||
{ pkgs ? import <nixpkgs> {} }: with (pkgs) checkpointBuildTools;
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
let
|
let
|
||||||
helloCheckpoint = checkpointBuildTools.prepareCheckpointBuild pkgs.hello;
|
inherit (pkgs.checkpointBuildTools)
|
||||||
|
prepareCheckpointBuild
|
||||||
|
mkCheckpointBuild
|
||||||
|
;
|
||||||
|
helloCheckpoint = prepareCheckpointBuild pkgs.hello;
|
||||||
changedHello = pkgs.hello.overrideAttrs (_: {
|
changedHello = pkgs.hello.overrideAttrs (_: {
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
patchPhase = ''
|
patchPhase = ''
|
||||||
sed -i 's/Hello, world!/Hello, Nix!/g' src/hello.c
|
sed -i 's/Hello, world!/Hello, Nix!/g' src/hello.c
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
in checkpointBuildTools.mkCheckpointBuild changedHello helloCheckpoint
|
in mkCheckpointBuild changedHello helloCheckpoint
|
||||||
```
|
```
|
||||||
|
@ -1,40 +1,53 @@
|
|||||||
{ 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 {
|
rec {
|
||||||
/* Prepare a derivation for local builds.
|
/* Prepare a derivation for local builds.
|
||||||
*
|
*
|
||||||
* This function prepares checkpoint builds by provinding,
|
* This function prepares checkpoint builds by storing
|
||||||
* containing the build output and the sources for cross checking.
|
* the build output and the sources for cross checking.
|
||||||
* The build output can be used later to allow checkpoint builds
|
* The build output can be used later to allow checkpoint builds
|
||||||
* by passing the derivation output to the `mkCheckpointBuild` function.
|
* by passing the derivation output to the `mkCheckpointBuild` function.
|
||||||
*
|
*
|
||||||
* To build a project with checkpoints follow these steps:
|
* To build a project with checkpoints, follow these steps:
|
||||||
* - run prepareIncrementalBuild on the desired derivation
|
* - run `prepareCheckpointBuild` on the desired derivation, e.g.
|
||||||
* e.G `incrementalBuildArtifacts = (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox);`
|
* checkpointArtifacts = prepareCheckpointBuild virtualbox;
|
||||||
* - change something you want in the sources of the package( e.G using source override)
|
* - change something you want in the sources of the package,
|
||||||
* changedVBox = pkgs.virtuabox.overrideAttrs (old: {
|
* e.g. using source override:
|
||||||
* src = path/to/vbox/sources;
|
* changedVBox = pkgs.virtuabox.overrideAttrs (old: {
|
||||||
* }
|
* src = path/to/vbox/sources;
|
||||||
* - use `mkCheckpointedBuild changedVBox buildOutput`
|
* };
|
||||||
|
* - use `mkCheckpointBuild changedVBox checkpointArtifacts`
|
||||||
* - enjoy shorter build times
|
* - enjoy shorter build times
|
||||||
*/
|
*/
|
||||||
prepareCheckpointBuild = drv: drv.overrideAttrs (old: {
|
prepareCheckpointBuild = drv: drv.overrideAttrs (old: {
|
||||||
outputs = [ "out" ];
|
outputs = [ "out" ];
|
||||||
name = drv.name + "-checkpointArtifacts";
|
name = drv.name + "-checkpointArtifacts";
|
||||||
# To determine differences between the state of the build directory
|
# To determine differences between the state of the build directory
|
||||||
# from an earlier build and a later one we store the state of the build
|
# from an earlier build and a later one we store the state of the build
|
||||||
# directory before build, but after patch phases.
|
# directory before build, but after patch phases.
|
||||||
# This way, the same derivation can be used multiple times and only changes are detected.
|
# 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 "") + ''
|
preBuild = (old.preBuild or "") + ''
|
||||||
mkdir -p $out/sources
|
mkdir -p $out/sources
|
||||||
cp -r ./* $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.
|
# to get the output files.
|
||||||
# We copy the complete build folder, to take care for
|
# We copy the complete build folder, to take care of
|
||||||
# Build tools, building in the source directory, instead of
|
# build tools that build in the source directory, instead of
|
||||||
# having a build root directory, e.G the Linux kernel.
|
# having a separate build directory such as the Linux kernel.
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
runHook preCheckpointInstall
|
runHook preCheckpointInstall
|
||||||
mkdir -p $out/outputs
|
mkdir -p $out/outputs
|
||||||
@ -44,26 +57,34 @@ rec {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Build a derivation based on the checkpoint output generated by
|
/* Build a derivation based on the checkpoint output generated by
|
||||||
* the `prepareCheckpointBuild function.
|
* the `prepareCheckpointBuild` function.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* let
|
* let
|
||||||
* checkpointArtifacts = prepareCheckpointBuild drv
|
* checkpointArtifacts = prepareCheckpointBuild drv;
|
||||||
* in mkCheckpointedBuild drv checkpointArtifacts
|
* in mkCheckpointBuild drv checkpointArtifacts
|
||||||
*/
|
*/
|
||||||
mkCheckpointedBuild = drv: previousBuildArtifacts: drv.overrideAttrs (old: {
|
mkCheckpointBuild = drv: checkpointArtifacts: drv.overrideAttrs (old: {
|
||||||
# The actual checkpoint build phase.
|
# The actual checkpoint build phase.
|
||||||
# We compare the changed sources from a previous build with the current and create a patch
|
# 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)
|
# Afterwards we clean the build directory and 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.
|
# The source difference patch is then applied to get the latest changes again to allow short build times.
|
||||||
preBuild = (old.preBuild or "") + ''
|
preBuild = (old.preBuild or "") + ''
|
||||||
set +e
|
set +e
|
||||||
diff -ur ${previousBuildArtifacts}/sources ./ > sourceDifference.patch
|
sourceDifferencePatchFile=$(${mktemp}/bin/mktemp)
|
||||||
|
diff -ur ${checkpointArtifacts}/sources ./ > "$sourceDifferencePatchFile"
|
||||||
set -e
|
set -e
|
||||||
shopt -s extglob dotglob
|
shopt -s dotglob
|
||||||
rm -r !("sourceDifference.patch")
|
rm -r *
|
||||||
${pkgs.rsync}/bin/rsync -cutU --chown=$USER:$USER --chmod=+w -r ${previousBuildArtifacts}/outputs/* .
|
${rsync}/bin/rsync \
|
||||||
patch -p 1 -i sourceDifference.patch
|
--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}
|
patch -p1 < ${./hello.patch}
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
checkpointBuiltHello = checkpointBuildTools.mkCheckpointedBuild patchedHello baseHelloArtifacts;
|
checkpointBuiltHello = checkpointBuildTools.mkCheckpointBuild patchedHello baseHelloArtifacts;
|
||||||
|
|
||||||
checkpointBuiltHelloWithCheck = checkpointBuiltHello.overrideAttrs (old: {
|
checkpointBuiltHelloWithCheck = checkpointBuiltHello.overrideAttrs (old: {
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
@ -41,7 +41,7 @@ let
|
|||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
|
||||||
checkpointBuiltHelloWithRemovedFile = checkpointBuildTools.mkCheckpointedBuild patchedHelloRemoveFile baseHelloRemoveFileArtifacts;
|
checkpointBuiltHelloWithRemovedFile = checkpointBuildTools.mkCheckpointBuild patchedHelloRemoveFile baseHelloRemoveFileArtifacts;
|
||||||
in
|
in
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "patched-hello-returns-correct-output";
|
name = "patched-hello-returns-correct-output";
|
||||||
|
@ -113,7 +113,7 @@ with pkgs;
|
|||||||
|
|
||||||
install-shell-files = callPackage ./install-shell-files {};
|
install-shell-files = callPackage ./install-shell-files {};
|
||||||
|
|
||||||
checkpoint-build = callPackage ./checkpointBuild {};
|
checkpointBuildTools = callPackage ./checkpointBuild {};
|
||||||
|
|
||||||
kernel-config = callPackage ./kernel.nix {};
|
kernel-config = callPackage ./kernel.nix {};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user