nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix

Python: setuptools/wheel/pip now bootstrap from source

Since wheel support was introduced in 2015 we always relied on pre-built
wheels for bootstrapping. Now, we can bootstrap directly from the
sources of these packages in git.

The `bootstrapped-pip` packages is used to build `pip`, `setuptools` and `wheel`,
after which those packages are used to build everything else.

Note that when building `bootstrapped-pip` some errors are shown.
These are not important, the build actually does succeed and work as intended.

authored by

Frederik Rietdijk and committed by
Frederik Rietdijk
56727dc1 1fca2ab5

+79 -55
+36 -39
pkgs/development/python-modules/bootstrapped-pip/default.nix
··· 1 { stdenv, python, fetchPypi, makeWrapper, unzip, makeSetupHook 2 , pipInstallHook 3 , setuptoolsBuildHook 4 - 5 }: 6 7 - let 8 - wheel_source = fetchPypi { 9 - pname = "wheel"; 10 - version = "0.33.6"; 11 - format = "wheel"; 12 - sha256 = "f4da1763d3becf2e2cd92a14a7c920f0f00eca30fdde9ea992c836685b9faf28"; 13 - }; 14 - setuptools_source = fetchPypi { 15 - pname = "setuptools"; 16 - version = "41.4.0"; 17 - format = "wheel"; 18 - sha256 = "8d01f7ee4191d9fdcd9cc5796f75199deccb25b154eba82d44d6a042cf873670"; 19 - }; 20 - 21 - in stdenv.mkDerivation rec { 22 pname = "pip"; 23 - version = "19.3.1"; 24 name = "${python.libPrefix}-bootstrapped-${pname}-${version}"; 25 26 - src = fetchPypi { 27 - inherit pname version; 28 - format = "wheel"; 29 - sha256 = "6917c65fc3769ecdc61405d3dfd97afdedd75808d200b2838d7d961cebc0c2c7"; 30 - }; 31 32 dontUseSetuptoolsBuild = true; 33 34 # Should be propagatedNativeBuildInputs 35 propagatedBuildInputs = [ ··· 22 (setuptoolsBuildHook.override{setuptools=null; wheel=null;}) 23 ]; 24 25 - unpackPhase = '' 26 - mkdir -p $out/${python.sitePackages} 27 - unzip -d $out/${python.sitePackages} $src 28 - unzip -d $out/${python.sitePackages} ${setuptools_source} 29 - unzip -d $out/${python.sitePackages} ${wheel_source} 30 - ''; 31 - 32 postPatch = '' 33 mkdir -p $out/bin 34 ''; ··· 29 nativeBuildInputs = [ makeWrapper unzip ]; 30 buildInputs = [ python ]; 31 32 - installPhase = '' 33 34 - # install pip binary 35 - echo '#!${python.interpreter}' > $out/bin/pip 36 - echo 'import sys;from pip._internal import main' >> $out/bin/pip 37 - echo 'sys.exit(main())' >> $out/bin/pip 38 - chmod +x $out/bin/pip 39 40 - # wrap binaries with PYTHONPATH 41 - for f in $out/bin/*; do 42 - wrapProgram $f --prefix PYTHONPATH ":" $out/${python.sitePackages}/ 43 - done 44 ''; 45 46 }
··· 1 { stdenv, python, fetchPypi, makeWrapper, unzip, makeSetupHook 2 , pipInstallHook 3 , setuptoolsBuildHook 4 + , wheel, pip, setuptools 5 }: 6 7 + stdenv.mkDerivation rec { 8 pname = "pip"; 9 + inherit (pip) version; 10 name = "${python.libPrefix}-bootstrapped-${pname}-${version}"; 11 12 + srcs = [ wheel.src pip.src setuptools.src ]; 13 + sourceRoot = "."; 14 15 dontUseSetuptoolsBuild = true; 16 + dontUsePipInstall = true; 17 18 # Should be propagatedNativeBuildInputs 19 propagatedBuildInputs = [ ··· 38 (setuptoolsBuildHook.override{setuptools=null; wheel=null;}) 39 ]; 40 41 postPatch = '' 42 mkdir -p $out/bin 43 ''; ··· 52 nativeBuildInputs = [ makeWrapper unzip ]; 53 buildInputs = [ python ]; 54 55 + buildPhase = ":"; 56 57 + installPhase = stdenv.lib.strings.optionalString (!stdenv.hostPlatform.isWindows) '' 58 + export SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES=0 59 + '' + '' 60 + # Give folders a known name 61 + mv pip* pip 62 + mv setuptools* setuptools 63 + mv wheel* wheel 64 + # Set up PYTHONPATH. The above folders need to be on PYTHONPATH 65 + # $out is where we are installing to and takes precedence 66 + export PYTHONPATH="$out/${python.sitePackages}:$(pwd)/pip/src:$(pwd)/setuptools:$(pwd)/setuptools/pkg_resources:$(pwd)/wheel" 67 68 + echo "Building setuptools wheel..." 69 + pushd setuptools 70 + ${python.pythonForBuild.interpreter} -m pip install --no-build-isolation --no-index --prefix=$out --ignore-installed --no-dependencies --no-cache --build tmpbuild . 71 + popd 72 + 73 + echo "Building wheel wheel..." 74 + pushd wheel 75 + ${python.pythonForBuild.interpreter} -m pip install --no-build-isolation --no-index --prefix=$out --ignore-installed --no-dependencies --no-cache --build tmpbuild . 76 + popd 77 + 78 + echo "Building pip wheel..." 79 + pushd pip 80 + ${python.pythonForBuild.interpreter} -m pip install --no-build-isolation --no-index --prefix=$out --ignore-installed --no-dependencies --no-cache --build tmpbuild . 81 + popd 82 ''; 83 84 + meta = { 85 + description = "Version of pip used for bootstrapping"; 86 + license = stdenv.lib.unique (pip.meta.license ++ setuptools.meta.license ++ wheel.meta.license); 87 + homepage = pip.meta.homepage; 88 + }; 89 }
+8 -5
pkgs/development/python-modules/pip/default.nix
··· 2 , python 3 , buildPythonPackage 4 , bootstrapped-pip 5 - , fetchPypi 6 , mock 7 , scripttest 8 , virtualenv ··· 17 version = "19.3.1"; 18 format = "other"; 19 20 - src = fetchPypi { 21 - inherit pname version; 22 - sha256 = "21207d76c1031e517668898a6b46a9fb1501c7a4710ef5dfd6a40ad9e6757ea7"; 23 }; 24 25 nativeBuildInputs = [ bootstrapped-pip ]; ··· 37 38 meta = { 39 description = "The PyPA recommended tool for installing Python packages"; 40 - license = lib.licenses.mit; 41 homepage = https://pip.pypa.io/; 42 priority = 10; 43 };
··· 2 , python 3 , buildPythonPackage 4 , bootstrapped-pip 5 + , fetchFromGitHub 6 , mock 7 , scripttest 8 , virtualenv ··· 17 version = "19.3.1"; 18 format = "other"; 19 20 + src = fetchFromGitHub { 21 + owner = "pypa"; 22 + repo = pname; 23 + rev = version; 24 + sha256 = "079gz0v37ah1l4i5iwyfb0d3mni422yv5ynnxa0wcqpnvkc7sfnw"; 25 + name = "${pname}-${version}-source"; 26 }; 27 28 nativeBuildInputs = [ bootstrapped-pip ]; ··· 34 35 meta = { 36 description = "The PyPA recommended tool for installing Python packages"; 37 + license = with lib.licenses; [ mit ]; 38 homepage = https://pip.pypa.io/; 39 priority = 10; 40 };
+28 -7
pkgs/development/python-modules/setuptools/default.nix
··· 1 { stdenv 2 , buildPythonPackage 3 - , fetchPypi 4 , python 5 , wrapPython 6 , unzip ··· 11 , setuptoolsBuildHook 12 }: 13 14 - buildPythonPackage rec { 15 pname = "setuptools"; 16 version = "41.4.0"; 17 # Because of bootstrapping we don't use the setuptoolsBuildHook that comes with format="setuptools" directly. 18 # Instead, we override it to remove setuptools to avoid a circular dependency. 19 # The same is done for pip and the pipInstallHook. 20 format = "other"; 21 22 - src = fetchPypi { 23 - inherit pname version; 24 - extension = "zip"; 25 - sha256 = "7eae782ccf36b790c21bde7d86a4f303a441cd77036b25c559a602cf5186ce4d"; 26 - }; 27 28 nativeBuildInputs = [ 29 bootstrapped-pip
··· 1 { stdenv 2 , buildPythonPackage 3 + , fetchFromGitHub 4 , python 5 , wrapPython 6 , unzip ··· 11 , setuptoolsBuildHook 12 }: 13 14 + let 15 pname = "setuptools"; 16 version = "41.4.0"; 17 + 18 + # Create an sdist of setuptools 19 + sdist = stdenv.mkDerivation rec { 20 + name = "${pname}-${version}-sdist.tar.gz"; 21 + 22 + src = fetchFromGitHub { 23 + owner = "pypa"; 24 + repo = pname; 25 + rev = "v${version}"; 26 + sha256 = "0asxfnsi56r81lm48ynqbfkmm3kvw2jwrlf2l9azn5w6xm30jvp5"; 27 + name = "${pname}-${version}-source"; 28 + }; 29 + 30 + buildPhase = '' 31 + ${python.pythonForBuild.interpreter} bootstrap.py 32 + ${python.pythonForBuild.interpreter} setup.py sdist --formats=gztar 33 + ''; 34 + 35 + installPhase = '' 36 + echo "Moving sdist..." 37 + mv dist/*.tar.gz $out 38 + ''; 39 + }; 40 + in buildPythonPackage rec { 41 + inherit pname version; 42 # Because of bootstrapping we don't use the setuptoolsBuildHook that comes with format="setuptools" directly. 43 # Instead, we override it to remove setuptools to avoid a circular dependency. 44 # The same is done for pip and the pipInstallHook. 45 format = "other"; 46 47 + src = sdist; 48 49 nativeBuildInputs = [ 50 bootstrapped-pip
+7 -4
pkgs/development/python-modules/wheel/default.nix
··· 2 , setuptools 3 , pip 4 , buildPythonPackage 5 - , fetchPypi 6 , pytest 7 , pytestcov 8 , coverage ··· 15 version = "0.33.6"; 16 format = "other"; 17 18 - src = fetchPypi { 19 - inherit pname version; 20 - sha256 = "10c9da68765315ed98850f8e048347c3eb06dd81822dc2ab1d4fde9dc9702646"; 21 }; 22 23 checkInputs = [ pytest pytestcov coverage ];
··· 2 , setuptools 3 , pip 4 , buildPythonPackage 5 + , fetchFromGitHub 6 , pytest 7 , pytestcov 8 , coverage ··· 15 version = "0.33.6"; 16 format = "other"; 17 18 + src = fetchFromGitHub { 19 + owner = "pypa"; 20 + repo = pname; 21 + rev = version; 22 + sha256 = "1bg4bxazsjxp621ymaykd8l75k7rvcvwawlipmjk7nsrl72l4p0s"; 23 + name = "${pname}-${version}-source"; 24 }; 25 26 checkInputs = [ pytest pytestcov coverage ];