From cc3fb612496a08c35fd8daf31101e7c2279ca032 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 18 Feb 2025 15:31:55 +0100 Subject: [PATCH] packaging: Add source overriding "methods" (cherry picked from commit 48fb6fdde955afd1078ea7bb7f0e8c73e0185f8f) --- flake.nix | 21 +++++++ packaging/components.nix | 123 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 136 insertions(+), 8 deletions(-) diff --git a/flake.nix b/flake.nix index 7158f1ac8..a92fd74fc 100644 --- a/flake.nix +++ b/flake.nix @@ -237,6 +237,27 @@ LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out ''; repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { }; + + /** + Checks for our packaging expressions. + This shouldn't build anything significant; just check that things + (including derivations) are _set up_ correctly. + */ + packaging-overriding = + let + pkgs = nixpkgsFor.${system}.native; + nix = self.packages.${system}.nix; + in + assert (nix.appendPatches [ pkgs.emptyFile ]).libs.nix-util.src.patches == [ pkgs.emptyFile ]; + # If this fails, something might be wrong with how we've wired the scope, + # or something could be broken in Nixpkgs. + pkgs.testers.testEqualContents { + assertion = "trivial patch does not change source contents"; + expected = "${./.}"; + actual = + # Same for all components; nix-util is an arbitrary pick + (nix.appendPatches [ pkgs.emptyFile ]).libs.nix-util.src; + }; } // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) { dockerImage = self.hydraJobs.dockerImage.${system}; diff --git a/packaging/components.nix b/packaging/components.nix index 546d5829d..de02f052b 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -32,9 +32,6 @@ let root = ../.; - # Nixpkgs implements this by returning a subpath into the fetched Nix sources. - resolvePath = p: p; - # Indirection for Nixpkgs to override when package.nix files are vendored filesetToSource = lib.fileset.toSource; @@ -84,6 +81,31 @@ let workDir = null; }; + resolveRelPath = p: lib.path.removePrefix root p; + + makeFetchedSourceLayer = + finalScope: finalAttrs: prevAttrs: + let + workDirPath = + # Ideally we'd pick finalAttrs.workDir, but for now `mkDerivation` has + # the requirement that everything except passthru and meta must be + # serialized by mkDerivation, which doesn't work for this. + prevAttrs.workDir; + + workDirSubpath = resolveRelPath workDirPath; + # sources = assert prevAttrs.fileset._type == "fileset"; prevAttrs.fileset; + # src = lib.fileset.toSource { fileset = sources; inherit root; }; + + in + { + sourceRoot = "${finalScope.patchedSrc.name}/" + workDirSubpath; + src = finalScope.patchedSrc; + + # Clear what `derivation` can't/shouldn't serialize; see prevAttrs.workDir. + fileset = null; + workDir = null; + }; + mesonLayer = finalAttrs: prevAttrs: { # NOTE: # As of https://github.com/NixOS/nixpkgs/blob/8baf8241cea0c7b30e0b8ae73474cb3de83c1a30/pkgs/by-name/me/meson/setup-hook.sh#L26, @@ -152,6 +174,17 @@ let enableParallelBuilding = true; }; + /** + Append patches to the source layer. + */ + appendPatches = + scope: patches: + scope.overrideScope ( + finalScope: prevScope: { + patches = prevScope.patches ++ patches; + } + ); + in # This becomes the pkgs.nixComponents attribute set @@ -159,13 +192,24 @@ in version = baseVersion + versionSuffix; inherit versionSuffix; - inherit resolvePath filesetToSource; + inherit filesetToSource; /** A user-provided extension function to apply to each component derivation. */ mesonComponentOverrides = finalAttrs: prevAttrs: { }; + /** + An overridable derivation layer for handling the sources. + */ + sourceLayer = localSourceLayer; + + /** + Resolve a path value to either itself or a path in the `src`, depending + whether `overrideSource` was called. + */ + resolvePath = p: p; + /** Apply an extension function (i.e. overlay-shaped) to all component derivations. */ @@ -177,9 +221,57 @@ in } ); + /** + Provide an alternate source. This allows the expressions to be vendored without copying the sources, + but it does make the build non-granular; all components will use a complete source. + + Packaging expressions will be ignored. + */ + overrideSource = + src: + scope.overrideScope ( + finalScope: prevScope: { + sourceLayer = makeFetchedSourceLayer finalScope; + /** + Unpatched source for the build of Nix. Packaging expressions will be ignored. + */ + src = src; + /** + Patches for the whole Nix source. Changes to packaging expressions will be ignored. + */ + patches = [ ]; + /** + Fetched and patched source to be used in component derivations. + */ + patchedSrc = + if finalScope.patches == [ ] then + src + else + pkgs.buildPackages.srcOnly ( + pkgs.buildPackages.stdenvNoCC.mkDerivation { + name = "${finalScope.src.name or "nix-source"}-patched"; + inherit (finalScope) src patches; + } + ); + resolvePath = p: finalScope.patchedSrc + "/${resolveRelPath p}"; + appendPatches = appendPatches finalScope; + } + ); + + /** + Append patches to be applied to the whole Nix source. + This affects all components. + + Changes to the packaging expressions will be ignored. + */ + appendPatches = + patches: + # switch to "fetched" source first, so that patches apply to the whole tree. + (scope.overrideSource "${./..}").appendPatches patches; + mkMesonDerivation = mkPackageBuilder [ miscGoodPractice - localSourceLayer + scope.sourceLayer setVersionLayer mesonLayer scope.mesonComponentOverrides @@ -187,7 +279,7 @@ in mkMesonExecutable = mkPackageBuilder [ miscGoodPractice bsdNoLinkAsNeeded - localSourceLayer + scope.sourceLayer setVersionLayer mesonLayer mesonBuildLayer @@ -196,7 +288,7 @@ in mkMesonLibrary = mkPackageBuilder [ miscGoodPractice bsdNoLinkAsNeeded - localSourceLayer + scope.sourceLayer mesonLayer setVersionLayer mesonBuildLayer @@ -255,6 +347,21 @@ in */ overrideAllMesonComponents = f: (scope.overrideAllMesonComponents f).nix-everything; - scope = scope; + /** + Append patches to be applied to the whole Nix source. + This affects all components. + + Changes to the packaging expressions will be ignored. + */ + appendPatches = ps: (scope.appendPatches ps).nix-everything; + + /** + Provide an alternate source. This allows the expressions to be vendored without copying the sources, + but it does make the build non-granular; all components will use a complete source. + + Packaging expressions will be ignored. + */ + overrideSource = src: (scope.overrideSource src).nix-everything; + }; }