diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2014-07-08 01:56:32 -0700 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2014-07-08 01:58:20 -0700 |
commit | 295ffd8c506821ed079d2151fb21cd27979d7387 (patch) | |
tree | 44b667a383aedfe5c97cebbe1e021791f4ec831e /lib | |
parent | 05516389441e6818ff3ee22bb4e51d50b3bb5cd4 (diff) | |
download | spack-295ffd8c506821ed079d2151fb21cd27979d7387.tar.gz spack-295ffd8c506821ed079d2151fb21cd27979d7387.tar.bz2 spack-295ffd8c506821ed079d2151fb21cd27979d7387.tar.xz spack-295ffd8c506821ed079d2151fb21cd27979d7387.zip |
Adding dotkit support to TAU.
- New spack.hooks package
- contains modules with pre and post install hooks
- New dotkit hook module
- generates/removes dotkits on install/uninstall
- New spack use, spack unuse commands
- use same syntax as install/uninstall
- New setup-env.bash script
- Sets up path, dotkit support
- new spack dotkit command
- used by script to parse specs, generate
specs of installed pckages for dotkit file names
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/llnl/util/tty/__init__.py | 12 | ||||
-rw-r--r-- | lib/spack/spack/__init__.py | 5 | ||||
-rw-r--r-- | lib/spack/spack/cmd/dotkit.py | 99 | ||||
-rw-r--r-- | lib/spack/spack/cmd/find.py | 14 | ||||
-rw-r--r-- | lib/spack/spack/cmd/unuse.py | 36 | ||||
-rw-r--r-- | lib/spack/spack/cmd/use.py | 50 | ||||
-rw-r--r-- | lib/spack/spack/hooks/__init__.py | 71 | ||||
-rw-r--r-- | lib/spack/spack/hooks/dotkit.py | 83 | ||||
-rw-r--r-- | lib/spack/spack/package.py | 13 | ||||
-rw-r--r-- | lib/spack/spack/util/prefix.py | 30 |
10 files changed, 392 insertions, 21 deletions
diff --git a/lib/spack/llnl/util/tty/__init__.py b/lib/spack/llnl/util/tty/__init__.py index 3f413cd46e..40cae11200 100644 --- a/lib/spack/llnl/util/tty/__init__.py +++ b/lib/spack/llnl/util/tty/__init__.py @@ -51,12 +51,14 @@ def msg(message, *args): def info(message, *args, **kwargs): format = kwargs.get('format', '*b') - cprint("@%s{==>} %s" % (format, cescape(str(message)))) + stream = kwargs.get('stream', sys.stdout) + + cprint("@%s{==>} %s" % (format, cescape(str(message))), stream=stream) for arg in args: lines = textwrap.wrap( str(arg), initial_indent=indent, subsequent_indent=indent) for line in lines: - print line + stream.write(line + '\n') def verbose(message, *args): @@ -66,15 +68,15 @@ def verbose(message, *args): def debug(message, *args): if _debug: - info(message, *args, format='g') + info(message, *args, format='g', stream=sys.stderr) def error(message, *args): - info("Error: " + str(message), *args, format='*r') + info("Error: " + str(message), *args, format='*r', stream=sys.stderr) def warn(message, *args): - info("Warning: " + str(message), *args, format='*Y') + info("Warning: " + str(message), *args, format='*Y', stream=sys.stderr) def die(message, *args): diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py index 58796d8854..d0cf8804ba 100644 --- a/lib/spack/spack/__init__.py +++ b/lib/spack/spack/__init__.py @@ -53,9 +53,12 @@ build_env_path = join_path(lib_path, "env") module_path = join_path(lib_path, "spack") compilers_path = join_path(module_path, "compilers") test_path = join_path(module_path, "test") +hooks_path = join_path(module_path, "hooks") var_path = join_path(prefix, "var", "spack") stage_path = join_path(var_path, "stage") install_path = join_path(prefix, "opt") +share_path = join_path(prefix, "share", "spack") +dotkit_path = join_path(share_path, "dotkit") # # Set up the packages database. @@ -90,7 +93,7 @@ concretizer = DefaultConcretizer() # Version information from spack.version import Version -spack_version = Version("1.0") +spack_version = Version("0.8") # # Executables used by Spack diff --git a/lib/spack/spack/cmd/dotkit.py b/lib/spack/spack/cmd/dotkit.py new file mode 100644 index 0000000000..7a691ae5c0 --- /dev/null +++ b/lib/spack/spack/cmd/dotkit.py @@ -0,0 +1,99 @@ +############################################################################## +# Copyright (c) 2013, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://scalability-llnl.github.io/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (as published by +# the Free Software Foundation) version 2.1 dated February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +import sys +import os +import shutil +import argparse + +import llnl.util.tty as tty +from llnl.util.lang import partition_list +from llnl.util.filesystem import mkdirp + +import spack.cmd +import spack.hooks.dotkit +from spack.spec import Spec + + +description ="Find dotkits for packages if they exist." + +def setup_parser(subparser): + subparser.add_argument( + '--refresh', action='store_true', help='Regenerate all dotkits') + + subparser.add_argument( + 'spec', nargs=argparse.REMAINDER, help='spec to find a dotkit for.') + + +def dotkit_find(parser, args): + if not args.spec: + parser.parse_args(['dotkit', '-h']) + + spec = spack.cmd.parse_specs(args.spec) + if len(spec) > 1: + tty.die("You can only pass one spec.") + spec = spec[0] + + if not spack.db.exists(spec.name): + tty.die("No such package: %s" % spec.name) + + specs = [s for s in spack.db.installed_package_specs() if s.satisfies(spec)] + + if len(specs) == 0: + tty.die("No installed packages match spec %s" % spec) + + if len(specs) > 1: + tty.error("Multiple matches for spec %s. Choose one:" % spec) + for s in specs: + sys.stderr.write(s.tree(color=True)) + sys.exit(1) + + match = specs[0] + if not os.path.isfile(spack.hooks.dotkit.dotkit_file(match.package)): + tty.die("No dotkit is installed for package %s." % spec) + + print match.format('$_$@$+$%@$=$#') + + +def dotkit_refresh(parser, args): + query_specs = spack.cmd.parse_specs(args.spec) + + specs = spack.db.installed_package_specs() + if query_specs: + specs = [s for s in specs + if any(s.satisfies(q) for q in query_specs)] + else: + shutil.rmtree(spack.dotkit_path, ignore_errors=False) + mkdirp(spack.dotkit_path) + + for spec in specs: + spack.hooks.dotkit.post_install(spec.package) + + + +def dotkit(parser, args): + if args.refresh: + dotkit_refresh(parser, args) + else: + dotkit_find(parser, args) diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py index 08cfb5af96..7f2bce119e 100644 --- a/lib/spack/spack/cmd/find.py +++ b/lib/spack/spack/cmd/find.py @@ -22,6 +22,7 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## +import sys import collections import argparse from StringIO import StringIO @@ -37,12 +38,14 @@ import spack.spec description ="Find installed spack packages" def setup_parser(subparser): - subparser.add_argument( + format_group = subparser.add_mutually_exclusive_group() + format_group.add_argument( '-p', '--paths', action='store_true', dest='paths', help='Show paths to package install directories') - subparser.add_argument( + format_group.add_argument( '-l', '--long', action='store_true', dest='full_specs', help='Show full-length specs of installed packages') + subparser.add_argument( 'query_specs', nargs=argparse.REMAINDER, help='optional specs to filter results') @@ -56,13 +59,16 @@ def find(parser, args): if nonexisting: msg = "No such package%s: " % ('s' if len(nonexisting) > 1 else '') - tty.msg(msg + ", ".join(s.name for s in nonexisting)) + msg += ", ".join(s.name for s in nonexisting) + tty.msg(msg) + if not query_specs: return - # Make a dict with specs keyed by architecture and compiler. specs = [s for s in spack.db.installed_package_specs() if not query_specs or any(s.satisfies(q) for q in query_specs)] + + # Make a dict with specs keyed by architecture and compiler. index = index_by(specs, 'architecture', 'compiler') # Traverse the index and print out each package diff --git a/lib/spack/spack/cmd/unuse.py b/lib/spack/spack/cmd/unuse.py new file mode 100644 index 0000000000..a31e16d11a --- /dev/null +++ b/lib/spack/spack/cmd/unuse.py @@ -0,0 +1,36 @@ +############################################################################## +# Copyright (c) 2013, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://scalability-llnl.github.io/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (as published by +# the Free Software Foundation) version 2.1 dated February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +import argparse +import spack.cmd.use + +description ="Remove package from environment using dotkit." + +def setup_parser(subparser): + subparser.add_argument( + 'spec', nargs=argparse.REMAINDER, help='Spec of package to remove.') + + +def unuse(parser, args): + spack.cmd.use.print_help() diff --git a/lib/spack/spack/cmd/use.py b/lib/spack/spack/cmd/use.py new file mode 100644 index 0000000000..10a0644df8 --- /dev/null +++ b/lib/spack/spack/cmd/use.py @@ -0,0 +1,50 @@ +############################################################################## +# Copyright (c) 2013, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://scalability-llnl.github.io/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (as published by +# the Free Software Foundation) version 2.1 dated February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +import argparse +import llnl.util.tty as tty +import spack + +description ="Add package to environment using dotkit." + +def setup_parser(subparser): + subparser.add_argument( + 'spec', nargs=argparse.REMAINDER, help='Spec of package to add.') + + +def print_help(): + tty.msg("Spack dotkit support is not initialized.", + "", + "To use dotkit with Spack, you must first run the command", + "below, which you can copy and paste:", + "", + "For bash:", + " . %s/setup-env.bash" % spack.share_path, + "", + "ksh/csh/tcsh shells are currently unsupported", + "") + + +def use(parser, args): + print_help() diff --git a/lib/spack/spack/hooks/__init__.py b/lib/spack/spack/hooks/__init__.py new file mode 100644 index 0000000000..4f0d574e49 --- /dev/null +++ b/lib/spack/spack/hooks/__init__.py @@ -0,0 +1,71 @@ +############################################################################## +# Copyright (c) 2013, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://scalability-llnl.github.io/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (as published by +# the Free Software Foundation) version 2.1 dated February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +"""This package contains modules with hooks for various stages in the + Spack install process. You can add modules here and they'll be + executaed by package at various times during the package lifecycle. + + Each hook is just a function that takes a package as a parameter. + Hooks are not executed in any particular order. + + Currently the following hooks are supported: + + * post_install() + * post_uninstall() + + This can be used to implement support for things like module + systems (e.g. modules, dotkit, etc.) or to add other custom + features. +""" +import imp +from llnl.util.lang import memoized, list_modules +from llnl.util.filesystem import join_path +import spack + +@memoized +def all_hook_modules(): + modules = [] + for name in list_modules(spack.hooks_path): + path = join_path(spack.hooks_path, name) + ".py" + modules.append(imp.load_source('spack.hooks', path)) + return modules + + +class HookRunner(object): + def __init__(self, hook_name): + self.hook_name = hook_name + + def __call__(self, pkg): + for module in all_hook_modules(): + if hasattr(module, self.hook_name): + hook = getattr(module, self.hook_name) + if hasattr(hook, '__call__'): + hook(pkg) + + +# +# Define some functions that can be called to fire off hooks. +# +post_install = HookRunner('post_install') +post_uninstall = HookRunner('post_uninstall') diff --git a/lib/spack/spack/hooks/dotkit.py b/lib/spack/spack/hooks/dotkit.py new file mode 100644 index 0000000000..f9920e3622 --- /dev/null +++ b/lib/spack/spack/hooks/dotkit.py @@ -0,0 +1,83 @@ +############################################################################## +# Copyright (c) 2013, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://scalability-llnl.github.io/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (as published by +# the Free Software Foundation) version 2.1 dated February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +import os +import re +import textwrap +import shutil +from contextlib import closing + +from llnl.util.filesystem import join_path + +import spack + + +def dotkit_file(pkg): + dk_file_name = pkg.spec.format('$_$@$%@$+$=$#') + ".dk" + return join_path(spack.dotkit_path, dk_file_name) + + +def post_install(pkg): + if not os.path.exists(spack.dotkit_path): + mkdirp(spack.dotkit_path) + + alterations = [] + for var, path in [ + ('PATH', pkg.prefix.bin), + ('MANPATH', pkg.prefix.man), + ('MANPATH', pkg.prefix.share_man), + ('LD_LIBRARY_PATH', pkg.prefix.lib), + ('LD_LIBRARY_PATH', pkg.prefix.lib64)]: + + if os.path.isdir(path): + alterations.append("dk_alter %s %s\n" % (var, path)) + + if not alterations: + return + + alterations.append("dk_alter CMAKE_PREFIX_PATH %s\n" % pkg.prefix) + + dk_file = dotkit_file(pkg) + with closing(open(dk_file, 'w')) as dk: + # Put everything in the spack category. + dk.write('#c spack\n') + + dk.write('#d %s\n' % pkg.spec.format("$_ $@")) + + # Recycle the description + if pkg.__doc__: + doc = re.sub(r'\s+', ' ', pkg.__doc__) + for line in textwrap.wrap(doc, 72): + dk.write("#h %s\n" % line) + + # Write alterations + for alter in alterations: + dk.write(alter) + + +def post_uninstall(pkg): + dk_file = dotkit_file(pkg) + if os.path.exists(dk_file): + shutil.rmtree(dk_file, ignore_errors=True) + diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index da599037dd..f45ddeaa6d 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -48,6 +48,7 @@ from llnl.util.lang import * import spack import spack.spec import spack.error +import spack.hooks import spack.build_environment as build_env import spack.url as url from spack.version import * @@ -495,7 +496,7 @@ class Package(object): on this one.""" dependents = [] for spec in spack.db.installed_package_specs(): - if self.name in spec.dependencies: + if self in spec.dependencies: dependents.append(spec) return dependents @@ -703,6 +704,10 @@ class Package(object): sys.exit(1) + # Once everything else is done, run post install hooks + spack.hooks.post_install(self) + + def do_install_dependencies(self): # Pass along paths of dependencies here for dep in self.spec.dependencies.values(): @@ -731,13 +736,17 @@ class Package(object): if not force: deps = self.installed_dependents + formatted_deps = [s.format('$_$@$%@$+$=$#') for s in deps] if deps: raise InstallError( "Cannot uninstall %s. The following installed packages depend on it: %s" - % (self.spec, deps)) + % (self.spec, formatted_deps)) self.remove_prefix() tty.msg("Successfully uninstalled %s." % self.spec) + # Once everything else is done, run post install hooks + spack.hooks.post_uninstall(self) + def do_clean(self): if self.stage.expanded_archive_path: diff --git a/lib/spack/spack/util/prefix.py b/lib/spack/spack/util/prefix.py index 1b5ab5933f..7bd63c16ca 100644 --- a/lib/spack/spack/util/prefix.py +++ b/lib/spack/spack/util/prefix.py @@ -69,13 +69,25 @@ class Prefix(str): s.share = join_path(s, 'share') s.doc = join_path(s.share, 'doc') s.info = join_path(s.share, 'info') - s.man = join_path(s.share, 'man') - s.man1 = join_path(s.man, 'man1') - s.man2 = join_path(s.man, 'man2') - s.man3 = join_path(s.man, 'man3') - s.man4 = join_path(s.man, 'man4') - s.man5 = join_path(s.man, 'man5') - s.man6 = join_path(s.man, 'man6') - s.man7 = join_path(s.man, 'man7') - s.man8 = join_path(s.man, 'man8') + + s.man = join_path(s, 'man') + s.man1 = join_path(s.man, 'man1') + s.man2 = join_path(s.man, 'man2') + s.man3 = join_path(s.man, 'man3') + s.man4 = join_path(s.man, 'man4') + s.man5 = join_path(s.man, 'man5') + s.man6 = join_path(s.man, 'man6') + s.man7 = join_path(s.man, 'man7') + s.man8 = join_path(s.man, 'man8') + + s.share_man = join_path(s.share, 'man') + s.share_man1 = join_path(s.share_man, 'man1') + s.share_man2 = join_path(s.share_man, 'man2') + s.share_man3 = join_path(s.share_man, 'man3') + s.share_man4 = join_path(s.share_man, 'man4') + s.share_man5 = join_path(s.share_man, 'man5') + s.share_man6 = join_path(s.share_man, 'man6') + s.share_man7 = join_path(s.share_man, 'man7') + s.share_man8 = join_path(s.share_man, 'man8') + return s |