Python 3.5: improve determinism

- Windows installers are indeterministic and we don't need them.
- since Python 3 ensurepip is installed by default. pip is indeteministic and we don't need it.
- rebuild bytecode to ensure its deterministic
This commit is contained in:
Frederik Rietdijk 2017-02-09 10:14:21 +01:00
parent 09f6b03b2e
commit 8970a9c86e
1 changed files with 33 additions and 7 deletions

View File

@ -50,6 +50,12 @@ in stdenv.mkDerivation {
NIX_LDFLAGS = optionalString stdenv.isLinux "-lgcc_s"; NIX_LDFLAGS = optionalString stdenv.isLinux "-lgcc_s";
# Determinism: The interpreter is patched to write null timestamps when compiling python files.
# This way python doesn't try to update them when we freeze timestamps in nix store.
DETERMINISTIC_BUILD=1;
# Determinism: We fix the hashes of str, bytes and datetime objects.
PYTHONHASHSEED=0;
prePatch = optionalString stdenv.isDarwin '' prePatch = optionalString stdenv.isDarwin ''
substituteInPlace configure --replace '`/usr/bin/arch`' '"i386"' substituteInPlace configure --replace '`/usr/bin/arch`' '"i386"'
substituteInPlace configure --replace '-Wl,-stack_size,1000000' ' ' substituteInPlace configure --replace '-Wl,-stack_size,1000000' ' '
@ -63,10 +69,25 @@ in stdenv.mkDerivation {
}) })
]; ];
postPatch = optionalString (x11Support && (tix != null)) '' postPatch = ''
# Determinism
substituteInPlace "Lib/py_compile.py" --replace "source_stats['mtime']" "(1 if 'DETERMINISTIC_BUILD' in os.environ else source_stats['mtime'])"
# Determinism. This is done unconditionally
substituteInPlace "Lib/importlib/_bootstrap_external.py" --replace "source_mtime = int(st['mtime'])" "source_mtime = 1"
'' + optionalString (x11Support && (tix != null)) ''
substituteInPlace "Lib/tkinter/tix.py" --replace "os.environ.get('TIX_LIBRARY')" "os.environ.get('TIX_LIBRARY') or '${tix}/lib'" substituteInPlace "Lib/tkinter/tix.py" --replace "os.environ.get('TIX_LIBRARY')" "os.environ.get('TIX_LIBRARY') or '${tix}/lib'"
''; '';
CPPFLAGS="${concatStringsSep " " (map (p: "-I${getDev p}/include") buildInputs)}";
LDFLAGS="${concatStringsSep " " (map (p: "-L${getLib p}/lib") buildInputs)}";
LIBS="${optionalString (!stdenv.isDarwin) "-lcrypt"} ${optionalString (ncurses != null) "-lncurses"}";
configureFlags = [
"--enable-shared"
"--with-threads"
"--without-ensurepip"
];
preConfigure = '' preConfigure = ''
for i in /usr /sw /opt /pkg; do # improve purity for i in /usr /sw /opt /pkg; do # improve purity
substituteInPlace ./setup.py --replace $i /no-such-path substituteInPlace ./setup.py --replace $i /no-such-path
@ -75,12 +96,6 @@ in stdenv.mkDerivation {
export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -msse2" export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -msse2"
export MACOSX_DEPLOYMENT_TARGET=10.6 export MACOSX_DEPLOYMENT_TARGET=10.6
''} ''}
configureFlagsArray=( --enable-shared --with-threads
CPPFLAGS="${concatStringsSep " " (map (p: "-I${getDev p}/include") buildInputs)}"
LDFLAGS="${concatStringsSep " " (map (p: "-L${getLib p}/lib") buildInputs)}"
LIBS="${optionalString (!stdenv.isDarwin) "-lcrypt"} ${optionalString (ncurses != null) "-lncurses"}"
)
''; '';
setupHook = ./setup-hook.sh; setupHook = ./setup-hook.sh;
@ -103,6 +118,10 @@ in stdenv.mkDerivation {
# Python on Nix is not manylinux1 compatible. https://github.com/NixOS/nixpkgs/issues/18484 # Python on Nix is not manylinux1 compatible. https://github.com/NixOS/nixpkgs/issues/18484
echo "manylinux1_compatible=False" >> $out/lib/${libPrefix}/_manylinux.py echo "manylinux1_compatible=False" >> $out/lib/${libPrefix}/_manylinux.py
# Determinism: Windows installers were not deterministic.
# We're also not interested in building Windows installers.
find "$out" -name 'wininst*.exe' | xargs -r rm -f
# Use Python3 as default python # Use Python3 as default python
ln -s "$out/bin/idle3" "$out/bin/idle" ln -s "$out/bin/idle3" "$out/bin/idle"
ln -s "$out/bin/pip3" "$out/bin/pip" ln -s "$out/bin/pip3" "$out/bin/pip"
@ -110,6 +129,13 @@ in stdenv.mkDerivation {
ln -s "$out/bin/python3" "$out/bin/python" ln -s "$out/bin/python3" "$out/bin/python"
ln -s "$out/bin/python3-config" "$out/bin/python-config" ln -s "$out/bin/python3-config" "$out/bin/python-config"
ln -s "$out/lib/pkgconfig/python3.pc" "$out/lib/pkgconfig/python.pc" ln -s "$out/lib/pkgconfig/python3.pc" "$out/lib/pkgconfig/python.pc"
# Determinism: rebuild all bytecode
# We exclude lib2to3 because that's Python 2 code which fails
# We rebuild three times, once for each optimization level
find $out -name "*.py" | $out/bin/python -m compileall -q -f -x "lib2to3" -i -
find $out -name "*.py" | $out/bin/python -O -m compileall -q -f -x "lib2to3" -i -
find $out -name "*.py" | $out/bin/python -OO -m compileall -q -f -x "lib2to3" -i -
''; '';
postFixup = '' postFixup = ''