From b634edb1a4223649e85da5cdad3176cc9e379e0c Mon Sep 17 00:00:00 2001 From: DavHau Date: Sat, 10 May 2025 15:23:38 +0700 Subject: [PATCH] python3Minimal: make it truly minimal Make python3 minimal truly minimal by disabling some more dependencies. This makes it easy to bootstrap python. After this, the only remaining runtime deps for python3Minimal are: - bash (for launching subprocesses with shell=True) - libc - libgcc - libffi All remaining deps seem to be fundamental and cannot be further reduced, except bash which could potentially be removed and replaced with `$SHELL` at runtime. Done: - add some more withXXX switches to the cpython package - use new switches in python3Minimal to disable some deps - set some other deps to null in python3Minimal - Set `allowedReferences` to guarantee that the closure remains minimal in the future. --- .../interpreters/python/cpython/default.nix | 32 +++++++++++++++++-- .../interpreters/python/default.nix | 14 ++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/pkgs/development/interpreters/python/cpython/default.nix b/pkgs/development/interpreters/python/cpython/default.nix index ba93166c2b66..4bbe05b0e4f0 100644 --- a/pkgs/development/interpreters/python/cpython/default.nix +++ b/pkgs/development/interpreters/python/cpython/default.nix @@ -14,10 +14,12 @@ # runtime dependencies bzip2, + withExpat ? true, expat, libffi, libuuid, libxcrypt, + withMpdecimal ? true, mpdecimal, ncurses, openssl, @@ -92,6 +94,9 @@ # tests testers, + # allow pythonMinimal to prevent accidental dependencies it doesn't want + allowedReferenceNames ? [ ], + }@inputs: # Note: this package is used for bootstrapping fetchurl, and thus @@ -216,17 +221,21 @@ let buildInputs = lib.filter (p: p != null) ( [ bzip2 - expat libffi libuuid libxcrypt - mpdecimal ncurses openssl sqlite xz zlib ] + ++ optionals withMpdecimal [ + mpdecimal + ] + ++ optionals withExpat [ + expat + ] ++ optionals bluezSupport [ bluez ] @@ -420,7 +429,7 @@ stdenv.mkDerivation (finalAttrs: { env = { CPPFLAGS = concatStringsSep " " (map (p: "-I${getDev p}/include") buildInputs); LDFLAGS = concatStringsSep " " (map (p: "-L${getLib p}/lib") buildInputs); - LIBS = "${optionalString (!stdenv.hostPlatform.isDarwin) "-lcrypt"}"; + LIBS = "${optionalString (!stdenv.hostPlatform.isDarwin && libxcrypt != null) "-lcrypt"}"; NIX_LDFLAGS = lib.optionalString (stdenv.cc.isGNU && !stdenv.hostPlatform.isStatic) ( { "glibc" = "-lgcc_s"; @@ -436,7 +445,11 @@ stdenv.mkDerivation (finalAttrs: { configureFlags = [ "--without-ensurepip" + ] + ++ optionals withExpat [ "--with-system-expat" + ] + ++ optionals withMpdecimal [ "--with-system-libmpdec" ] ++ optionals (openssl != null) [ @@ -743,6 +756,19 @@ stdenv.mkDerivation (finalAttrs: { buildPackages.bashNonInteractive ]; + # Optionally set allowedReferences to guarantee minimal dependencies + # Allows python3Minimal to stay minimal and not have deps added by accident + # Doesn't do anything if allowedReferenceNames is empty (was not set) + ${if allowedReferenceNames != [ ] then "allowedReferences" else null} = + # map allowed names to their derivations + (map (name: inputs.${name}) allowedReferenceNames) ++ [ + # any version of python depends on libc and libgcc + stdenv.cc.cc.lib + stdenv.cc.libc + # allows python referring to its own store path + "out" + ]; + separateDebugInfo = true; passthru = passthru // { diff --git a/pkgs/development/interpreters/python/default.nix b/pkgs/development/interpreters/python/default.nix index d738e391ea86..127bc8f87912 100644 --- a/pkgs/development/interpreters/python/default.nix +++ b/pkgs/development/interpreters/python/default.nix @@ -113,6 +113,10 @@ sqlite = null; tzdata = null; libuuid = null; + bzip2 = null; + libxcrypt = null; + xz = null; + zlib = null; libffi = libffiBoot; # without test suite stripConfig = true; stripIdlelib = true; @@ -124,6 +128,16 @@ enableOptimizations = false; enableLTO = false; mimetypesSupport = false; + withExpat = false; + withMpdecimal = false; + /* + The actual 'allowedReferences' attribute is set inside the cpython derivation. + This is necessary in order to survive overrides of dependencies. + */ + allowedReferenceNames = [ + "bashNonInteractive" + "libffi" + ]; } // sources.python312 )).overrideAttrs