Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fe4ccdd555 | ||
![]() |
46b68263d8 | ||
![]() |
03a5771b9d | ||
![]() |
a93a613668 | ||
![]() |
c36d9f297f | ||
![]() |
b44df29316 | ||
![]() |
fba963f1d1 | ||
![]() |
9c5b583508 | ||
![]() |
eb22abc521 | ||
![]() |
aa83c483f7 | ||
![]() |
46bfcbbd3d | ||
![]() |
74e04b7e20 | ||
![]() |
28163cb34f | ||
![]() |
b280034380 |
40
CHANGELOG.md
40
CHANGELOG.md
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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.
|
||||
|
@@ -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}
|
||||
|
@@ -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))
|
||||
|
||||
|
||||
|
@@ -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())
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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'},
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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()
|
||||
|
@@ -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):
|
||||
|
@@ -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):
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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')
|
||||
|
@@ -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):
|
||||
|
Reference in New Issue
Block a user