summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2014-07-08 01:56:32 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2014-07-08 01:58:20 -0700
commit295ffd8c506821ed079d2151fb21cd27979d7387 (patch)
tree44b667a383aedfe5c97cebbe1e021791f4ec831e /lib
parent05516389441e6818ff3ee22bb4e51d50b3bb5cd4 (diff)
downloadspack-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__.py12
-rw-r--r--lib/spack/spack/__init__.py5
-rw-r--r--lib/spack/spack/cmd/dotkit.py99
-rw-r--r--lib/spack/spack/cmd/find.py14
-rw-r--r--lib/spack/spack/cmd/unuse.py36
-rw-r--r--lib/spack/spack/cmd/use.py50
-rw-r--r--lib/spack/spack/hooks/__init__.py71
-rw-r--r--lib/spack/spack/hooks/dotkit.py83
-rw-r--r--lib/spack/spack/package.py13
-rw-r--r--lib/spack/spack/util/prefix.py30
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