stacks: add option to link only roots or all specs, default to all
This commit is contained in:
parent
7ec89aa036
commit
ec6e5b0fd3
@ -78,8 +78,12 @@
|
|||||||
env_schema_keys = ('spack', 'env')
|
env_schema_keys = ('spack', 'env')
|
||||||
|
|
||||||
# Magic names
|
# Magic names
|
||||||
|
# The name of the standalone spec list in the manifest yaml
|
||||||
user_speclist_name = 'specs'
|
user_speclist_name = 'specs'
|
||||||
def_view_name = 'default'
|
# The name of the default view (the view loaded on env.activate)
|
||||||
|
default_view_name = 'default'
|
||||||
|
# Default behavior to link all packages into views (vs. only root packages)
|
||||||
|
default_view_link = 'all'
|
||||||
|
|
||||||
|
|
||||||
def valid_env_name(name):
|
def valid_env_name(name):
|
||||||
@ -145,7 +149,7 @@ def activate(
|
|||||||
cmds += 'export SPACK_OLD_PS1="${PS1}"; fi;\n'
|
cmds += 'export SPACK_OLD_PS1="${PS1}"; fi;\n'
|
||||||
cmds += 'export PS1="%s ${PS1}";\n' % prompt
|
cmds += 'export PS1="%s ${PS1}";\n' % prompt
|
||||||
|
|
||||||
if add_view and def_view_name in env.views:
|
if add_view and default_view_name in env.views:
|
||||||
cmds += env.add_default_view_to_shell(shell)
|
cmds += env.add_default_view_to_shell(shell)
|
||||||
|
|
||||||
return cmds
|
return cmds
|
||||||
@ -187,7 +191,7 @@ def deactivate(shell='sh'):
|
|||||||
cmds += 'unset SPACK_OLD_PS1; export SPACK_OLD_PS1;\n'
|
cmds += 'unset SPACK_OLD_PS1; export SPACK_OLD_PS1;\n'
|
||||||
cmds += 'fi;\n'
|
cmds += 'fi;\n'
|
||||||
|
|
||||||
if def_view_name in _active_environment.views:
|
if default_view_name in _active_environment.views:
|
||||||
cmds += _active_environment.rm_default_view_from_shell(shell)
|
cmds += _active_environment.rm_default_view_from_shell(shell)
|
||||||
|
|
||||||
tty.debug("Deactivated environmennt '%s'" % _active_environment.name)
|
tty.debug("Deactivated environmennt '%s'" % _active_environment.name)
|
||||||
@ -414,7 +418,8 @@ def _eval_conditional(string):
|
|||||||
|
|
||||||
|
|
||||||
class ViewDescriptor(object):
|
class ViewDescriptor(object):
|
||||||
def __init__(self, root, projections={}, select=[], exclude=[]):
|
def __init__(self, root, projections={}, select=[], exclude=[],
|
||||||
|
link=default_view_link):
|
||||||
self.root = root
|
self.root = root
|
||||||
self.projections = projections
|
self.projections = projections
|
||||||
self.select = select
|
self.select = select
|
||||||
@ -422,6 +427,7 @@ def __init__(self, root, projections={}, select=[], exclude=[]):
|
|||||||
self.exclude = exclude
|
self.exclude = exclude
|
||||||
self.exclude_fn = lambda x: not any(x.satisfies(e)
|
self.exclude_fn = lambda x: not any(x.satisfies(e)
|
||||||
for e in self.exclude)
|
for e in self.exclude)
|
||||||
|
self.link = link
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
ret = {'root': self.root}
|
ret = {'root': self.root}
|
||||||
@ -431,6 +437,8 @@ def to_dict(self):
|
|||||||
ret['select'] = self.select
|
ret['select'] = self.select
|
||||||
if self.exclude:
|
if self.exclude:
|
||||||
ret['exclude'] = self.exclude
|
ret['exclude'] = self.exclude
|
||||||
|
if self.link != default_view_link:
|
||||||
|
ret['link'] = self.link
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -438,19 +446,22 @@ def from_dict(d):
|
|||||||
return ViewDescriptor(d['root'],
|
return ViewDescriptor(d['root'],
|
||||||
d.get('projections', {}),
|
d.get('projections', {}),
|
||||||
d.get('select', []),
|
d.get('select', []),
|
||||||
d.get('exclude', []))
|
d.get('exclude', []),
|
||||||
|
d.get('link', default_view_link))
|
||||||
|
|
||||||
def view(self):
|
def view(self):
|
||||||
return YamlFilesystemView(self.root, spack.store.layout,
|
return YamlFilesystemView(self.root, spack.store.layout,
|
||||||
ignore_conflicts=True,
|
ignore_conflicts=True,
|
||||||
projections=self.projections)
|
projections=self.projections)
|
||||||
|
|
||||||
def regenerate(self, specs):
|
def regenerate(self, all_specs, roots):
|
||||||
specs_for_view = []
|
specs_for_view = []
|
||||||
|
specs = all_specs if self.link == 'all' else roots
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
# The view does not store build deps, so if we want it to
|
# The view does not store build deps, so if we want it to
|
||||||
# recognize environment specs (which do store build deps), then
|
# recognize environment specs (which do store build deps), then
|
||||||
# they need to be stripped
|
# they need to be stripped
|
||||||
|
if spec.concrete: # Do not link unconcretized roots
|
||||||
specs_for_view.append(spack.spec.Spec.from_dict(
|
specs_for_view.append(spack.spec.Spec.from_dict(
|
||||||
spec.to_dict(all_deps=False)
|
spec.to_dict(all_deps=False)
|
||||||
))
|
))
|
||||||
@ -523,9 +534,9 @@ def __init__(self, path, init_file=None, with_view=None):
|
|||||||
self.views = {}
|
self.views = {}
|
||||||
elif with_view is True:
|
elif with_view is True:
|
||||||
self.views = {
|
self.views = {
|
||||||
def_view_name: ViewDescriptor(self.view_path_default)}
|
default_view_name: ViewDescriptor(self.view_path_default)}
|
||||||
elif isinstance(with_view, six.string_types):
|
elif isinstance(with_view, six.string_types):
|
||||||
self.views = {def_view_name: ViewDescriptor(with_view)}
|
self.views = {default_view_name: ViewDescriptor(with_view)}
|
||||||
# If with_view is None, then defer to the view settings determined by
|
# If with_view is None, then defer to the view settings determined by
|
||||||
# the manifest file
|
# the manifest file
|
||||||
|
|
||||||
@ -556,9 +567,9 @@ def _read_manifest(self, f):
|
|||||||
# enable_view can be boolean, string, or None
|
# enable_view can be boolean, string, or None
|
||||||
if enable_view is True or enable_view is None:
|
if enable_view is True or enable_view is None:
|
||||||
self.views = {
|
self.views = {
|
||||||
def_view_name: ViewDescriptor(self.view_path_default)}
|
default_view_name: ViewDescriptor(self.view_path_default)}
|
||||||
elif isinstance(enable_view, six.string_types):
|
elif isinstance(enable_view, six.string_types):
|
||||||
self.views = {def_view_name: ViewDescriptor(enable_view)}
|
self.views = {default_view_name: ViewDescriptor(enable_view)}
|
||||||
elif enable_view:
|
elif enable_view:
|
||||||
self.views = dict((name, ViewDescriptor.from_dict(values))
|
self.views = dict((name, ViewDescriptor.from_dict(values))
|
||||||
for name, values in enable_view.items())
|
for name, values in enable_view.items())
|
||||||
@ -881,23 +892,24 @@ def default_view(self):
|
|||||||
raise SpackEnvironmentError(
|
raise SpackEnvironmentError(
|
||||||
"{0} does not have a view enabled".format(self.name))
|
"{0} does not have a view enabled".format(self.name))
|
||||||
|
|
||||||
if def_view_name not in self.views:
|
if default_view_name not in self.views:
|
||||||
raise SpackEnvironmentError(
|
raise SpackEnvironmentError(
|
||||||
"{0} does not have a default view enabled".format(self.name))
|
"{0} does not have a default view enabled".format(self.name))
|
||||||
|
|
||||||
return self.views[def_view_name]
|
return self.views[default_view_name]
|
||||||
|
|
||||||
def update_default_view(self, viewpath):
|
def update_default_view(self, viewpath):
|
||||||
if def_view_name in self.views and self.default_view.root != viewpath:
|
name = default_view_name
|
||||||
|
if name in self.views and self.default_view.root != viewpath:
|
||||||
shutil.rmtree(self.default_view.root)
|
shutil.rmtree(self.default_view.root)
|
||||||
|
|
||||||
if viewpath:
|
if viewpath:
|
||||||
if def_view_name in self.views:
|
if name in self.views:
|
||||||
self.default_view.root = viewpath
|
self.default_view.root = viewpath
|
||||||
else:
|
else:
|
||||||
self.views[def_view_name] = ViewDescriptor(viewpath)
|
self.views[name] = ViewDescriptor(viewpath)
|
||||||
else:
|
else:
|
||||||
self.views.pop(def_view_name, None)
|
self.views.pop(name, None)
|
||||||
|
|
||||||
def regenerate_views(self):
|
def regenerate_views(self):
|
||||||
if not self.views:
|
if not self.views:
|
||||||
@ -907,7 +919,7 @@ def regenerate_views(self):
|
|||||||
|
|
||||||
specs = self._get_environment_specs()
|
specs = self._get_environment_specs()
|
||||||
for view in self.views.values():
|
for view in self.views.values():
|
||||||
view.regenerate(specs)
|
view.regenerate(specs, self.roots())
|
||||||
|
|
||||||
def _shell_vars(self):
|
def _shell_vars(self):
|
||||||
updates = [
|
updates = [
|
||||||
@ -921,7 +933,7 @@ def _shell_vars(self):
|
|||||||
('CMAKE_PREFIX_PATH', ['']),
|
('CMAKE_PREFIX_PATH', ['']),
|
||||||
]
|
]
|
||||||
path_updates = list()
|
path_updates = list()
|
||||||
if def_view_name in self.views:
|
if default_view_name in self.views:
|
||||||
for var, subdirs in updates:
|
for var, subdirs in updates:
|
||||||
paths = filter(lambda x: os.path.exists(x),
|
paths = filter(lambda x: os.path.exists(x),
|
||||||
list(os.path.join(self.default_view.root, x)
|
list(os.path.join(self.default_view.root, x)
|
||||||
@ -1198,7 +1210,8 @@ def write(self):
|
|||||||
[])
|
[])
|
||||||
yaml_spec_list[:] = self.user_specs.yaml_list
|
yaml_spec_list[:] = self.user_specs.yaml_list
|
||||||
|
|
||||||
if self.views and len(self.views) == 1 and def_view_name in self.views:
|
default_name = default_view_name
|
||||||
|
if self.views and len(self.views) == 1 and default_name in self.views:
|
||||||
path = self.default_view.root
|
path = self.default_view.root
|
||||||
if self.default_view == ViewDescriptor(self.view_path_default):
|
if self.default_view == ViewDescriptor(self.view_path_default):
|
||||||
view = True
|
view = True
|
||||||
|
@ -96,6 +96,10 @@
|
|||||||
'root': {
|
'root': {
|
||||||
'type': 'string'
|
'type': 'string'
|
||||||
},
|
},
|
||||||
|
'link': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '(roots|all)',
|
||||||
|
},
|
||||||
'select': {
|
'select': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
|
@ -32,10 +32,9 @@
|
|||||||
find = SpackCommand('find')
|
find = SpackCommand('find')
|
||||||
|
|
||||||
|
|
||||||
def check_mpileaks_install(viewdir):
|
def check_mpileaks_and_deps_in_view(viewdir):
|
||||||
"""Check that the expected install directories exist."""
|
"""Check that the expected install directories exist."""
|
||||||
assert os.path.exists(str(viewdir.join('.spack', 'mpileaks')))
|
assert os.path.exists(str(viewdir.join('.spack', 'mpileaks')))
|
||||||
# Check that dependencies got in too
|
|
||||||
assert os.path.exists(str(viewdir.join('.spack', 'libdwarf')))
|
assert os.path.exists(str(viewdir.join('.spack', 'libdwarf')))
|
||||||
|
|
||||||
|
|
||||||
@ -634,7 +633,7 @@ def test_env_updates_view_install(
|
|||||||
add('mpileaks')
|
add('mpileaks')
|
||||||
install('--fake')
|
install('--fake')
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
|
|
||||||
def test_env_without_view_install(
|
def test_env_without_view_install(
|
||||||
@ -656,7 +655,7 @@ def test_env_without_view_install(
|
|||||||
|
|
||||||
# After enabling the view, the specs should be linked into the environment
|
# After enabling the view, the specs should be linked into the environment
|
||||||
# view dir
|
# view dir
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
|
|
||||||
def test_env_config_view_default(
|
def test_env_config_view_default(
|
||||||
@ -686,7 +685,7 @@ def test_env_updates_view_install_package(
|
|||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
install('--fake', 'mpileaks')
|
install('--fake', 'mpileaks')
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
assert os.path.exists(str(view_dir.join('.spack/mpileaks')))
|
||||||
|
|
||||||
|
|
||||||
def test_env_updates_view_add_concretize(
|
def test_env_updates_view_add_concretize(
|
||||||
@ -698,7 +697,7 @@ def test_env_updates_view_add_concretize(
|
|||||||
add('mpileaks')
|
add('mpileaks')
|
||||||
concretize()
|
concretize()
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
|
|
||||||
def test_env_updates_view_uninstall(
|
def test_env_updates_view_uninstall(
|
||||||
@ -708,7 +707,7 @@ def test_env_updates_view_uninstall(
|
|||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
install('--fake', 'mpileaks')
|
install('--fake', 'mpileaks')
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
uninstall('-ay')
|
uninstall('-ay')
|
||||||
@ -725,7 +724,7 @@ def test_env_updates_view_uninstall_referenced_elsewhere(
|
|||||||
add('mpileaks')
|
add('mpileaks')
|
||||||
concretize()
|
concretize()
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
uninstall('-ay')
|
uninstall('-ay')
|
||||||
@ -742,7 +741,7 @@ def test_env_updates_view_remove_concretize(
|
|||||||
add('mpileaks')
|
add('mpileaks')
|
||||||
concretize()
|
concretize()
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
remove('mpileaks')
|
remove('mpileaks')
|
||||||
@ -758,7 +757,7 @@ def test_env_updates_view_force_remove(
|
|||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
install('--fake', 'mpileaks')
|
install('--fake', 'mpileaks')
|
||||||
|
|
||||||
check_mpileaks_install(view_dir)
|
check_mpileaks_and_deps_in_view(view_dir)
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
remove('-f', 'mpileaks')
|
remove('-f', 'mpileaks')
|
||||||
@ -1123,7 +1122,7 @@ def test_stack_combinatorial_view(tmpdir, mock_fetch, mock_packages,
|
|||||||
install()
|
install()
|
||||||
|
|
||||||
test = ev.read('test')
|
test = ev.read('test')
|
||||||
for _, spec in test.concretized_specs():
|
for spec in test._get_environment_specs():
|
||||||
assert os.path.exists(
|
assert os.path.exists(
|
||||||
os.path.join(viewdir, spec.name, '%s-%s' %
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
(spec.version, spec.compiler.name)))
|
(spec.version, spec.compiler.name)))
|
||||||
@ -1156,7 +1155,7 @@ def test_stack_view_select(tmpdir, mock_fetch, mock_packages,
|
|||||||
install()
|
install()
|
||||||
|
|
||||||
test = ev.read('test')
|
test = ev.read('test')
|
||||||
for _, spec in test.concretized_specs():
|
for spec in test._get_environment_specs():
|
||||||
if spec.satisfies('%gcc'):
|
if spec.satisfies('%gcc'):
|
||||||
assert os.path.exists(
|
assert os.path.exists(
|
||||||
os.path.join(viewdir, spec.name, '%s-%s' %
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
@ -1194,7 +1193,7 @@ def test_stack_view_exclude(tmpdir, mock_fetch, mock_packages,
|
|||||||
install()
|
install()
|
||||||
|
|
||||||
test = ev.read('test')
|
test = ev.read('test')
|
||||||
for _, spec in test.concretized_specs():
|
for spec in test._get_environment_specs():
|
||||||
if not spec.satisfies('callpath'):
|
if not spec.satisfies('callpath'):
|
||||||
assert os.path.exists(
|
assert os.path.exists(
|
||||||
os.path.join(viewdir, spec.name, '%s-%s' %
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
@ -1233,7 +1232,88 @@ def test_stack_view_select_and_exclude(tmpdir, mock_fetch, mock_packages,
|
|||||||
install()
|
install()
|
||||||
|
|
||||||
test = ev.read('test')
|
test = ev.read('test')
|
||||||
for _, spec in test.concretized_specs():
|
for spec in test._get_environment_specs():
|
||||||
|
if spec.satisfies('%gcc') and not spec.satisfies('callpath'):
|
||||||
|
assert os.path.exists(
|
||||||
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
|
(spec.version, spec.compiler.name)))
|
||||||
|
else:
|
||||||
|
assert not os.path.exists(
|
||||||
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
|
(spec.version, spec.compiler.name)))
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_link_roots(tmpdir, mock_fetch, mock_packages, mock_archive,
|
||||||
|
install_mockery):
|
||||||
|
filename = str(tmpdir.join('spack.yaml'))
|
||||||
|
viewdir = str(tmpdir.join('view'))
|
||||||
|
with open(filename, 'w') as f:
|
||||||
|
f.write("""\
|
||||||
|
env:
|
||||||
|
definitions:
|
||||||
|
- packages: [mpileaks, callpath]
|
||||||
|
- compilers: ['%%gcc', '%%clang']
|
||||||
|
specs:
|
||||||
|
- matrix:
|
||||||
|
- [$packages]
|
||||||
|
- [$compilers]
|
||||||
|
|
||||||
|
view:
|
||||||
|
combinatorial:
|
||||||
|
root: %s
|
||||||
|
select: ['%%gcc']
|
||||||
|
exclude: [callpath]
|
||||||
|
link: 'roots'
|
||||||
|
projections:
|
||||||
|
'all': '{name}/{version}-{compiler.name}'""" % viewdir)
|
||||||
|
with tmpdir.as_cwd():
|
||||||
|
env('create', 'test', './spack.yaml')
|
||||||
|
with ev.read('test'):
|
||||||
|
install()
|
||||||
|
|
||||||
|
test = ev.read('test')
|
||||||
|
for spec in test._get_environment_specs():
|
||||||
|
if spec in test.roots() and (spec.satisfies('%gcc') and
|
||||||
|
not spec.satisfies('callpath')):
|
||||||
|
assert os.path.exists(
|
||||||
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
|
(spec.version, spec.compiler.name)))
|
||||||
|
else:
|
||||||
|
assert not os.path.exists(
|
||||||
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
|
(spec.version, spec.compiler.name)))
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_link_all(tmpdir, mock_fetch, mock_packages, mock_archive,
|
||||||
|
install_mockery):
|
||||||
|
filename = str(tmpdir.join('spack.yaml'))
|
||||||
|
viewdir = str(tmpdir.join('view'))
|
||||||
|
with open(filename, 'w') as f:
|
||||||
|
f.write("""\
|
||||||
|
env:
|
||||||
|
definitions:
|
||||||
|
- packages: [mpileaks, callpath]
|
||||||
|
- compilers: ['%%gcc', '%%clang']
|
||||||
|
specs:
|
||||||
|
- matrix:
|
||||||
|
- [$packages]
|
||||||
|
- [$compilers]
|
||||||
|
|
||||||
|
view:
|
||||||
|
combinatorial:
|
||||||
|
root: %s
|
||||||
|
select: ['%%gcc']
|
||||||
|
exclude: [callpath]
|
||||||
|
link: 'all'
|
||||||
|
projections:
|
||||||
|
'all': '{name}/{version}-{compiler.name}'""" % viewdir)
|
||||||
|
with tmpdir.as_cwd():
|
||||||
|
env('create', 'test', './spack.yaml')
|
||||||
|
with ev.read('test'):
|
||||||
|
install()
|
||||||
|
|
||||||
|
test = ev.read('test')
|
||||||
|
for spec in test._get_environment_specs():
|
||||||
if spec.satisfies('%gcc') and not spec.satisfies('callpath'):
|
if spec.satisfies('%gcc') and not spec.satisfies('callpath'):
|
||||||
assert os.path.exists(
|
assert os.path.exists(
|
||||||
os.path.join(viewdir, spec.name, '%s-%s' %
|
os.path.join(viewdir, spec.name, '%s-%s' %
|
||||||
@ -1342,7 +1422,7 @@ def test_stack_view_multiple_views(tmpdir, mock_fetch, mock_packages,
|
|||||||
assert os.path.join(default_viewdir, 'bin') in shell
|
assert os.path.join(default_viewdir, 'bin') in shell
|
||||||
|
|
||||||
test = ev.read('test')
|
test = ev.read('test')
|
||||||
for _, spec in test.concretized_specs():
|
for spec in test._get_environment_specs():
|
||||||
if not spec.satisfies('callpath%gcc'):
|
if not spec.satisfies('callpath%gcc'):
|
||||||
assert os.path.exists(
|
assert os.path.exists(
|
||||||
os.path.join(combin_viewdir, spec.name, '%s-%s' %
|
os.path.join(combin_viewdir, spec.name, '%s-%s' %
|
||||||
|
Loading…
Reference in New Issue
Block a user