Files
nix-files/pkgs/by-name/nixpkgs-bootstrap/mkNixpkgs.nix
Colin 58ab12310a toplevel: define a "static-x86_64" and "static-aarch64" host, to experiment with static linking
progress is early, and it's unclear if the work the make gtk, opengl, etc compatible with such a system will ever be feasible
2025-06-28 11:54:47 +00:00

183 lines
8.7 KiB
Nix

# XXX: this is in the bootstrap path;
# this means it has to be evaluatable using only builtins,
# though i'm free to include optional functionality (e.g. update scripts) so long as i gate it behind availability checks.
#
# some considerations in order to keep this file compatible with updateScripts (e.g. `scripts/update sane.nixpkgs-bootstrap.master`):
# - <repo:nixos/nixpkgs:pkgs/common-updater/scripts/update-source-version>, used by `{git,unstableGit}updater`,
# updates the src attributes (rev, url, etc), then attempts to `nix-build` the package, discovers the new
# source hash by scraping the nix error, "hash mismatch in fixed-output derivation ...", then patches in the new hash.
# - this logic only works for nixpkgs fetchers -- NOT (necessarily) the nix builtin fetcher.
# - this process requires that attrs like `sane.nixpkgs-bootstrap.master.src` be _evaluatable_, even if
# e.g. the `patches` i intend to apply don't cleanly apply to the new rev.
#
# this leads to the following updateScript-aware implementation:
# 1. impure.nix evaluates (approximately) to `(import nixpkgs-bootstrap/master.nix { ... }).pkgs.extend (overlays)`.
# - that's `(mkNixpkgs { branch = "master", rev = ... }).pkgs.extend (overlays)`
# 2. we can't guarantee that `sane.nixpkgs-bootstrap.master.src` is actually evaluatable, when updating the bootstrap,
# however we _can_ detect that the bootstrap is being updated during eval of `mkNixpkgs`(*),
# and if so force a failure which the update script will parse identically as if the actual `sane.nixpkgs-bootstrap.master.src` had failed to build.
# (*) `mkNixpkgs` can detect that an updateScript for `foo.src` is running by testing `foo.src.hash`
# against the sentinel value which `update-source-version` assigns during updates.
#
#
# branch workflow:
# - daily:
# - nixos-unstable cut from master after enough packages have been built in caches.
# - every 6 hours:
# - master auto-merged into staging and staging-next
# - staging-next auto-merged into staging.
# - manually, approximately once per month:
# - staging-next is cut from staging.
# - staging-next merged into master.
#
# which branch to source from?
# - nixos-unstable: for everyday development; it provides good caching
# - master: temporarily if i'm otherwise cherry-picking lots of already-applied patches
# - staging-next: if testing stuff that's been PR'd into staging, i.e. base library updates.
# - staging: maybe if no staging-next -> master PR has been cut yet?
{
#VVV these may or may not be available when called. VVV
applyPatches ? null,
fetchpatch2 ? null,
fetchzip ? null,
nixpkgs-bootstrap-updater ? null,
stdenv ? null,
#VVV config
localSystem ? if stdenv != null then stdenv.buildPlatform.system else builtins.currentSystem, #< not available in pure mode
system ? if stdenv != null then stdenv.hostPlatform.system else localSystem,
}:
let
optionalAttrs = cond: attrs: if cond then attrs else {};
# nixpkgs' update-source-version (updateScript) calculates the new hash for a `src` by specifying this hardcoded bogus hash and then attempting to realize it.
sentinelSha256 = "sha256-AzH1rZFqEH8sovZZfJykvsEmCedEZWigQFHWHl6/PdE=";
fetchBootstrap = { url, pname, version, ... }@args: {
# N.B. `outPath` is a special attr name which nix consults when coercing an attrset to a string.
outPath = builtins.fetchTarball ({
inherit url;
name = if version != "" then "${pname}-${version}" else pname;
} // (
builtins.removeAttrs args [ "url" "pname" "version" ]
));
inherit pname version;
};
mkNixpkgs = {
branch,
rev ? "",
sha256 ? "",
version ? "",
}@args: let
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
pname = "nixpkgs-${branch}";
commonNixpkgsArgs = {
inherit localSystem;
# reset impurities
config = {};
overlays = [];
};
# first, fetch the unpatched nixpkgs src:
src' = if fetchzip != null then
fetchzip { inherit url pname version sha256; }
else if sha256 != "" && sha256 != sentinelSha256 then
# fetch nixpkgs using `builtins.fetchTarball`.
# a proper bootstrap would be to return `(import (fetchBootstrap src) {}).fetchzip src`.
# this would be more immune to bugs like <https://github.com/NixOS/nixpkgs/pull/404702#issuecomment-2861798821>,
# however it would force an extra eval of nixpkgs for _every_ user invocation of `nix`.
fetchBootstrap { inherit url pname version sha256; }
else
# we don't know the hash for our nixpkgs.
# likely that an updateScript is running, and attempting to discover the new hash.
# then, use an impure bootstrap to fetch nixpkgs, and then invoke that nixpkgs' `fetchzip`.
# this is expected to fail, however by failing inside a nixpkgs' fetcher, we allow the updateScript to complete.
let
impureNixpkgsSrc = fetchBootstrap { inherit url pname version; };
impureNixpkgs = import impureNixpkgsSrc commonNixpkgsArgs;
in
impureNixpkgs.fetchzip { inherit url pname version sha256; }
;
unpatchedNixpkgs = import src' commonNixpkgsArgs;
applyPatches' = if applyPatches != null then applyPatches else unpatchedNixpkgs.applyPatches;
fetchpatch2' = if fetchpatch2 != null then fetchpatch2 else unpatchedNixpkgs.fetchpatch2;
srcMeta = (src'.meta or {}) // {
position = let
position = builtins.unsafeGetAttrPos "rev" args;
in
"${position.file}:${toString position.line}";
};
patchedSrc = applyPatches' {
name = "nixpkgs-${branch}-sane";
inherit version;
src = {
# required by unstableGitUpdater
gitRepoUrl = "https://github.com/NixOS/nixpkgs.git";
inherit rev;
} // src' // {
meta = srcMeta;
passthru = (src'.passthru or {}) // {
# required so that unstableGitUpdater can know in which file the `rev` variable can be updated in:
# N.B.: declare `meta` in passthru instead of toplevel, so that it takes precedence over the default calculated by `mkDerivation`/`applyPatches`
meta = srcMeta;
# for convenience:
pkgs = nixpkgs;
unpatchedSrc = src';
} // optionalAttrs (nixpkgs-bootstrap-updater != null) {
updateScript = nixpkgs-bootstrap-updater.makeUpdateScript {
inherit branch;
};
};
};
patches = import ./patches.nix { fetchpatch2 = fetchpatch2'; };
# skip applied patches
prePatch = ''
realpatch=$(command -v patch)
patch() {
OUT=$($realpatch "$@") || echo "$OUT" | grep "Skipping patch" -q
}
'';
};
nativeNixpkgsArgs = commonNixpkgsArgs // {
config = {
allowUnfree = true; # NIXPKGS_ALLOW_UNFREE=1
allowBroken = true; # NIXPKGS_ALLOW_BROKEN=1
allowUnsupportedSystem = true; # NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1
};
};
nixpkgsArgs = nativeNixpkgsArgs // optionalAttrs (system != localSystem) {
# XXX(2023/12/11): cache.nixos.org uses `system = ...` instead of `hostPlatform.system`, and that choice impacts the closure of every package.
# so avoid specifying hostPlatform.system on non-cross builds, so i can use upstream caches.
crossSystem = system;
# config = nativeNixpkgsArgs.config // optionalAttrs (system.isStatic && system.hasSharedLibraries) {
# # default nixpkgs' behavior when `isStatic` is to _never_ build shared objects.
# replaceCrossStdenv = { buildPackages, baseStdenv }: baseStdenv.override (old: {
# # mkDerivationFromStdenv = _stdenv: args: baseStdenv.mkDerivation (args // {
# # dontAddStaticConfigureFlags = args.dontAddStaticConfigureFlags or true;
# # });
# # mkDerivationFromStdenv = _stdenv: args: (baseStdenv.mkDerivation args).overrideAttrs (prev: {
# # dontAddStaticConfigureFlags = prev.dontAddStaticConfigureFlags or true;
# # # dontAddStaticConfigureFlags = args.dontAddStaticConfigureFlags or true;
# # });
# mkDerivationFromStdenv = _stdenv: args: (baseStdenv.mkDerivation args).overrideAttrs (prev: {
# # this is not wholly correct; goal is to undo some effects of pkgs/stdenv/adapters.nix' makeStatic
# # to build BOTH .a and .so files (but default to static)
# configureFlags = buildPackages.lib.remove "--disable-shared" (prev.configureFlags or args.configureFlags or []);
# # cmakeFlags = buildPackages.lib.remove "-DBUILD_SHARED_LIBS:BOOL=OFF" (
# # buildPackages.lib.remove "-DCMAKE_SKIP_INSTALL_RPATH=On" (prev.cmakeFlags or args.cmakeFlags or [])
# # );
# });
# });
# };
};
nixpkgs = import patchedSrc nixpkgsArgs;
in
patchedSrc
;
in
mkNixpkgs