2015-01-11 11:37:01 +08:00
|
|
|
import os
|
2015-01-21 07:07:53 +08:00
|
|
|
import re
|
2015-02-02 22:09:35 +08:00
|
|
|
from contextlib import closing
|
2015-02-17 16:21:15 +08:00
|
|
|
from llnl.util.lang import match_predicate
|
2015-12-02 22:20:11 +08:00
|
|
|
from spack.util.environment import *
|
2015-02-02 22:09:35 +08:00
|
|
|
|
2015-02-09 18:54:49 +08:00
|
|
|
from spack import *
|
|
|
|
import spack
|
|
|
|
|
2015-01-08 03:48:21 +08:00
|
|
|
|
2014-10-31 06:02:06 +08:00
|
|
|
class Python(Package):
|
|
|
|
"""The Python programming language."""
|
|
|
|
homepage = "http://www.python.org"
|
2016-01-09 06:16:30 +08:00
|
|
|
url = "http://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz"
|
2014-10-31 06:02:06 +08:00
|
|
|
|
2015-01-08 03:48:21 +08:00
|
|
|
extendable = True
|
|
|
|
|
2016-01-09 06:16:30 +08:00
|
|
|
version('3.5.1', 'be78e48cdfc1a7ad90efff146dce6cfe')
|
|
|
|
version('3.5.0', 'a56c0c0b45d75a0ec9c6dee933c41c36')
|
|
|
|
version('2.7.11', '6b6076ec9e93f05dd63e47eb9c15728b', preferred=True)
|
|
|
|
version('2.7.10', 'd7547558fd673bd9d38e2108c6b42521')
|
|
|
|
version('2.7.9', '5eebcaa0030dc4061156d3429657fb83')
|
|
|
|
version('2.7.8', 'd4bca0159acb0b44a781292b5231936f')
|
2014-10-31 06:02:06 +08:00
|
|
|
|
|
|
|
depends_on("openssl")
|
2014-11-03 16:15:05 +08:00
|
|
|
depends_on("bzip2")
|
|
|
|
depends_on("readline")
|
|
|
|
depends_on("ncurses")
|
2014-10-31 06:02:06 +08:00
|
|
|
depends_on("sqlite")
|
2015-12-02 22:20:11 +08:00
|
|
|
depends_on("zlib")
|
2014-10-31 06:02:06 +08:00
|
|
|
|
|
|
|
def install(self, spec, prefix):
|
2014-11-03 16:15:05 +08:00
|
|
|
# Need this to allow python build to find the Python installation.
|
|
|
|
env['PYTHONHOME'] = prefix
|
2015-11-20 06:52:22 +08:00
|
|
|
env['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
|
2014-11-03 16:15:05 +08:00
|
|
|
|
2015-12-02 22:20:11 +08:00
|
|
|
# Rest of install is pretty standard except setup.py needs to be able to read the CPPFLAGS
|
|
|
|
# and LDFLAGS as it scans for the library and headers to build
|
2015-12-22 22:50:18 +08:00
|
|
|
configure_args= [
|
|
|
|
"--prefix=%s" % prefix,
|
2014-11-03 16:15:05 +08:00
|
|
|
"--with-threads",
|
2015-12-02 22:20:11 +08:00
|
|
|
"--enable-shared",
|
|
|
|
"CPPFLAGS=-I%s/include -I%s/include -I%s/include -I%s/include -I%s/include -I%s/include" % (
|
|
|
|
spec['openssl'].prefix, spec['bzip2'].prefix,
|
|
|
|
spec['readline'].prefix, spec['ncurses'].prefix,
|
|
|
|
spec['sqlite'].prefix, spec['zlib'].prefix),
|
|
|
|
"LDFLAGS=-L%s/lib -L%s/lib -L%s/lib -L%s/lib -L%s/lib -L%s/lib" % (
|
|
|
|
spec['openssl'].prefix, spec['bzip2'].prefix,
|
|
|
|
spec['readline'].prefix, spec['ncurses'].prefix,
|
2015-12-22 22:50:18 +08:00
|
|
|
spec['sqlite'].prefix, spec['zlib'].prefix)
|
|
|
|
]
|
|
|
|
if spec.satisfies('@3:'):
|
|
|
|
configure_args.append('--without-ensurepip')
|
|
|
|
configure(*configure_args)
|
2014-10-31 06:02:06 +08:00
|
|
|
make()
|
|
|
|
make("install")
|
2015-01-11 11:37:01 +08:00
|
|
|
|
2016-02-19 07:45:29 +08:00
|
|
|
# Modify compiler paths in configuration files. This is necessary for
|
|
|
|
# building site packages outside of spack
|
|
|
|
filter_file(r'([/s]=?)([\S=]*)/lib/spack/env(/[^\s/]*)?/(\S*)(\s)',
|
|
|
|
(r'\4\5'),
|
|
|
|
join_path(prefix.lib, 'python%d.%d' % self.version[:2], '_sysconfigdata.py'))
|
|
|
|
|
|
|
|
python3_version = ''
|
|
|
|
if spec.satisfies('@3:'):
|
|
|
|
python3_version = '-%d.%dm' % self.version[:2]
|
|
|
|
makefile_filepath = join_path(prefix.lib, 'python%d.%d' % self.version[:2], 'config%s' % python3_version, 'Makefile')
|
|
|
|
filter_file(r'([/s]=?)([\S=]*)/lib/spack/env(/[^\s/]*)?/(\S*)(\s)',
|
|
|
|
(r'\4\5'),
|
|
|
|
makefile_filepath)
|
|
|
|
|
2015-01-11 11:37:01 +08:00
|
|
|
|
2015-02-02 22:09:35 +08:00
|
|
|
# ========================================================================
|
|
|
|
# Set up environment to make install easy for python extensions.
|
|
|
|
# ========================================================================
|
|
|
|
|
2015-01-20 16:23:16 +08:00
|
|
|
@property
|
|
|
|
def python_lib_dir(self):
|
|
|
|
return os.path.join('lib', 'python%d.%d' % self.version[:2])
|
|
|
|
|
|
|
|
|
2015-02-15 17:59:36 +08:00
|
|
|
@property
|
|
|
|
def python_include_dir(self):
|
|
|
|
return os.path.join('include', 'python%d.%d' % self.version[:2])
|
|
|
|
|
|
|
|
|
2015-01-20 16:23:16 +08:00
|
|
|
@property
|
|
|
|
def site_packages_dir(self):
|
|
|
|
return os.path.join(self.python_lib_dir, 'site-packages')
|
|
|
|
|
|
|
|
|
2015-02-09 11:41:17 +08:00
|
|
|
def setup_dependent_environment(self, module, spec, ext_spec):
|
2015-01-11 11:37:01 +08:00
|
|
|
"""Called before python modules' install() methods.
|
|
|
|
|
|
|
|
In most cases, extensions will only need to have one line::
|
|
|
|
|
|
|
|
python('setup.py', 'install', '--prefix=%s' % prefix)
|
|
|
|
"""
|
|
|
|
# Python extension builds can have a global python executable function
|
2015-12-02 22:20:11 +08:00
|
|
|
if self.version >= Version("3.0.0") and self.version < Version("4.0.0"):
|
|
|
|
module.python = Executable(join_path(spec.prefix.bin, 'python3'))
|
|
|
|
else:
|
|
|
|
module.python = Executable(join_path(spec.prefix.bin, 'python'))
|
2015-01-11 11:37:01 +08:00
|
|
|
|
|
|
|
# Add variables for lib/pythonX.Y and lib/pythonX.Y/site-packages dirs.
|
2015-02-15 17:59:36 +08:00
|
|
|
module.python_lib_dir = os.path.join(ext_spec.prefix, self.python_lib_dir)
|
|
|
|
module.python_include_dir = os.path.join(ext_spec.prefix, self.python_include_dir)
|
|
|
|
module.site_packages_dir = os.path.join(ext_spec.prefix, self.site_packages_dir)
|
2015-01-11 11:37:01 +08:00
|
|
|
|
|
|
|
# Make the site packages directory if it does not exist already.
|
|
|
|
mkdirp(module.site_packages_dir)
|
2015-01-20 16:23:16 +08:00
|
|
|
|
2015-02-09 11:39:36 +08:00
|
|
|
# Set PYTHONPATH to include site-packages dir for the
|
|
|
|
# extension and any other python extensions it depends on.
|
|
|
|
python_paths = []
|
2015-02-07 08:35:35 +08:00
|
|
|
for d in ext_spec.traverse():
|
|
|
|
if d.package.extends(self.spec):
|
2015-02-09 11:39:36 +08:00
|
|
|
python_paths.append(os.path.join(d.prefix, self.site_packages_dir))
|
|
|
|
os.environ['PYTHONPATH'] = ':'.join(python_paths)
|
2015-02-07 08:35:35 +08:00
|
|
|
|
2015-01-20 16:23:16 +08:00
|
|
|
|
2015-02-02 22:09:35 +08:00
|
|
|
# ========================================================================
|
|
|
|
# Handle specifics of activating and deactivating python modules.
|
|
|
|
# ========================================================================
|
|
|
|
|
|
|
|
def python_ignore(self, ext_pkg, args):
|
2015-01-20 16:23:16 +08:00
|
|
|
"""Add some ignore files to activate/deactivate args."""
|
2015-02-17 16:21:15 +08:00
|
|
|
ignore_arg = args.get('ignore', lambda f: False)
|
2015-02-02 22:09:35 +08:00
|
|
|
|
2015-02-17 16:21:15 +08:00
|
|
|
# Always ignore easy-install.pth, as it needs to be merged.
|
|
|
|
patterns = [r'easy-install\.pth$']
|
2015-02-02 22:09:35 +08:00
|
|
|
|
2015-02-17 16:21:15 +08:00
|
|
|
# Ignore pieces of setuptools installed by other packages.
|
|
|
|
if ext_pkg.name != 'py-setuptools':
|
2015-12-23 01:15:47 +08:00
|
|
|
patterns.append(r'/site[^/]*\.pyc?$')
|
2015-02-17 16:21:15 +08:00
|
|
|
patterns.append(r'setuptools\.pth')
|
|
|
|
patterns.append(r'bin/easy_install[^/]*$')
|
|
|
|
patterns.append(r'setuptools.*egg$')
|
2015-02-02 22:09:35 +08:00
|
|
|
|
2015-02-17 16:21:15 +08:00
|
|
|
return match_predicate(ignore_arg, patterns)
|
2015-01-20 16:23:16 +08:00
|
|
|
|
|
|
|
|
2015-02-15 17:58:35 +08:00
|
|
|
def write_easy_install_pth(self, exts):
|
2015-02-02 22:09:35 +08:00
|
|
|
paths = []
|
2015-02-15 17:58:35 +08:00
|
|
|
for ext in sorted(exts.values()):
|
2015-02-02 22:09:35 +08:00
|
|
|
ext_site_packages = os.path.join(ext.prefix, self.site_packages_dir)
|
|
|
|
easy_pth = "%s/easy-install.pth" % ext_site_packages
|
|
|
|
|
|
|
|
if not os.path.isfile(easy_pth):
|
|
|
|
continue
|
|
|
|
|
|
|
|
with closing(open(easy_pth)) as f:
|
|
|
|
for line in f:
|
|
|
|
line = line.rstrip()
|
|
|
|
|
|
|
|
# Skip lines matching these criteria
|
|
|
|
if not line: continue
|
|
|
|
if re.search(r'^(import|#)', line): continue
|
|
|
|
if (ext.name != 'py-setuptools' and
|
|
|
|
re.search(r'setuptools.*egg$', line)): continue
|
|
|
|
|
|
|
|
paths.append(line)
|
|
|
|
|
|
|
|
site_packages = os.path.join(self.prefix, self.site_packages_dir)
|
|
|
|
main_pth = "%s/easy-install.pth" % site_packages
|
|
|
|
|
|
|
|
if not paths:
|
|
|
|
if os.path.isfile(main_pth):
|
|
|
|
os.remove(main_pth)
|
|
|
|
|
|
|
|
else:
|
|
|
|
with closing(open(main_pth, 'w')) as f:
|
|
|
|
f.write("import sys; sys.__plen = len(sys.path)\n")
|
|
|
|
for path in paths:
|
|
|
|
f.write("%s\n" % path)
|
|
|
|
f.write("import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; "
|
|
|
|
"p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)\n")
|
|
|
|
|
|
|
|
|
2015-01-20 16:23:16 +08:00
|
|
|
def activate(self, ext_pkg, **args):
|
2015-05-11 08:56:27 +08:00
|
|
|
ignore=self.python_ignore(ext_pkg, args)
|
|
|
|
args.update(ignore=ignore)
|
|
|
|
|
2015-01-20 16:23:16 +08:00
|
|
|
super(Python, self).activate(ext_pkg, **args)
|
|
|
|
|
2015-02-15 17:58:35 +08:00
|
|
|
exts = spack.install_layout.extension_map(self.spec)
|
|
|
|
exts[ext_pkg.name] = ext_pkg.spec
|
|
|
|
self.write_easy_install_pth(exts)
|
2015-02-02 22:09:35 +08:00
|
|
|
|
2015-01-20 16:23:16 +08:00
|
|
|
|
|
|
|
def deactivate(self, ext_pkg, **args):
|
2015-02-02 22:09:35 +08:00
|
|
|
args.update(ignore=self.python_ignore(ext_pkg, args))
|
2015-01-20 16:23:16 +08:00
|
|
|
super(Python, self).deactivate(ext_pkg, **args)
|
2015-02-02 22:09:35 +08:00
|
|
|
|
2015-02-15 17:58:35 +08:00
|
|
|
exts = spack.install_layout.extension_map(self.spec)
|
2015-02-17 04:41:22 +08:00
|
|
|
if ext_pkg.name in exts: # Make deactivate idempotent.
|
|
|
|
del exts[ext_pkg.name]
|
|
|
|
self.write_easy_install_pth(exts)
|