Compare commits

..

14 Commits

Author SHA1 Message Date
Todd Gamblin
fe4ccdd555 update CHANGELOG.md for 0.13.2 2019-12-04 22:02:41 -08:00
Todd Gamblin
46b68263d8 version bump: 0.13.2 2019-12-04 21:20:09 -08:00
Peter Scheibel
03a5771b9d Bugfix: allow missing modules if they are blacklisted (#13540)
`spack module loads` and `spack module find` previously failed if any upstream modules were missing.  This prevented it from being used with upstreams (or, really, any spack instance) that blacklisted modules.

This PR makes module finding is now more lenient (especially for blacklisted modules).

- `spack module find` now does not report an error if the spec is blacklisted
  - instead, it prints a single warning if any modules will be omitted from the loads file
  - It comments the missing modules out of the loads file so the user can see what's missing
  - Debug messages are also printed so users can check this with `spack -d...`

- also added tests for new functionality
2019-12-04 20:55:50 -08:00
Massimiliano Culpo
a93a613668 Speedup environment activation (#13557)
* Add a transaction around repeated calls to `spec.prefix` in the activation process
* cache the computation of home in the python package to speed up setting deps
* ensure that module-scope variables are only set *once* per module
2019-12-02 14:05:35 -08:00
Todd Gamblin
c36d9f297f bugfix: mirror path works for unknown versions (#13626)
`mirror_archive_path` was failing to account for the case where the fetched version isn't known to Spack.

- [x] don't require the fetched version to be in `Package.versions`
- [x] add regression test for mirror paths when package does not have a version
2019-12-01 20:23:06 -08:00
Adam J. Stewart
b44df29316 environments: don't try to modify run-env if a spec is not installed (#13589)
Fixes #13529
Fixes #13509
2019-12-01 20:22:31 -08:00
Greg Becker
fba963f1d1 use semicolons instead of newlines in module/python command (#13904) 2019-12-01 20:21:34 -08:00
Daryl W. Grunau
9c5b583508 verify.py: os.path.exists exception handling (#13656) 2019-12-01 20:21:08 -08:00
Adam J. Stewart
eb22abc521 Document use of the maintainers field (#13748) 2019-11-17 15:30:08 -07:00
Greg Becker
aa83c483f7 Bugfix/config caching 13754 (#13759)
* remove reference to `spack.store` in method definition

Referencing `spack.store` in method definition will cache the `spack.config.config` singleton variable too early, before we have a chance to add command line and environment scopes.
2019-11-15 13:55:51 -08:00
Massimiliano Culpo
46bfcbbd3d hwloc: added 'master' version pointing at the HEAD of the master branch (#13734) 2019-11-15 12:38:30 -08:00
Greg Becker
74e04b7e20 Config option to allow gpg warning suppression (#13744)
Add a configuration option to suppress gpg warnings during binary
package verification. This only suppresses warnings: a gpg failure
will still fail the install. This allows users who have already
explicitly trusted the gpg key they are using to avoid seeing
repeated warnings that it is self-signed.
2019-11-14 16:22:19 -08:00
Peter Scheibel
28163cb34f determine target relative to the link directory rather than the full link path (which includes the file name) (#13727) 2019-11-14 12:15:47 -08:00
Greg Becker
b280034380 Allow binary relocation of strings in relative binaries (#13724)
Binaries with relative RPATHS currently do not relocate strings
hard-coded in binaries

This PR extends the best-effort relocation of strings hard-coded
in binaries to those whose RPATHs have been relativized.
2019-11-13 16:03:16 -08:00
21 changed files with 275 additions and 79 deletions

View File

@@ -1,3 +1,43 @@
# v0.13.2 (2019-12-04)
This release contains major performance improvements for Spack environments, as
well as some bugfixes and minor changes.
* allow missing modules if they are blacklisted (#13540)
* speed up environment activation (#13557)
* mirror path works for unknown versions (#13626)
* environments: don't try to modify run-env if a spec is not installed (#13589)
* use semicolons instead of newlines in module/python command (#13904)
* verify.py: os.path.exists exception handling (#13656)
* Document use of the maintainers field (#13479)
* bugfix with config caching (#13755)
* hwloc: added 'master' version pointing at the HEAD of the master branch (#13734)
* config option to allow gpg warning suppression (#13744)
* fix for relative symlinks when relocating binary packages (#13727)
* allow binary relocation of strings in relative binaries (#13724)
# v0.13.1 (2019-11-05)
This is a bugfix release on top of `v0.13.0`. Specific fixes include:
* `spack find` now displays variants and other spec constraints
* bugfix: uninstall should find concrete specs by DAG hash (#13598)
* environments: make shell modifications partially unconditional (#13523)
* binary distribution: relocate text files properly in relative binaries (#13578)
* bugfix: fetch prefers to fetch local mirrors over remote resources (#13545)
* environments: only write when necessary (#13546)
* bugfix: spack.util.url.join() now handles absolute paths correctly (#13488)
* sbang: use utf-8 for encoding when patching (#13490)
* Specs with quoted flags containing spaces are parsed correctly (#13521)
* targets: print a warning message before downgrading (#13513)
* Travis CI: Test Python 3.8 (#13347)
* Documentation: Database.query methods share docstrings (#13515)
* cuda: fix conflict statements for x86-64 targets (#13472)
* cpu: fix clang flags for generic x86_64 (#13491)
* syaml_int type should use int.__repr__ rather than str.__repr__ (#13487)
* elpa: prefer 2016.05.004 until sse/avx/avx2 issues are resolved (#13530)
* trilinos: temporarily constrain netcdf@:4.7.1 (#13526)
# v0.13.0 (2019-10-25)
`v0.13.0` is our biggest Spack release yet, with *many* new major features.

View File

@@ -80,6 +80,14 @@ config:
verify_ssl: true
# Suppress gpg warnings from binary package verification
# Only suppresses warnings, gpg failure will still fail the install
# Potential rationale to set True: users have already explicitly trusted the
# gpg key they are using, and may not want to see repeated warnings that it
# is self-signed or something of the sort.
suppress_gpg_warnings: false
# If set to true, Spack will attempt to build any compiler on the spec
# that is not already available. If set to False, Spack will only use
# compilers already configured in compilers.yaml

View File

@@ -136,6 +136,10 @@ generates a boilerplate template for your package, and opens up the new
homepage = "http://www.example.com"
url = "https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2"
# FIXME: Add a list of GitHub accounts to
# notify when the package is updated.
# maintainers = ['github_user1', 'github_user2']
version('6.1.2', '8ddbb26dc3bd4e2302984debba1406a5')
version('6.1.1', '4c175f86e11eb32d8bf9872ca3a8e11d')
version('6.1.0', '86ee6e54ebfc4a90b643a65e402c4048')
@@ -184,6 +188,17 @@ The rest of the tasks you need to do are as follows:
The ``homepage`` is displayed when users run ``spack info`` so
that they can learn more about your package.
#. Add a comma-separated list of maintainers.
The ``maintainers`` field is a list of GitHub accounts of people
who want to be notified any time the package is modified. When a
pull request is submitted that updates the package, these people
will be requested to review the PR. This is useful for developers
who maintain a Spack package for their own software, as well as
users who rely on a piece of software and want to ensure that the
package doesn't break. It also gives users a list of people to
contact for help when someone reports a build error with the package.
#. Add ``depends_on()`` calls for the package's dependencies.
``depends_on`` tells Spack that other packages need to be built

View File

@@ -5,7 +5,7 @@
#: major, minor, patch version for Spack, in a tuple
spack_version_info = (0, 13, 1)
spack_version_info = (0, 13, 2)
#: String containing Spack version joined with .'s
spack_version = '.'.join(str(v) for v in spack_version_info)

View File

@@ -21,6 +21,7 @@
from llnl.util.filesystem import mkdirp, install_tree
import spack.cmd
import spack.config as config
import spack.fetch_strategy as fs
import spack.util.gpg as gpg_util
import spack.relocate as relocate
@@ -534,7 +535,22 @@ def relocate_package(workdir, spec, allow_root):
newprefix=new_prefix)
# If the binary files in the package were not edited to use
# relative RPATHs, then the RPATHs need to be relocated
if not rel:
if rel:
if old_path != new_path:
files_to_relocate = list(filter(
lambda pathname: not relocate.file_is_relocatable(
pathname, paths_to_relocate=[old_path, old_prefix]),
map(lambda filename: os.path.join(workdir, filename),
buildinfo['relocate_binaries'])))
if len(old_path) < len(new_path) and files_to_relocate:
tty.debug('Cannot do a binary string replacement with padding '
'for package because %s is longer than %s.' %
(new_path, old_path))
else:
for path_name in files_to_relocate:
relocate.replace_prefix_bin(path_name, old_path, new_path)
else:
path_names = set()
for filename in buildinfo['relocate_binaries']:
path_name = os.path.join(workdir, filename)
@@ -577,7 +593,8 @@ def extract_tarball(spec, filename, allow_root=False, unsigned=False,
if not unsigned:
if os.path.exists('%s.asc' % specfile_path):
try:
Gpg.verify('%s.asc' % specfile_path, specfile_path)
suppress = config.get('config:suppress_gpg_warnings', False)
Gpg.verify('%s.asc' % specfile_path, specfile_path, suppress)
except Exception as e:
shutil.rmtree(tmpdir)
tty.die(e)

View File

@@ -422,6 +422,11 @@ def set_build_environment_variables(pkg, env, dirty):
def _set_variables_for_single_module(pkg, module):
"""Helper function to set module variables for single module."""
# Put a marker on this module so that it won't execute the body of this
# function again, since it is not needed
marker = '_set_run_already_called'
if getattr(module, marker, False):
return
jobs = spack.config.get('config:build_jobs') if pkg.parallel else 1
jobs = min(jobs, multiprocessing.cpu_count())
@@ -489,6 +494,10 @@ def static_to_shared_library(static_lib, shared_lib=None, **kwargs):
m.static_to_shared_library = static_to_shared_library
# Put a marker on this module so that it won't execute the body of this
# function again, since it is not needed
setattr(m, marker, True)
def set_module_variables_for_package(pkg):
"""Populate the module scope of install() with some useful functions.

View File

@@ -60,6 +60,10 @@ class {class_name}({base_class_name}):
homepage = "https://www.example.com"
{url_def}
# FIXME: Add a list of GitHub accounts to
# notify when the package is updated.
# maintainers = ['github_user1', 'github_user2']
{versions}
{dependencies}

View File

@@ -111,6 +111,14 @@ def one_spec_or_raise(specs):
return specs[0]
_missing_modules_warning = (
"Modules have been omitted for one or more specs, either"
" because they were blacklisted or because the spec is"
" associated with a package that is installed upstream and"
" that installation has not generated a module file. Rerun"
" this command with debug output enabled for more details.")
def loads(module_type, specs, args, out=sys.stdout):
"""Prompt the list of modules associated with a list of specs"""
@@ -131,7 +139,9 @@ def loads(module_type, specs, args, out=sys.stdout):
)
modules = list(
(spec, spack.modules.common.get_module(module_type, spec, False))
(spec,
spack.modules.common.get_module(
module_type, spec, get_full_path=False, required=False))
for spec in specs)
module_commands = {
@@ -145,15 +155,24 @@ def loads(module_type, specs, args, out=sys.stdout):
}
exclude_set = set(args.exclude)
prompt_template = '{comment}{exclude}{command}{prefix}{name}'
load_template = '{comment}{exclude}{command}{prefix}{name}'
for spec, mod in modules:
d['exclude'] = '## ' if spec.name in exclude_set else ''
d['comment'] = '' if not args.shell else '# {0}\n'.format(
spec.format())
d['name'] = mod
out.write(prompt_template.format(**d))
if not mod:
module_output_for_spec = (
'## blacklisted or missing from upstream: {0}'.format(
spec.format()))
else:
d['exclude'] = '## ' if spec.name in exclude_set else ''
d['comment'] = '' if not args.shell else '# {0}\n'.format(
spec.format())
d['name'] = mod
module_output_for_spec = load_template.format(**d)
out.write(module_output_for_spec)
out.write('\n')
if not all(mod for _, mod in modules):
tty.warn(_missing_modules_warning)
def find(module_type, specs, args):
"""Retrieve paths or use names of module files"""
@@ -161,18 +180,27 @@ def find(module_type, specs, args):
single_spec = one_spec_or_raise(specs)
if args.recurse_dependencies:
specs_to_retrieve = list(
single_spec.traverse(order='post', cover='nodes',
dependency_specs_to_retrieve = list(
single_spec.traverse(root=False, order='post', cover='nodes',
deptype=('link', 'run')))
else:
specs_to_retrieve = [single_spec]
dependency_specs_to_retrieve = []
try:
modules = [spack.modules.common.get_module(module_type, spec,
args.full_path)
for spec in specs_to_retrieve]
modules = [
spack.modules.common.get_module(
module_type, spec, args.full_path, required=False)
for spec in dependency_specs_to_retrieve]
modules.append(
spack.modules.common.get_module(
module_type, single_spec, args.full_path, required=True))
except spack.modules.common.ModuleNotFoundError as e:
tty.die(e.message)
if not all(modules):
tty.warn(_missing_modules_warning)
modules = list(x for x in modules if x)
print(' '.join(modules))

View File

@@ -159,7 +159,8 @@ def activate(
cmds += 'export PS1="%s ${PS1}";\n' % prompt
if add_view and default_view_name in env.views:
cmds += env.add_default_view_to_shell(shell)
with spack.store.db.read_transaction():
cmds += env.add_default_view_to_shell(shell)
return cmds
@@ -207,7 +208,8 @@ def deactivate(shell='sh'):
cmds += 'fi;\n'
if default_view_name in _active_environment.views:
cmds += _active_environment.rm_default_view_from_shell(shell)
with spack.store.db.read_transaction():
cmds += _active_environment.rm_default_view_from_shell(shell)
tty.debug("Deactivated environmennt '%s'" % _active_environment.name)
_active_environment = None
@@ -1117,7 +1119,7 @@ def add_default_view_to_shell(self, shell):
self.default_view))
for _, spec in self.concretized_specs():
if spec in self.default_view:
if spec in self.default_view and spec.package.installed:
env_mod.extend(self.environment_modifications_for_spec(
spec, self.default_view))
@@ -1138,7 +1140,7 @@ def rm_default_view_from_shell(self, shell):
self.default_view).reversed())
for _, spec in self.concretized_specs():
if spec in self.default_view:
if spec in self.default_view and spec.package.installed:
env_mod.extend(
self.environment_modifications_for_spec(
spec, self.default_view).reversed())

View File

@@ -303,8 +303,8 @@ def mirror_archive_paths(fetcher, per_package_ref, spec=None):
storage path of the resource associated with the specified ``fetcher``."""
ext = None
if spec:
ext = spec.package.versions[spec.package.version].get(
'extension', None)
versions = spec.package.versions.get(spec.package.version, {})
ext = versions.get('extension', None)
# If the spec does not explicitly specify an extension (the default case),
# then try to determine it automatically. An extension can only be
# specified for the primary source of the package (e.g. the source code

View File

@@ -312,20 +312,45 @@ def upstream_module(self, spec, module_type):
module_index = self.module_indices[db_index]
module_type_index = module_index.get(module_type, {})
if not module_type_index:
raise ModuleNotFoundError(
tty.debug(
"No {0} modules associated with the Spack instance where"
" {1} is installed".format(module_type, spec))
return None
if spec.dag_hash() in module_type_index:
return module_type_index[spec.dag_hash()]
else:
raise ModuleNotFoundError(
tty.debug(
"No module is available for upstream package {0}".format(spec))
return None
def get_module(module_type, spec, get_full_path):
def get_module(module_type, spec, get_full_path, required=True):
"""Retrieve the module file for a given spec and module type.
Retrieve the module file for the given spec if it is available. If the
module is not available, this will raise an exception unless the module
is blacklisted or if the spec is installed upstream.
Args:
module_type: the type of module we want to retrieve (e.g. lmod)
spec: refers to the installed package that we want to retrieve a module
for
required: if the module is required but blacklisted, this function will
print a debug message. If a module is missing but not blacklisted,
then an exception is raised (regardless of whether it is required)
get_full_path: if ``True``, this returns the full path to the module.
Otherwise, this returns the module name.
Returns:
The module name or path. May return ``None`` if the module is not
available.
"""
if spec.package.installed_upstream:
module = spack.modules.common.upstream_module_index.upstream_module(
spec, module_type)
module = (spack.modules.common.upstream_module_index
.upstream_module(spec, module_type))
if not module:
return None
if get_full_path:
return module.path
else:
@@ -333,10 +358,17 @@ def get_module(module_type, spec, get_full_path):
else:
writer = spack.modules.module_types[module_type](spec)
if not os.path.isfile(writer.layout.filename):
err_msg = "No module available for package {0} at {1}".format(
spec, writer.layout.filename
)
raise ModuleNotFoundError(err_msg)
if not writer.conf.blacklisted:
err_msg = "No module available for package {0} at {1}".format(
spec, writer.layout.filename
)
raise ModuleNotFoundError(err_msg)
elif required:
tty.debug("The module configuration has blacklisted {0}: "
"omitting it".format(spec))
else:
return None
if get_full_path:
return writer.layout.filename
else:

View File

@@ -488,11 +488,11 @@ def make_link_relative(cur_path_names, orig_path_names):
Change absolute links to be relative.
"""
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
old_src = os.readlink(orig_path)
new_src = os.path.relpath(old_src, orig_path)
target = os.readlink(orig_path)
relative_target = os.path.relpath(target, os.path.dirname(orig_path))
os.unlink(cur_path)
os.symlink(new_src, cur_path)
os.symlink(relative_target, cur_path)
def make_macho_binaries_relative(cur_path_names, orig_path_names, old_dir,
@@ -637,7 +637,7 @@ def is_relocatable(spec):
return True
def file_is_relocatable(file):
def file_is_relocatable(file, paths_to_relocate=None):
"""Returns True if the file passed as argument is relocatable.
Args:
@@ -650,6 +650,8 @@ def file_is_relocatable(file):
ValueError: if the file does not exist or the path is not absolute
"""
default_paths_to_relocate = [spack.store.layout.root, spack.paths.prefix]
paths_to_relocate = paths_to_relocate or default_paths_to_relocate
if not (platform.system().lower() == 'darwin'
or platform.system().lower() == 'linux'):
@@ -684,19 +686,13 @@ def file_is_relocatable(file):
if idpath is not None:
set_of_strings.discard(idpath)
if any(spack.store.layout.root in x for x in set_of_strings):
# One binary has the root folder not in the RPATH,
# meaning that this spec is not relocatable
msg = 'Found "{0}" in {1} strings'
tty.debug(msg.format(spack.store.layout.root, file))
return False
if any(spack.paths.prefix in x for x in set_of_strings):
# One binary has the root folder not in the RPATH,
# meaning that this spec is not relocatable
msg = 'Found "{0}" in {1} strings'
tty.debug(msg.format(spack.paths.prefix, file))
return False
for path_to_relocate in paths_to_relocate:
if any(path_to_relocate in x for x in set_of_strings):
# One binary has the root folder not in the RPATH,
# meaning that this spec is not relocatable
msg = 'Found "{0}" in {1} strings'
tty.debug(msg.format(path_to_relocate, file))
return False
return True

View File

@@ -56,6 +56,7 @@
'source_cache': {'type': 'string'},
'misc_cache': {'type': 'string'},
'verify_ssl': {'type': 'boolean'},
'suppress_gpg_warnings': {'type': 'boolean'},
'install_missing_compilers': {'type': 'boolean'},
'debug': {'type': 'boolean'},
'checksum': {'type': 'boolean'},

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
import re
import pytest
@@ -144,6 +145,34 @@ def test_find_recursive():
assert len(out.split()) > 1
@pytest.mark.db
def test_find_recursive_blacklisted(database, module_configuration):
module_configuration('blacklist')
module('lmod', 'refresh', '-y', '--delete-tree')
module('lmod', 'find', '-r', 'mpileaks ^mpich')
@pytest.mark.db
def test_loads_recursive_blacklisted(database, module_configuration):
module_configuration('blacklist')
module('lmod', 'refresh', '-y', '--delete-tree')
output = module('lmod', 'loads', '-r', 'mpileaks ^mpich')
lines = output.split('\n')
assert any(re.match(r'[^#]*module load.*mpileaks', l) for l in lines)
assert not any(re.match(r'[^#]module load.*callpath', l) for l in lines)
assert any(re.match(r'## blacklisted or missing.*callpath', l)
for l in lines)
# TODO: currently there is no way to separate stdout and stderr when
# invoking a SpackCommand. Supporting this requires refactoring
# SpackCommand, or log_output, or both.
# start_of_warning = spack.cmd.modules._missing_modules_warning[:10]
# assert start_of_warning not in output
# Needed to make the 'module_configuration' fixture below work
writer_cls = spack.modules.lmod.LmodModulefileWriter

View File

@@ -146,6 +146,12 @@ def test_all_mirror(
repos.clear()
def test_mirror_archive_paths_no_version(mock_packages, config, mock_archive):
spec = Spec('trivial-install-test-package@nonexistingversion')
fetcher = spack.fetch_strategy.URLFetchStrategy(mock_archive.url)
spack.mirror.mirror_archive_paths(fetcher, 'per-package-ref', spec)
def test_mirror_with_url_patches(mock_packages, config, monkeypatch):
spec = Spec('patch-several-dependencies')
spec.concretize()

View File

@@ -10,8 +10,7 @@
import spack.spec
import spack.modules.tcl
from spack.modules.common import (
UpstreamModuleIndex, ModuleNotFoundError)
from spack.modules.common import UpstreamModuleIndex
import spack.error
@@ -133,18 +132,15 @@ def test_upstream_module_index():
assert m1.path == '/path/to/a'
# No modules are defined for the DB associated with s2
with pytest.raises(ModuleNotFoundError):
upstream_index.upstream_module(s2, 'tcl')
assert not upstream_index.upstream_module(s2, 'tcl')
# Modules are defined for the index associated with s1, but none are
# defined for the requested type
with pytest.raises(ModuleNotFoundError):
upstream_index.upstream_module(s1, 'lmod')
assert not upstream_index.upstream_module(s1, 'lmod')
# A module is registered with a DB and the associated module index has
# modules of the specified type defined, but not for the requested spec
with pytest.raises(ModuleNotFoundError):
upstream_index.upstream_module(s3, 'tcl')
assert not upstream_index.upstream_module(s3, 'tcl')
# The spec isn't recorded as installed in any of the DBs
with pytest.raises(spack.error.SpackError):

View File

@@ -100,8 +100,11 @@ def sign(cls, key, file, output, clearsign=False):
cls.gpg()(*args)
@classmethod
def verify(cls, signature, file):
cls.gpg()('--verify', signature, file)
def verify(cls, signature, file, suppress_warnings=False):
if suppress_warnings:
cls.gpg()('--verify', signature, file, error=str)
else:
cls.gpg()('--verify', signature, file)
@classmethod
def list(cls, trusted, signing):

View File

@@ -17,7 +17,7 @@
# This list is not exhaustive. Currently we only use load and unload
# If we need another option that changes the environment, add it here.
module_change_commands = ['load', 'swap', 'unload', 'purge', 'use', 'unuse']
py_cmd = "'import os\nimport json\nprint(json.dumps(dict(os.environ)))'"
py_cmd = "'import os;import json;print(json.dumps(dict(os.environ)))'"
# This is just to enable testing. I hate it but we can't find a better way
_test_mode = False

View File

@@ -28,24 +28,26 @@ def compute_hash(path):
def create_manifest_entry(path):
data = {}
stat = os.stat(path)
data['mode'] = stat.st_mode
data['owner'] = stat.st_uid
data['group'] = stat.st_gid
if os.path.exists(path):
stat = os.stat(path)
if os.path.islink(path):
data['type'] = 'link'
data['dest'] = os.readlink(path)
data['mode'] = stat.st_mode
data['owner'] = stat.st_uid
data['group'] = stat.st_gid
elif os.path.isdir(path):
data['type'] = 'dir'
if os.path.islink(path):
data['type'] = 'link'
data['dest'] = os.readlink(path)
else:
data['type'] = 'file'
data['hash'] = compute_hash(path)
data['time'] = stat.st_mtime
data['size'] = stat.st_size
elif os.path.isdir(path):
data['type'] = 'dir'
else:
data['type'] = 'file'
data['hash'] = compute_hash(path)
data['time'] = stat.st_mtime
data['size'] = stat.st_size
return data

View File

@@ -2,9 +2,6 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack import *
import sys
@@ -28,7 +25,9 @@ class Hwloc(AutotoolsPackage):
url = "https://download.open-mpi.org/release/hwloc/v2.0/hwloc-2.0.2.tar.gz"
list_url = "http://www.open-mpi.org/software/hwloc/"
list_depth = 2
git = 'https://github.com/open-mpi/hwloc.git'
version('master', branch='master')
version('2.0.2', sha256='27dcfe42e3fb3422b72ce48b48bf601c0a3e46e850ee72d9bdd17b5863b6e42c')
version('2.0.1', sha256='f1156df22fc2365a31a3dc5f752c53aad49e34a5e22d75ed231cd97eaa437f9d')
version('2.0.0', sha256='a0d425a0fc7c7e3f2c92a272ffaffbd913005556b4443e1887d2e1718d902887')
@@ -59,7 +58,10 @@ class Hwloc(AutotoolsPackage):
)
depends_on('pkgconfig', type='build')
depends_on('m4', type='build', when='@master')
depends_on('autoconf', type='build', when='@master')
depends_on('automake', type='build', when='@master')
depends_on('libtool', type='build', when='@master')
depends_on('cuda', when='+nvml')
depends_on('cuda', when='+cuda')
depends_on('gl', when='+gl')

View File

@@ -163,6 +163,9 @@ class Python(AutotoolsPackage):
_DISTUTIL_CACHE_FILENAME = 'sysconfig.json'
_distutil_vars = None
# Used to cache home locations, since computing them might be expensive
_homes = {}
# An in-source build with --enable-optimizations fails for python@3.X
build_directory = 'spack-build'
@@ -622,8 +625,11 @@ def home(self):
``packages.yaml`` unknowingly. Query the python executable to
determine exactly where it is installed."""
prefix = self.get_config_var('prefix')
return Prefix(prefix)
dag_hash = self.spec.dag_hash()
if dag_hash not in self._homes:
prefix = self.get_config_var('prefix')
self._homes[dag_hash] = Prefix(prefix)
return self._homes[dag_hash]
@property
def libs(self):