diff options
author | Janne Heß <dasJ@users.noreply.github.com> | 2023-12-19 11:37:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-19 11:37:15 +0100 |
commit | 5eed5416ffa70d1a6c1ff00548c746014df7e2c6 (patch) | |
tree | 6afba481a6b8ab7c9b99392142087adb83e8ee59 /pkgs/build-support | |
parent | 6e207024d379a6abb4f7c30a113eeb6ce7203288 (diff) | |
parent | 5ebb78d9522ce232286ae0518a1020b8e099e7e1 (diff) |
Merge pull request #167670 from messemar/incremental-builds
incremental builds: add derivation override functions
Diffstat (limited to 'pkgs/build-support')
-rw-r--r-- | pkgs/build-support/checkpoint-build.nix | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/pkgs/build-support/checkpoint-build.nix b/pkgs/build-support/checkpoint-build.nix new file mode 100644 index 0000000000000..e08dde353e891 --- /dev/null +++ b/pkgs/build-support/checkpoint-build.nix @@ -0,0 +1,69 @@ +{ pkgs }: +rec { + /* Prepare a derivation for local builds. + * + * This function prepares checkpoint builds by provinding, + * containing 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) + * changedVBox = pkgs.virtuabox.overrideAttrs (old: { + * src = path/to/vbox/sources; + * } + * - use `mkCheckpointedBuild changedVBox buildOutput` + * - enjoy shorter build times + */ + prepareCheckpointBuild = drv: drv.overrideAttrs (old: { + outputs = [ "out" ]; + name = drv.name + "-checkpointArtifacts"; + # 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 + # 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. + preBuild = (old.preBuild or "") + '' + mkdir -p $out/sources + cp -r ./* $out/sources/ + ''; + + # 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. + installPhase = '' + runHook preCheckpointInstall + mkdir -p $out/outputs + cp -r ./* $out/outputs/ + runHook postCheckpointInstall + ''; + }); + + /* Build a derivation based on the checkpoint output generated by + * the `prepareCheckpointBuild function. + * + * Usage: + * let + * checkpointArtifacts = prepareCheckpointBuild drv + * in mkCheckpointedBuild drv checkpointArtifacts + */ + mkCheckpointedBuild = drv: previousBuildArtifacts: 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. + preBuild = (old.preBuild or "") + '' + set +e + diff -ur ${previousBuildArtifacts}/sources ./ > sourceDifference.patch + 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 + ''; + }); +} |