diff options
-rw-r--r-- | lib/spack/docs/basic_usage.rst | 42 | ||||
-rw-r--r-- | lib/spack/spack/build_environment.py | 41 | ||||
-rw-r--r-- | lib/spack/spack/cmd/uninstall.py | 191 | ||||
-rw-r--r-- | lib/spack/spack/test/__init__.py | 3 | ||||
-rw-r--r-- | lib/spack/spack/test/cmd/__init__.py | 0 | ||||
-rw-r--r-- | lib/spack/spack/test/cmd/uninstall.py | 37 | ||||
-rw-r--r-- | lib/spack/spack/test/database.py | 82 | ||||
-rw-r--r-- | lib/spack/spack/test/install.py | 29 | ||||
-rw-r--r-- | lib/spack/spack/test/mock_database.py | 78 | ||||
-rw-r--r-- | var/spack/repos/builtin.mock/packages/cmake-client/package.py | 89 | ||||
-rw-r--r-- | var/spack/repos/builtin.mock/packages/cmake/package.py | 69 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/dbus/package.py | 2 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/git/package.py | 2 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/libxcb/package.py | 3 |
14 files changed, 494 insertions, 174 deletions
diff --git a/lib/spack/docs/basic_usage.rst b/lib/spack/docs/basic_usage.rst index accf09cc2a..72a02802fb 100644 --- a/lib/spack/docs/basic_usage.rst +++ b/lib/spack/docs/basic_usage.rst @@ -149,26 +149,46 @@ customize an installation in :ref:`sec-specs`. ``spack uninstall`` ~~~~~~~~~~~~~~~~~~~~~ -To uninstall a package, type ``spack uninstall <package>``. This will -completely remove the directory in which the package was installed. +To uninstall a package, type ``spack uninstall <package>``. This will ask the user for +confirmation, and in case will completely remove the directory in which the package was installed. .. code-block:: sh spack uninstall mpich If there are still installed packages that depend on the package to be -uninstalled, spack will refuse to uninstall it. You can override this -behavior with ``spack uninstall -f <package>``, but you risk breaking -other installed packages. In general, it is safer to remove dependent -packages *before* removing their dependencies. +uninstalled, spack will refuse to uninstall it. -A line like ``spack uninstall mpich`` may be ambiguous, if multiple -``mpich`` configurations are installed. For example, if both +To uninstall a package and every package that depends on it, you may give the +`--dependents` option. + +.. code-block:: sh + + spack uninstall --dependents mpich + +will display a list of all the packages that depends on `mpich` and, upon confirmation, +will uninstall them in the right order. + +A line like + +.. code-block:: sh + + spack uninstall mpich + +may be ambiguous, if multiple ``mpich`` configurations are installed. For example, if both ``mpich@3.0.2`` and ``mpich@3.1`` are installed, ``mpich`` could refer to either one. Because it cannot determine which one to uninstall, -Spack will ask you to provide a version number to remove the -ambiguity. As an example, ``spack uninstall mpich@3.1`` is -unambiguous in this scenario. +Spack will ask you either to provide a version number to remove the +ambiguity or use the ``--all`` option to uninstall all of the matching packages. + +You may force uninstall a package with the `--force` option + +.. code-block:: sh + + spack uninstall --force mpich + +but you risk breaking other installed packages. In general, it is safer to remove dependent +packages *before* removing their dependencies or use the `--dependents` option. Seeing installed packages diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 640db0c1d1..f4f8037ac0 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -213,7 +213,7 @@ def set_module_variables_for_package(pkg, module): # TODO: of build dependencies, as opposed to link dependencies. # TODO: Currently, everything is a link dependency, but tools like # TODO: this shouldn't be. - m.cmake = which("cmake") + m.cmake = Executable('cmake') # standard CMake arguments m.std_cmake_args = ['-DCMAKE_INSTALL_PREFIX=%s' % pkg.prefix, @@ -278,21 +278,6 @@ def parent_class_modules(cls): return result -def setup_module_variables_for_dag(pkg): - """Set module-scope variables for all packages in the DAG.""" - for spec in pkg.spec.traverse(order='post'): - # If a user makes their own package repo, e.g. - # spack.repos.mystuff.libelf.Libelf, and they inherit from - # an existing class like spack.repos.original.libelf.Libelf, - # then set the module variables for both classes so the - # parent class can still use them if it gets called. - spkg = spec.package - modules = parent_class_modules(spkg.__class__) - for mod in modules: - set_module_variables_for_package(spkg, mod) - set_module_variables_for_package(spkg, spkg.module) - - def setup_package(pkg): """Execute all environment setup routines.""" spack_env = EnvironmentModifications() @@ -316,20 +301,26 @@ def setup_package(pkg): set_compiler_environment_variables(pkg, spack_env) set_build_environment_variables(pkg, spack_env) - setup_module_variables_for_dag(pkg) - # Allow dependencies to modify the module + # traverse in postorder so package can use vars from its dependencies spec = pkg.spec - for dependency_spec in spec.traverse(root=False): - dpkg = dependency_spec.package - dpkg.setup_dependent_package(pkg.module, spec) + for dspec in pkg.spec.traverse(order='post'): + # If a user makes their own package repo, e.g. + # spack.repos.mystuff.libelf.Libelf, and they inherit from + # an existing class like spack.repos.original.libelf.Libelf, + # then set the module variables for both classes so the + # parent class can still use them if it gets called. + spkg = dspec.package + modules = parent_class_modules(spkg.__class__) + for mod in modules: + set_module_variables_for_package(spkg, mod) + set_module_variables_for_package(spkg, spkg.module) - # Allow dependencies to set up environment as well - for dependency_spec in spec.traverse(root=False): - dpkg = dependency_spec.package + # Allow dependencies to modify the module + dpkg = dspec.package + dpkg.setup_dependent_package(pkg.module, spec) dpkg.setup_dependent_environment(spack_env, run_env, spec) - # Allow the package to apply some settings. pkg.setup_environment(spack_env, run_env) # Make sure nothing's strange about the Spack environment. diff --git a/lib/spack/spack/cmd/uninstall.py b/lib/spack/spack/cmd/uninstall.py index 350ef372cb..1ff3d8db5f 100644 --- a/lib/spack/spack/cmd/uninstall.py +++ b/lib/spack/spack/cmd/uninstall.py @@ -23,19 +23,33 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## from __future__ import print_function -import sys + import argparse import llnl.util.tty as tty -from llnl.util.tty.colify import colify - import spack import spack.cmd import spack.repository from spack.cmd.find import display_specs -from spack.package import PackageStillNeededError -description="Remove an installed package" +description = "Remove an installed package" + +error_message = """You can either: + a) Use a more specific spec, or + b) use spack uninstall -a to uninstall ALL matching specs. +""" + + +def ask_for_confirmation(message): + while True: + tty.msg(message + '[y/n]') + choice = raw_input().lower() + if choice == 'y': + break + elif choice == 'n': + raise SystemExit('Operation aborted') + tty.warn('Please reply either "y" or "n"') + def setup_parser(subparser): subparser.add_argument( @@ -44,10 +58,101 @@ def setup_parser(subparser): subparser.add_argument( '-a', '--all', action='store_true', dest='all', help="USE CAREFULLY. Remove ALL installed packages that match each " + - "supplied spec. i.e., if you say uninstall libelf, ALL versions of " + - "libelf are uninstalled. This is both useful and dangerous, like rm -r.") + "supplied spec. i.e., if you say uninstall libelf, ALL versions of " + + "libelf are uninstalled. This is both useful and dangerous, like rm -r.") subparser.add_argument( - 'packages', nargs=argparse.REMAINDER, help="specs of packages to uninstall") + '-d', '--dependents', action='store_true', dest='dependents', + help='Also uninstall any packages that depend on the ones given via command line.' + ) + subparser.add_argument( + '-y', '--yes-to-all', action='store_true', dest='yes_to_all', + help='Assume "yes" is the answer to every confirmation asked to the user.' + + ) + subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to uninstall") + + +def concretize_specs(specs, allow_multiple_matches=False, force=False): + """ + Returns a list of specs matching the non necessarily concretized specs given from cli + + Args: + specs: list of specs to be matched against installed packages + allow_multiple_matches : boolean (if True multiple matches for each item in specs are admitted) + + Return: + list of specs + """ + specs_from_cli = [] # List of specs that match expressions given via command line + has_errors = False + for spec in specs: + matching = spack.installed_db.query(spec) + # For each spec provided, make sure it refers to only one package. + # Fail and ask user to be unambiguous if it doesn't + if not allow_multiple_matches and len(matching) > 1: + tty.error("%s matches multiple packages:" % spec) + print() + display_specs(matching, long=True) + print() + has_errors = True + + # No installed package matches the query + if len(matching) == 0 and not force: + tty.error("%s does not match any installed packages." % spec) + has_errors = True + + specs_from_cli.extend(matching) + if has_errors: + tty.die(error_message) + + return specs_from_cli + + +def installed_dependents(specs): + """ + Returns a dictionary that maps a spec with a list of its installed dependents + + Args: + specs: list of specs to be checked for dependents + + Returns: + dictionary of installed dependents + """ + dependents = {} + for item in specs: + lst = [x for x in item.package.installed_dependents if x not in specs] + if lst: + lst = list(set(lst)) + dependents[item] = lst + return dependents + + +def do_uninstall(specs, force): + """ + Uninstalls all the specs in a list. + + Args: + specs: list of specs to be uninstalled + force: force uninstallation (boolean) + """ + packages = [] + for item in specs: + try: + # should work if package is known to spack + packages.append(item.package) + except spack.repository.UnknownPackageError as e: + # The package.py file has gone away -- but still + # want to uninstall. + spack.Package(item).do_uninstall(force=True) + + # Sort packages to be uninstalled by the number of installed dependents + # This ensures we do things in the right order + def num_installed_deps(pkg): + return len(pkg.installed_dependents) + + packages.sort(key=num_installed_deps) + for item in packages: + item.do_uninstall(force=force) def uninstall(parser, args): @@ -56,50 +161,34 @@ def uninstall(parser, args): with spack.installed_db.write_transaction(): specs = spack.cmd.parse_specs(args.packages) + # Gets the list of installed specs that match the ones give via cli + uninstall_list = concretize_specs(specs, args.all, args.force) # takes care of '-a' is given in the cli + dependent_list = installed_dependents(uninstall_list) # takes care of '-d' - # For each spec provided, make sure it refers to only one package. - # Fail and ask user to be unambiguous if it doesn't - pkgs = [] - for spec in specs: - matching_specs = spack.installed_db.query(spec) - if not args.all and len(matching_specs) > 1: - tty.error("%s matches multiple packages:" % spec) - print() - display_specs(matching_specs, long=True) - print() - print("You can either:") - print(" a) Use a more specific spec, or") - print(" b) use spack uninstall -a to uninstall ALL matching specs.") - sys.exit(1) - - if len(matching_specs) == 0: - if args.force: continue - tty.die("%s does not match any installed packages." % spec) - - for s in matching_specs: - try: - # should work if package is known to spack - pkgs.append(s.package) - except spack.repository.UnknownPackageError as e: - # The package.py file has gone away -- but still - # want to uninstall. - spack.Package(s).do_uninstall(force=True) - - # Sort packages to be uninstalled by the number of installed dependents - # This ensures we do things in the right order - def num_installed_deps(pkg): - return len(pkg.installed_dependents) - pkgs.sort(key=num_installed_deps) - - # Uninstall packages in order now. - for pkg in pkgs: - try: - pkg.do_uninstall(force=args.force) - except PackageStillNeededError as e: - tty.error("Will not uninstall %s" % e.spec.format("$_$@$%@$#", color=True)) + # Process dependent_list and update uninstall_list + has_error = False + if dependent_list and not args.dependents and not args.force: + for spec, lst in dependent_list.items(): + tty.error("Will not uninstall %s" % spec.format("$_$@$%@$#", color=True)) print('') print("The following packages depend on it:") - display_specs(e.dependents, long=True) + display_specs(lst, long=True) print('') - print("You can use spack uninstall -f to force this action.") - sys.exit(1) + has_error = True + elif args.dependents: + for key, lst in dependent_list.items(): + uninstall_list.extend(lst) + uninstall_list = list(set(uninstall_list)) + + if has_error: + tty.die('You can use spack uninstall --dependents to uninstall these dependencies as well') + + if not args.yes_to_all: + tty.msg("The following packages will be uninstalled : ") + print('') + display_specs(uninstall_list, long=True) + print('') + ask_for_confirmation('Do you want to proceed ? ') + + # Uninstall everything on the list + do_uninstall(uninstall_list, args.force) diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py index cd842561e6..175a49428c 100644 --- a/lib/spack/spack/test/__init__.py +++ b/lib/spack/spack/test/__init__.py @@ -67,7 +67,8 @@ test_names = ['versions', 'namespace_trie', 'yaml', 'sbang', - 'environment'] + 'environment', + 'cmd.uninstall'] def list_tests(): diff --git a/lib/spack/spack/test/cmd/__init__.py b/lib/spack/spack/test/cmd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/spack/spack/test/cmd/__init__.py diff --git a/lib/spack/spack/test/cmd/uninstall.py b/lib/spack/spack/test/cmd/uninstall.py new file mode 100644 index 0000000000..80efe06d36 --- /dev/null +++ b/lib/spack/spack/test/cmd/uninstall.py @@ -0,0 +1,37 @@ +import spack.test.mock_database + +from spack.cmd.uninstall import uninstall + + +class MockArgs(object): + def __init__(self, packages, all=False, force=False, dependents=False): + self.packages = packages + self.all = all + self.force = force + self.dependents = dependents + self.yes_to_all = True + + +class TestUninstall(spack.test.mock_database.MockDatabase): + def test_uninstall(self): + parser = None + # Multiple matches + args = MockArgs(['mpileaks']) + self.assertRaises(SystemExit, uninstall, parser, args) + # Installed dependents + args = MockArgs(['libelf']) + self.assertRaises(SystemExit, uninstall, parser, args) + # Recursive uninstall + args = MockArgs(['callpath'], all=True, dependents=True) + uninstall(parser, args) + + all_specs = spack.install_layout.all_specs() + self.assertEqual(len(all_specs), 7) + # query specs with multiple configurations + mpileaks_specs = [s for s in all_specs if s.satisfies('mpileaks')] + callpath_specs = [s for s in all_specs if s.satisfies('callpath')] + mpi_specs = [s for s in all_specs if s.satisfies('mpi')] + + self.assertEqual(len(mpileaks_specs), 0) + self.assertEqual(len(callpath_specs), 0) + self.assertEqual(len(mpi_specs), 3) diff --git a/lib/spack/spack/test/database.py b/lib/spack/spack/test/database.py index ce6e8a0552..465263d057 100644 --- a/lib/spack/spack/test/database.py +++ b/lib/spack/spack/test/database.py @@ -28,16 +28,12 @@ both in memory and in its file """ import os.path import multiprocessing -import shutil -import tempfile import spack from llnl.util.filesystem import join_path from llnl.util.lock import * from llnl.util.tty.colify import colify -from spack.database import Database -from spack.directory_layout import YamlDirectoryLayout -from spack.test.mock_packages_test import * +from spack.test.mock_database import MockDatabase def _print_ref_counts(): @@ -75,80 +71,7 @@ def _print_ref_counts(): colify(recs, cols=3) -class DatabaseTest(MockPackagesTest): - - def _mock_install(self, spec): - s = Spec(spec) - s.concretize() - pkg = spack.repo.get(s) - pkg.do_install(fake=True) - - - def _mock_remove(self, spec): - specs = spack.installed_db.query(spec) - assert(len(specs) == 1) - spec = specs[0] - spec.package.do_uninstall(spec) - - - def setUp(self): - super(DatabaseTest, self).setUp() - # - # TODO: make the mockup below easier. - # - - # Make a fake install directory - self.install_path = tempfile.mkdtemp() - self.spack_install_path = spack.install_path - spack.install_path = self.install_path - - self.install_layout = YamlDirectoryLayout(self.install_path) - self.spack_install_layout = spack.install_layout - spack.install_layout = self.install_layout - - # Make fake database and fake install directory. - self.installed_db = Database(self.install_path) - self.spack_installed_db = spack.installed_db - spack.installed_db = self.installed_db - - # make a mock database with some packages installed note that - # the ref count for dyninst here will be 3, as it's recycled - # across each install. - # - # Here is what the mock DB looks like: - # - # o mpileaks o mpileaks' o mpileaks'' - # |\ |\ |\ - # | o callpath | o callpath' | o callpath'' - # |/| |/| |/| - # o | mpich o | mpich2 o | zmpi - # | | o | fake - # | | | - # | |______________/ - # | .____________/ - # |/ - # o dyninst - # |\ - # | o libdwarf - # |/ - # o libelf - # - - # Transaction used to avoid repeated writes. - with spack.installed_db.write_transaction(): - self._mock_install('mpileaks ^mpich') - self._mock_install('mpileaks ^mpich2') - self._mock_install('mpileaks ^zmpi') - - - def tearDown(self): - super(DatabaseTest, self).tearDown() - shutil.rmtree(self.install_path) - spack.install_path = self.spack_install_path - spack.install_layout = self.spack_install_layout - spack.installed_db = self.spack_installed_db - - +class DatabaseTest(MockDatabase): def test_005_db_exists(self): """Make sure db cache file exists after creating.""" index_file = join_path(self.install_path, '.spack-db', 'index.yaml') @@ -157,7 +80,6 @@ class DatabaseTest(MockPackagesTest): self.assertTrue(os.path.exists(index_file)) self.assertTrue(os.path.exists(lock_file)) - def test_010_all_install_sanity(self): """Ensure that the install layout reflects what we think it does.""" all_specs = spack.install_layout.all_specs() diff --git a/lib/spack/spack/test/install.py b/lib/spack/spack/test/install.py index 8297893f01..fc5b7e67df 100644 --- a/lib/spack/spack/test/install.py +++ b/lib/spack/spack/test/install.py @@ -64,7 +64,14 @@ class InstallTest(MockPackagesTest): shutil.rmtree(self.tmpdir, ignore_errors=True) - def test_install_and_uninstall(self): + def fake_fetchify(self, pkg): + """Fake the URL for a package so it downloads from a file.""" + fetcher = FetchStrategyComposite() + fetcher.append(URLFetchStrategy(self.repo.url)) + pkg.fetcher = fetcher + + + def ztest_install_and_uninstall(self): # Get a basic concrete spec for the trivial install package. spec = Spec('trivial_install_test_package') spec.concretize() @@ -73,11 +80,7 @@ class InstallTest(MockPackagesTest): # Get the package pkg = spack.repo.get(spec) - # Fake the URL for the package so it downloads from a file. - - fetcher = FetchStrategyComposite() - fetcher.append(URLFetchStrategy(self.repo.url)) - pkg.fetcher = fetcher + self.fake_fetchify(pkg) try: pkg.do_install() @@ -85,3 +88,17 @@ class InstallTest(MockPackagesTest): except Exception, e: pkg.remove_prefix() raise + + + def test_install_environment(self): + spec = Spec('cmake-client').concretized() + + for s in spec.traverse(): + self.fake_fetchify(s.package) + + pkg = spec.package + try: + pkg.do_install() + except Exception, e: + pkg.remove_prefix() + raise diff --git a/lib/spack/spack/test/mock_database.py b/lib/spack/spack/test/mock_database.py new file mode 100644 index 0000000000..6fd05439bf --- /dev/null +++ b/lib/spack/spack/test/mock_database.py @@ -0,0 +1,78 @@ +import shutil +import tempfile + +import spack +from spack.spec import Spec +from spack.database import Database +from spack.directory_layout import YamlDirectoryLayout +from spack.test.mock_packages_test import MockPackagesTest + + +class MockDatabase(MockPackagesTest): + def _mock_install(self, spec): + s = Spec(spec) + s.concretize() + pkg = spack.repo.get(s) + pkg.do_install(fake=True) + + def _mock_remove(self, spec): + specs = spack.installed_db.query(spec) + assert(len(specs) == 1) + spec = specs[0] + spec.package.do_uninstall(spec) + + def setUp(self): + super(MockDatabase, self).setUp() + # + # TODO: make the mockup below easier. + # + + # Make a fake install directory + self.install_path = tempfile.mkdtemp() + self.spack_install_path = spack.install_path + spack.install_path = self.install_path + + self.install_layout = YamlDirectoryLayout(self.install_path) + self.spack_install_layout = spack.install_layout + spack.install_layout = self.install_layout + + # Make fake database and fake install directory. + self.installed_db = Database(self.install_path) + self.spack_installed_db = spack.installed_db + spack.installed_db = self.installed_db + + # make a mock database with some packages installed note that + # the ref count for dyninst here will be 3, as it's recycled + # across each install. + # + # Here is what the mock DB looks like: + # + # o mpileaks o mpileaks' o mpileaks'' + # |\ |\ |\ + # | o callpath | o callpath' | o callpath'' + # |/| |/| |/| + # o | mpich o | mpich2 o | zmpi + # | | o | fake + # | | | + # | |______________/ + # | .____________/ + # |/ + # o dyninst + # |\ + # | o libdwarf + # |/ + # o libelf + # + + # Transaction used to avoid repeated writes. + with spack.installed_db.write_transaction(): + self._mock_install('mpileaks ^mpich') + self._mock_install('mpileaks ^mpich2') + self._mock_install('mpileaks ^zmpi') + + def tearDown(self): + super(MockDatabase, self).tearDown() + shutil.rmtree(self.install_path) + spack.install_path = self.spack_install_path + spack.install_layout = self.spack_install_layout + spack.installed_db = self.spack_installed_db diff --git a/var/spack/repos/builtin.mock/packages/cmake-client/package.py b/var/spack/repos/builtin.mock/packages/cmake-client/package.py new file mode 100644 index 0000000000..a5d3ef156a --- /dev/null +++ b/var/spack/repos/builtin.mock/packages/cmake-client/package.py @@ -0,0 +1,89 @@ +############################################################################## +# 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://github.com/llnl/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 +############################################################################## +from spack import * +import os + +def check(condition, msg): + """Raise an install error if condition is False.""" + if not condition: + raise InstallError(msg) + + +class CmakeClient(Package): + """A dumy package that uses cmake.""" + homepage = 'https://www.example.com' + url = 'https://www.example.com/cmake-client-1.0.tar.gz' + + version('1.0', '4cb3ff35b2472aae70f542116d616e63') + + depends_on('cmake') + + + def setup_environment(self, spack_env, run_env): + spack_cc # Ensure spack module-scope variable is avaiabl + check(from_cmake == "from_cmake", + "setup_environment couldn't read global set by cmake.") + + check(self.spec['cmake'].link_arg == "test link arg", + "link arg on dependency spec not readable from setup_environment.") + + + def setup_dependent_environment(self, spack_env, run_env, dspec): + spack_cc # Ensure spack module-scope variable is avaiable + check(from_cmake == "from_cmake", + "setup_dependent_environment couldn't read global set by cmake.") + + check(self.spec['cmake'].link_arg == "test link arg", + "link arg on dependency spec not readable from setup_dependent_environment.") + + + def setup_dependent_package(self, module, dspec): + spack_cc # Ensure spack module-scope variable is avaiable + check(from_cmake == "from_cmake", + "setup_dependent_package couldn't read global set by cmake.") + + check(self.spec['cmake'].link_arg == "test link arg", + "link arg on dependency spec not readable from setup_dependent_package.") + + + + def install(self, spec, prefix): + # check that cmake is in the global scope. + global cmake + check(cmake is not None, "No cmake was in environment!") + + # check that which('cmake') returns the right one. + cmake = which('cmake') + check(cmake.exe[0].startswith(spec['cmake'].prefix.bin), + "Wrong cmake was in environment: %s" % cmake) + + check(from_cmake == "from_cmake", + "Couldn't read global set by cmake.") + + check(os.environ['from_cmake'] == 'from_cmake', + "Couldn't read env var set in envieonmnt by dependency") + + mkdirp(prefix.bin) + touch(join_path(prefix.bin, 'dummy')) diff --git a/var/spack/repos/builtin.mock/packages/cmake/package.py b/var/spack/repos/builtin.mock/packages/cmake/package.py new file mode 100644 index 0000000000..deb44c2bf7 --- /dev/null +++ b/var/spack/repos/builtin.mock/packages/cmake/package.py @@ -0,0 +1,69 @@ +############################################################################## +# 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://github.com/llnl/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 +############################################################################## +from spack import * +import os + +def check(condition, msg): + """Raise an install error if condition is False.""" + if not condition: + raise InstallError(msg) + + +class Cmake(Package): + """A dumy package for the cmake build system.""" + homepage = 'https://www.cmake.org' + url = 'https://cmake.org/files/v3.4/cmake-3.4.3.tar.gz' + + version('3.4.3', '4cb3ff35b2472aae70f542116d616e63', + url='https://cmake.org/files/v3.4/cmake-3.4.3.tar.gz') + + + def setup_environment(self, spack_env, run_env): + spack_cc # Ensure spack module-scope variable is avaiable + spack_env.set('for_install', 'for_install') + + def setup_dependent_environment(self, spack_env, run_env, dspec): + spack_cc # Ensure spack module-scope variable is avaiable + spack_env.set('from_cmake', 'from_cmake') + + + def setup_dependent_package(self, module, dspec): + spack_cc # Ensure spack module-scope variable is avaiable + + self.spec.from_cmake = "from_cmake" + module.from_cmake = "from_cmake" + + self.spec.link_arg = "test link arg" + + + def install(self, spec, prefix): + mkdirp(prefix.bin) + + check(os.environ['for_install'] == 'for_install', + "Couldn't read env var set in compile envieonmnt") + + cmake_exe = join_path(prefix.bin, 'cmake') + touch(cmake_exe) + set_executable(cmake_exe) diff --git a/var/spack/repos/builtin/packages/dbus/package.py b/var/spack/repos/builtin/packages/dbus/package.py index 422f5a19eb..74ce8ef502 100644 --- a/var/spack/repos/builtin/packages/dbus/package.py +++ b/var/spack/repos/builtin/packages/dbus/package.py @@ -20,6 +20,8 @@ class Dbus(Package): version('1.8.4', '4717cb8ab5b80978fcadf2b4f2f72e1b') version('1.8.2', 'd6f709bbec0a022a1847c7caec9d6068') + depends_on('expat') + def install(self, spec, prefix): configure( "--prefix=%s" % prefix, diff --git a/var/spack/repos/builtin/packages/git/package.py b/var/spack/repos/builtin/packages/git/package.py index 586b6ce3c3..388f84aefd 100644 --- a/var/spack/repos/builtin/packages/git/package.py +++ b/var/spack/repos/builtin/packages/git/package.py @@ -36,6 +36,8 @@ class Git(Package): depends_on("curl", when="+curl") depends_on("expat", when="+expat") + # Also depends_on gettext: apt-get install gettext (Ubuntu) + # Use system perl for now. # depends_on("perl") # depends_on("pcre") diff --git a/var/spack/repos/builtin/packages/libxcb/package.py b/var/spack/repos/builtin/packages/libxcb/package.py index 1dd5954c99..d7d94c4546 100644 --- a/var/spack/repos/builtin/packages/libxcb/package.py +++ b/var/spack/repos/builtin/packages/libxcb/package.py @@ -14,6 +14,9 @@ class Libxcb(Package): depends_on("python") depends_on("xcb-proto") + # depends_on('pthread') # Ubuntu: apt-get install libpthread-stubs0-dev + # depends_on('xau') # Ubuntu: apt-get install libxau-dev + def patch(self): filter_file('typedef struct xcb_auth_info_t {', 'typedef struct {', 'src/xcb.h') |