3
0
Fork 0
forked from mirrors/nixpkgs
nixpkgs/pkgs/development/interpreters/python/cpython/2.7/default.nix

306 lines
11 KiB
Nix
Raw Normal View History

{ stdenv, fetchurl, fetchpatch
, bzip2
, expat
, libffi
, gdbm
, db
, ncurses
, openssl
, readline
, sqlite
2017-01-01 18:37:02 +00:00
, tcl ? null, tk ? null, tix ? null, xlibsWrapper ? null, libX11 ? null, x11Support ? false
, zlib
, self
, configd, coreutils
, autoreconfHook
, python-setup-hook
# Some proprietary libs assume UCS2 unicode, especially on darwin :(
, ucsEncoding ? 4
# For the Python package set
, packageOverrides ? (self: super: {})
, pkgsBuildBuild
, pkgsBuildHost
, pkgsBuildTarget
, pkgsHostHost
, pkgsTargetTarget
, sourceVersion
, sha256
, passthruFun
, static ? false
, enableOptimizations ? (!stdenv.isDarwin)
, pythonAttr ? "python${sourceVersion.major}${sourceVersion.minor}"
2015-03-19 00:50:56 +00:00
}:
2015-03-19 00:50:56 +00:00
assert x11Support -> tcl != null
&& tk != null
&& xlibsWrapper != null
2015-03-19 00:50:56 +00:00
&& libX11 != null;
with stdenv.lib;
let
buildPackages = pkgsBuildHost;
inherit (passthru) pythonForBuild;
passthru = passthruFun rec {
inherit self sourceVersion packageOverrides;
implementation = "cpython";
libPrefix = "python${pythonVersion}";
executable = libPrefix;
pythonVersion = with sourceVersion; "${major}.${minor}";
sitePackages = "lib/${libPrefix}/site-packages";
inherit hasDistutilsCxxPatch;
pythonOnBuildForBuild = pkgsBuildBuild.${pythonAttr};
pythonOnBuildForHost = pkgsBuildHost.${pythonAttr};
pythonOnBuildForTarget = pkgsBuildTarget.${pythonAttr};
pythonOnHostForHost = pkgsHostHost.${pythonAttr};
pythonOnTargetForTarget = pkgsTargetTarget.${pythonAttr} or {};
} // {
inherit ucsEncoding;
};
version = with sourceVersion; "${major}.${minor}.${patch}${suffix}";
src = fetchurl {
url = with sourceVersion; "https://www.python.org/ftp/python/${major}.${minor}.${patch}/Python-${version}.tar.xz";
inherit sha256;
};
hasDistutilsCxxPatch = !(stdenv.cc.isGNU or false);
patches =
[ # Look in C_INCLUDE_PATH and LIBRARY_PATH for stuff.
./search-path.patch
# Python recompiles a Python if the mtime stored *in* the
# pyc/pyo file differs from the mtime of the source file. This
# doesn't work in Nix because Nix changes the mtime of files in
# the Nix store to 1. So treat that as a special case.
./nix-store-mtime.patch
# patch python to put zero timestamp into pyc
# if DETERMINISTIC_BUILD env var is set
./deterministic-build.patch
# Fix python bug #27177 (https://bugs.python.org/issue27177)
# The issue is that `match.group` only recognizes python integers
# instead of everything that has `__index__`.
# This bug was fixed upstream, but not backported to 2.7
(fetchpatch {
name = "re_match_index.patch";
url = "https://bugs.python.org/file43084/re_match_index.patch";
sha256 = "0l9rw6r5r90iybdkp3hhl2pf0h0s1izc68h5d3ywrm92pq32wz57";
})
# Fix race-condition during pyc creation. Has a slight backwards
# incompatible effect: pyc symlinks will now be overridden
# (https://bugs.python.org/issue17222). Included in python >= 3.4,
# backported in debian since 2013.
# https://bugs.python.org/issue13146
./atomic_pyc.patch
cpython: Use --enable-optimizations, for a 16% speedup. Without this flag, the configure script prints a warning at the end, like this (reformatted): If you want a release build with all stable optimizations active (PGO, etc), please run ./configure --enable-optimizations We're doing a build to distribute to people for day-to-day use, doing things other than developing the Python interpreter. So that's certainly a release build -- we're the target audience for this recommendation. --- And, trying it out, upstream isn't kidding! I ran the standard benchmark suite that the CPython developers use for performance work, "pyperformance". Following its usage instructions: https://pyperformance.readthedocs.io/usage.html I ran the whole suite, like so: $ nix-shell -p ./result."$variant" --run ' cd $(mktemp -d); python -m venv venv; . venv/bin/activate pip install pyperformance pyperformance run -o ~/tmp/result.'"$variant"'.json ' and then examined the results with commands like: $ python -m pyperf compare_to --table -G \ ~/tmp/result.{$before,$after}.json Across all the benchmarks in the suite, the median speedup was 16%. (Meaning 1.16x faster; 14% less time). The middle half of them ranged from a 13% to a 22% speedup. Each of the 60 benchmarks in the suite got faster, by speedups ranging from 3% to 53%. --- One reason this isn't just the default to begin with is that, until recently, it made the build a lot slower. What it does is turn on profile-guided optimization, which means first build for profiling, then run some task to get a profile, then build again using the profile. And, short of further customization, the task it would use would be nearly the full test suite, which includes a lot of expensive and slow tests, and can easily take half an hour to run. Happily, in 2019 an upstream developer did the work to carefully select a more appropriate set of tests to use for the profile: https://github.com/python/cpython/commit/4e16a4a31 https://bugs.python.org/issue36044 This suite takes just 2 minutes to run. And the resulting final build is actually slightly faster than with the much longer suite, at least as measured by those standard "pyperformance" benchmarks. That work went into the 3.8 release, but the same list works great if used on older releases too. So, start passing that --enable-optimizations flag; and backport that good-for-PGO set of tests, so that we use it on all releases.
2020-03-29 22:05:04 +01:00
# Backport from CPython 3.8 of a good list of tests to run for PGO.
./profile-task.patch
# Patch is likely to go away in the next release (if there is any)
./CVE-2019-20907.patch
] ++ optionals (x11Support && stdenv.isDarwin) [
./use-correct-tcl-tk-on-darwin.patch
] ++ optionals stdenv.isLinux [
# Disable the use of ldconfig in ctypes.util.find_library (since
# ldconfig doesn't work on NixOS), and don't use
# ctypes.util.find_library during the loading of the uuid module
# (since it will do a futile invocation of gcc (!) to find
# libuuid, slowing down program startup a lot).
./no-ldconfig.patch
] ++ optionals stdenv.hostPlatform.isCygwin [
2014-10-23 20:25:57 +01:00
./2.5.2-ctypes-util-find_library.patch
./2.5.2-tkinter-x11.patch
./2.6.2-ssl-threads.patch
./2.6.5-export-PySignal_SetWakeupFd.patch
./2.6.5-FD_SETSIZE.patch
./2.6.5-ncurses-abi6.patch
./2.7.3-dbm.patch
./2.7.3-dylib.patch
./2.7.3-getpath-exe-extension.patch
./2.7.3-no-libm.patch
] ++ optionals hasDistutilsCxxPatch [
# Patch from http://bugs.python.org/issue1222585 adapted to work with
# `patch -p1' and with a last hunk removed
# Upstream distutils is calling C compiler to compile C++ code, which
# only works for GCC and Apple Clang. This makes distutils to call C++
# compiler when needed.
./python-2.7-distutils-C++.patch
] ++ optional (stdenv.hostPlatform != stdenv.buildPlatform) [
./cross-compile.patch
];
2015-03-19 00:50:56 +00:00
preConfigure = ''
# Purity.
for i in /usr /sw /opt /pkg; do
substituteInPlace ./setup.py --replace $i /no-such-path
done
2014-12-26 17:28:15 +00:00
'' + optionalString (stdenv ? cc && stdenv.cc.libc != null) ''
for i in Lib/plat-*/regen; do
2014-12-26 17:28:15 +00:00
substituteInPlace $i --replace /usr/include/ ${stdenv.cc.libc}/include/
done
2015-06-12 01:58:26 +01:00
'' + optionalString stdenv.isDarwin ''
substituteInPlace configure --replace '`/usr/bin/arch`' '"i386"'
2015-11-03 21:59:39 +00:00
substituteInPlace Lib/multiprocessing/__init__.py \
--replace 'os.popen(comm)' 'os.popen("${coreutils}/bin/nproc")'
'';
configureFlags = optionals enableOptimizations [
cpython: Use --enable-optimizations, for a 16% speedup. Without this flag, the configure script prints a warning at the end, like this (reformatted): If you want a release build with all stable optimizations active (PGO, etc), please run ./configure --enable-optimizations We're doing a build to distribute to people for day-to-day use, doing things other than developing the Python interpreter. So that's certainly a release build -- we're the target audience for this recommendation. --- And, trying it out, upstream isn't kidding! I ran the standard benchmark suite that the CPython developers use for performance work, "pyperformance". Following its usage instructions: https://pyperformance.readthedocs.io/usage.html I ran the whole suite, like so: $ nix-shell -p ./result."$variant" --run ' cd $(mktemp -d); python -m venv venv; . venv/bin/activate pip install pyperformance pyperformance run -o ~/tmp/result.'"$variant"'.json ' and then examined the results with commands like: $ python -m pyperf compare_to --table -G \ ~/tmp/result.{$before,$after}.json Across all the benchmarks in the suite, the median speedup was 16%. (Meaning 1.16x faster; 14% less time). The middle half of them ranged from a 13% to a 22% speedup. Each of the 60 benchmarks in the suite got faster, by speedups ranging from 3% to 53%. --- One reason this isn't just the default to begin with is that, until recently, it made the build a lot slower. What it does is turn on profile-guided optimization, which means first build for profiling, then run some task to get a profile, then build again using the profile. And, short of further customization, the task it would use would be nearly the full test suite, which includes a lot of expensive and slow tests, and can easily take half an hour to run. Happily, in 2019 an upstream developer did the work to carefully select a more appropriate set of tests to use for the profile: https://github.com/python/cpython/commit/4e16a4a31 https://bugs.python.org/issue36044 This suite takes just 2 minutes to run. And the resulting final build is actually slightly faster than with the much longer suite, at least as measured by those standard "pyperformance" benchmarks. That work went into the 3.8 release, but the same list works great if used on older releases too. So, start passing that --enable-optimizations flag; and backport that good-for-PGO set of tests, so that we use it on all releases.
2020-03-29 22:05:04 +01:00
"--enable-optimizations"
] ++ [
2014-10-23 20:25:57 +01:00
"--enable-shared"
"--with-threads"
"--enable-unicode=ucs${toString ucsEncoding}"
] ++ optionals (stdenv.hostPlatform.isCygwin || stdenv.hostPlatform.isAarch64) [
2014-10-23 20:25:57 +01:00
"--with-system-ffi"
] ++ optionals stdenv.hostPlatform.isCygwin [
2014-10-23 20:25:57 +01:00
"--with-system-expat"
"ac_cv_func_bind_textdomain_codeset=yes"
2015-06-12 01:58:26 +01:00
] ++ optionals stdenv.isDarwin [
"--disable-toolbox-glue"
] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
2017-10-18 04:35:20 +01:00
"PYTHON_FOR_BUILD=${getBin buildPackages.python}/bin/python"
"ac_cv_buggy_getaddrinfo=no"
# Assume little-endian IEEE 754 floating point when cross compiling
"ac_cv_little_endian_double=yes"
"ac_cv_big_endian_double=no"
"ac_cv_mixed_endian_double=no"
"ac_cv_x87_double_rounding=yes"
"ac_cv_tanh_preserves_zero_sign=yes"
# Generally assume that things are present and work
"ac_cv_posix_semaphores_enabled=yes"
"ac_cv_broken_sem_getvalue=no"
"ac_cv_wchar_t_signed=yes"
"ac_cv_rshift_extends_sign=yes"
"ac_cv_broken_nice=no"
"ac_cv_broken_poll=no"
"ac_cv_working_tzset=yes"
"ac_cv_have_long_long_format=yes"
"ac_cv_have_size_t_format=yes"
"ac_cv_computed_gotos=yes"
"ac_cv_file__dev_ptmx=yes"
"ac_cv_file__dev_ptc=yes"
cpython: don't use lchmod() on Linux, fix w/musl upstream issue: https://bugs.python.org/issue31940 There are two PR's proposed to fix this, but both seem to be stalling waiting for review. I previously used what appears to be the favored of the two approaches[1] to fix this, with plan of keeping it musl-only until PR was merged. However, while writing up a commit message explaining the problem and why it needed fixing... I investigated a bit and found it increasingly hard to justify anything other than ... simply not using lchmod. Here's what I found: * lchmod is non-POSIX, seems BSD-only these days * Functionality of lchmod isn't supported on Linux * best scenario on Linux would be an error * POSIX does provide lchmod-esque functionality with fchmodat(), which AFAICT is generally preferred. * Python intentionally overlooks fchmodat()[2] electing instead to use lchmod() behavior as a proxy for whether fchmodat() "works". I'm not sure I follow their reasoning... * both glibc and musl provide lchmod impls: * glibc returns ENOSYS "not implemented" * musl implements lchmod with fchmodat(), and so returns EOPNOTSUPP "op not supported" * Python doesn't expect EOPNOTSUPP from lchmod, since it's not valid on BSD's lchmod. * "configure" doesn't actually check lchmod usefully, instead checks for glibc preprocessor defines to indicate if the function is just a stub[3]; somewhat fittingly, if the magic macros are defined then the next line of the C source is "choke me", causing the compiler to trip, fall, and point a finger at whatever is near where it ends up. (somewhat amusing, but AFAIK effective way to get an error :P) I'm leaving out links to threads on mailing lists and such, but for now I hope I've convinced you (or to those reading commit history: explained my reasons) that this is a bit of a mess[4]. And so instead of making a big mess messier, and with hopes of never thinking about this again, I propose we simply tell Python "don't use lchmod" on Linux. [1] https://github.com/python/cpython/pull/4783 [2] https://github.com/python/cpython/blob/28453feaa8d88bbcbf6d834b1d5ca396d17265f2/Lib/os.py#L144 [3] https://github.com/python/cpython/blob/28453feaa8d88bbcbf6d834b1d5ca396d17265f2/configure#L2198 [4] Messes happen, no good intention goes unpunished :).
2018-04-26 01:42:35 +01:00
]
# Never even try to use lchmod on linux,
# don't rely on detecting glibc-isms.
++ optional stdenv.hostPlatform.isLinux "ac_cv_func_lchmod=no"
++ optional static "LDFLAGS=-static";
2014-10-23 20:25:57 +01:00
buildInputs =
optional (stdenv ? cc && stdenv.cc.libc != null) stdenv.cc.libc ++
[ bzip2 openssl zlib ]
++ optional (stdenv.hostPlatform.isCygwin || stdenv.hostPlatform.isAarch64) libffi
++ optional stdenv.hostPlatform.isCygwin expat
++ [ db gdbm ncurses sqlite readline ]
++ optionals x11Support [ tcl tk xlibsWrapper libX11 ]
++ optional (stdenv.isDarwin && configd != null) configd;
2017-10-18 04:35:20 +01:00
nativeBuildInputs =
[ autoreconfHook ]
++ optionals (stdenv.hostPlatform != stdenv.buildPlatform)
[ buildPackages.stdenv.cc buildPackages.python ];
mkPaths = paths: {
C_INCLUDE_PATH = makeSearchPathOutput "dev" "include" paths;
LIBRARY_PATH = makeLibraryPath paths;
};
# Python 2.7 needs this
crossCompileEnv = stdenv.lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform)
{ _PYTHON_HOST_PLATFORM = stdenv.hostPlatform.config; };
# Build the basic Python interpreter without modules that have
# external dependencies.
in with passthru; stdenv.mkDerivation ({
pname = "python";
inherit version;
inherit src patches buildInputs nativeBuildInputs preConfigure configureFlags;
LDFLAGS = stdenv.lib.optionalString (!stdenv.isDarwin) "-lgcc_s";
inherit (mkPaths buildInputs) C_INCLUDE_PATH LIBRARY_PATH;
NIX_CFLAGS_COMPILE = optionalString stdenv.isDarwin "-msse2"
+ optionalString stdenv.hostPlatform.isMusl " -DTHREAD_STACK_SIZE=0x100000";
DETERMINISTIC_BUILD = 1;
setupHook = python-setup-hook sitePackages;
2017-01-01 18:37:02 +00:00
postPatch = optionalString (x11Support && (tix != null)) ''
substituteInPlace "Lib/lib-tk/Tix.py" --replace "os.environ.get('TIX_LIBRARY')" "os.environ.get('TIX_LIBRARY') or '${tix}/lib'"
'';
postInstall =
''
# needed for some packages, especially packages that backport
# functionality to 2.x from 3.x
for item in $out/lib/${libPrefix}/test/*; do
if [[ "$item" != */test_support.py*
&& "$item" != */test/support
&& "$item" != */test/regrtest.py* ]]; then
rm -rf "$item"
else
echo $item
fi
done
touch $out/lib/${libPrefix}/test/__init__.py
ln -s $out/lib/${libPrefix}/pdb.py $out/bin/pdb
ln -s $out/lib/${libPrefix}/pdb.py $out/bin/pdb${sourceVersion.major}.${sourceVersion.minor}
ln -s $out/share/man/man1/{python2.7.1.gz,python.1.gz}
2014-03-17 18:10:00 +00:00
rm "$out"/lib/python*/plat-*/regen # refers to glibc.dev
# Determinism: Windows installers were not deterministic.
# We're also not interested in building Windows installers.
find "$out" -name 'wininst*.exe' | xargs -r rm -f
2017-10-18 04:35:20 +01:00
'' + optionalString (stdenv.hostPlatform == stdenv.buildPlatform)
''
# 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 -
'' + optionalString stdenv.hostPlatform.isCygwin ''
cp libpython2.7.dll.a $out/lib
'';
inherit passthru;
postFixup = ''
# Include a sitecustomize.py file. Note it causes an error when it's in postInstall with 2.7.
cp ${../../sitecustomize.py} $out/${sitePackages}/sitecustomize.py
'';
enableParallelBuilding = true;
doCheck = false; # expensive, and fails
meta = {
homepage = "http://python.org";
description = "A high-level dynamically-typed programming language";
longDescription = ''
Python is a remarkably powerful dynamic programming language that
is used in a wide variety of application domains. Some of its key
distinguishing features include: clear, readable syntax; strong
introspection capabilities; intuitive object orientation; natural
expression of procedural code; full modularity, supporting
hierarchical packages; exception-based error handling; and very
high level dynamic data types.
'';
license = stdenv.lib.licenses.psfl;
platforms = stdenv.lib.platforms.all;
maintainers = with stdenv.lib.maintainers; [ fridh ];
# Higher priority than Python 3.x so that `/bin/python` points to `/bin/python2`
# in case both 2 and 3 are installed.
priority = -100;
};
} // crossCompileEnv)