diff --git a/lib/spack/spack/directory_layout.py b/lib/spack/spack/directory_layout.py index aed42f4a2ce1bec48fda624cf9ef03fe558c461c..7f581dfe29cfa9d54d64ba87fc4204f584d5ac2e 100644 --- a/lib/spack/spack/directory_layout.py +++ b/lib/spack/spack/directory_layout.py @@ -9,6 +9,12 @@ from spack.error import SpackError +def _check_concrete(spec): + """If the spec is not concrete, raise a ValueError""" + if not spec.concrete: + raise ValueError('Specs passed to a DirectoryLayout must be concrete!') + + class DirectoryLayout(object): """A directory layout is used to associate unique paths with specs. Different installations are going to want differnet layouts for their @@ -39,7 +45,8 @@ def make_path_for_spec(self, spec): def path_for_spec(self, spec): """Return an absolute path from the root to a directory for the spec.""" - assert(spec.concrete) + _check_concrete(spec) + path = self.relative_path_for_spec(spec) assert(not path.startswith(self.root)) return os.path.join(self.root, path) @@ -105,7 +112,7 @@ def __init__(self, root, **kwargs): def relative_path_for_spec(self, spec): - assert(spec.concrete) + _check_concrete(spec) path = new_path( spec.architecture, @@ -134,7 +141,7 @@ def read_spec(self, path): def make_path_for_spec(self, spec): - assert(spec.concrete) + _check_concrete(spec) path = self.path_for_spec(spec) spec_file_path = new_path(path, self.spec_file) @@ -200,5 +207,3 @@ class InstallDirectoryAlreadyExistsError(DirectoryLayoutError): def __init__(self, path): super(InstallDirectoryAlreadyExistsError, self).__init__( "Install path %s already exists!") - - diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index cb779c404751641f1ea0903db87ba00ae4243068..acbc7fc927419a42f78ec8f727fb16f38073f5ab 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -67,7 +67,7 @@ class Cmake(Package): url = 'http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz' md5 = '097278785da7182ec0aea8769d06860c' - def install(self, prefix): + def install(self, spec, prefix): configure('--prefix=%s' % prefix, '--parallel=%s' % make_jobs) make() @@ -407,27 +407,9 @@ def add_commands_to_module(self): m.rmtree = shutil.rmtree m.move = shutil.move - # Useful directories within the prefix + # Useful directories within the prefix are encapsulated in + # a Prefix object. m.prefix = self.prefix - m.bin = new_path(self.prefix, 'bin') - m.sbin = new_path(self.prefix, 'sbin') - m.etc = new_path(self.prefix, 'etc') - m.include = new_path(self.prefix, 'include') - m.lib = new_path(self.prefix, 'lib') - m.lib64 = new_path(self.prefix, 'lib64') - m.libexec = new_path(self.prefix, 'libexec') - m.share = new_path(self.prefix, 'share') - m.doc = new_path(m.share, 'doc') - m.info = new_path(m.share, 'info') - m.man = new_path(m.share, 'man') - m.man1 = new_path(m.man, 'man1') - m.man2 = new_path(m.man, 'man2') - m.man3 = new_path(m.man, 'man3') - m.man4 = new_path(m.man, 'man4') - m.man5 = new_path(m.man, 'man5') - m.man6 = new_path(m.man, 'man6') - m.man7 = new_path(m.man, 'man7') - m.man8 = new_path(m.man, 'man8') def preorder_traversal(self, visited=None, **kwargs): @@ -529,7 +511,7 @@ def installed_dependents(self): @property def prefix(self): """Get the prefix into which this package should be installed.""" - return spack.install_layout.path_for_spec(self.spec) + return self.spec.prefix def url_version(self, version): @@ -620,7 +602,7 @@ def do_install(self): # case it needs to add extra files) spack.install_layout.make_path_for_spec(self.spec) - self.install(self.prefix) + self.install(self.spec, self.prefix) if not os.path.isdir(self.prefix): tty.die("Install failed for %s. No install dir created." % self.name) @@ -683,7 +665,7 @@ def module(self): fromlist=[self.__class__.__name__]) - def install(self, prefix): + def install(self, spec, prefix): """Package implementations override this with their own build configuration.""" tty.die("Packages must provide an install method!") diff --git a/lib/spack/spack/packages/callpath.py b/lib/spack/spack/packages/callpath.py index e5102a5fad0e94b5777c44e7a066453853e29237..267f4a4e4997d2f5d817ab3dae0b1fe7be82f290 100644 --- a/lib/spack/spack/packages/callpath.py +++ b/lib/spack/spack/packages/callpath.py @@ -7,7 +7,7 @@ class Callpath(Package): depends_on("dyninst") depends_on("mpich") - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/packages/cmake.py b/lib/spack/spack/packages/cmake.py index d73cdd2c88fa2c679148eab67ad041fbb27e9c4f..3ee294b134bd3c3314fbb74c1537a9970e22232d 100644 --- a/lib/spack/spack/packages/cmake.py +++ b/lib/spack/spack/packages/cmake.py @@ -5,7 +5,7 @@ class Cmake(Package): url = 'http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz' versions = { '2.8.10.2' : '097278785da7182ec0aea8769d06860c' } - def install(self, prefix): + def install(self, spec, prefix): configure('--prefix=%s' % prefix, '--parallel=%s' % make_jobs) make() diff --git a/lib/spack/spack/packages/dyninst.py b/lib/spack/spack/packages/dyninst.py index 7648a389ee74120fc388f2cba9c5aa722e7a1e3e..187cc2bb5ab99da3739bf774e4d560882bf1213c 100644 --- a/lib/spack/spack/packages/dyninst.py +++ b/lib/spack/spack/packages/dyninst.py @@ -11,7 +11,7 @@ class Dyninst(Package): depends_on("libelf") depends_on("libdwarf") - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/packages/libdwarf.py b/lib/spack/spack/packages/libdwarf.py index 928a007193096549e22a5233961870432766625b..3102c3d4dd65c9150643f1b8a887ce6c3abec637 100644 --- a/lib/spack/spack/packages/libdwarf.py +++ b/lib/spack/spack/packages/libdwarf.py @@ -23,21 +23,21 @@ def clean(self): make('clean') - def install(self, prefix): + def install(self, spec, prefix): # dwarf build does not set arguments for ar properly make.add_default_arg('ARFLAGS=rcs') # Dwarf doesn't provide an install, so we have to do it. - mkdirp(bin, include, lib, man1) + mkdirp(prefix.bin, prefix.include, prefix.lib, prefix.man1) with working_dir('libdwarf'): configure("--prefix=%s" % prefix, '--enable-shared') make() - install('libdwarf.a', lib) - install('libdwarf.so', lib) - install('libdwarf.h', include) - install('dwarf.h', include) + install('libdwarf.a', prefix.lib) + install('libdwarf.so', prefix.lib) + install('libdwarf.h', prefix.include) + install('dwarf.h', prefix.include) with working_dir('dwarfdump2'): configure("--prefix=%s" % prefix) @@ -46,6 +46,6 @@ def install(self, prefix): # cause a race in parallel make(parallel=False) - install('dwarfdump', bin) - install('dwarfdump.conf', lib) - install('dwarfdump.1', man1) + install('dwarfdump', prefix.bin) + install('dwarfdump.conf', prefix.lib) + install('dwarfdump.1', prefix.man1) diff --git a/lib/spack/spack/packages/libelf.py b/lib/spack/spack/packages/libelf.py index 621444706e548ba3e6e860c71290fc365066b470..98e873669361b06f453b36cf0f8ef61698400267 100644 --- a/lib/spack/spack/packages/libelf.py +++ b/lib/spack/spack/packages/libelf.py @@ -6,7 +6,7 @@ class Libelf(Package): versions = { '0.8.13' : '4136d7b4c04df68b686570afa26988ac' } - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix, "--enable-shared", "--disable-dependency-tracking", diff --git a/lib/spack/spack/packages/libunwind.py b/lib/spack/spack/packages/libunwind.py index f53985709e4600d0d68a200f512247e834225b0c..0366ebefbab296619ca1c5809ad07f16e96eed4d 100644 --- a/lib/spack/spack/packages/libunwind.py +++ b/lib/spack/spack/packages/libunwind.py @@ -6,7 +6,7 @@ class Libunwind(Package): versions = { '1.1' : 'fb4ea2f6fbbe45bf032cd36e586883ce' } - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/packages/mpich.py b/lib/spack/spack/packages/mpich.py index 8cd201f965f013ac34c6cc58fac9e3f1a9de27d4..a21db55fe887d5145db98730af0b37301a688ee2 100644 --- a/lib/spack/spack/packages/mpich.py +++ b/lib/spack/spack/packages/mpich.py @@ -13,7 +13,7 @@ class Mpich(Package): provides('mpi@:3', when='@3:') provides('mpi@:1', when='@1:') - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/packages/mpileaks.py b/lib/spack/spack/packages/mpileaks.py index ffeb38ea45273bfbe2b4133a2c0d849989f4c957..41b7df058746f864d2bbdb8bb01b59e400e41817 100644 --- a/lib/spack/spack/packages/mpileaks.py +++ b/lib/spack/spack/packages/mpileaks.py @@ -7,7 +7,7 @@ class Mpileaks(Package): depends_on("mpich") depends_on("callpath") - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index c27203f05e28558827efd40b7aa2437598d2d0ee..3aba17142becf49e3a53e74334039cff65b4d4d8 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -82,6 +82,7 @@ from spack.color import * from spack.util.lang import * from spack.util.string import * +from spack.util.prefix import Prefix # Convenient names for color formats so that other things can use them @@ -439,6 +440,11 @@ def preorder_traversal(self, visited=None, d=0, **kwargs): yield elt + @property + def prefix(self): + return Prefix(spack.install_layout.path_for_spec(self)) + + def _concretize_helper(self, presets=None, visited=None): """Recursive helper function for concretize(). This concretizes everything bottom-up. As things are diff --git a/lib/spack/spack/test/mock_packages/callpath.py b/lib/spack/spack/test/mock_packages/callpath.py index e9ad344eaa9b8e8f935c795a624325912a21b14d..8d8949942f6c877b70997e441229a25ef637541a 100644 --- a/lib/spack/spack/test/mock_packages/callpath.py +++ b/lib/spack/spack/test/mock_packages/callpath.py @@ -11,7 +11,7 @@ class Callpath(Package): depends_on("dyninst") depends_on("mpi") - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/test/mock_packages/dyninst.py b/lib/spack/spack/test/mock_packages/dyninst.py index 6940c7788dc567211c75639fc3a507b8d6aa5b5e..c4c779f54caba5adb7e9d571b8e4c4ceedacaa19 100644 --- a/lib/spack/spack/test/mock_packages/dyninst.py +++ b/lib/spack/spack/test/mock_packages/dyninst.py @@ -12,7 +12,7 @@ class Dyninst(Package): depends_on("libelf") depends_on("libdwarf") - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/test/mock_packages/fake.py b/lib/spack/spack/test/mock_packages/fake.py index 68077f5f82897e93cc57e89c5186781256dac33b..c1356180e9a9a574178d33e86bfe5320dcba8aea 100644 --- a/lib/spack/spack/test/mock_packages/fake.py +++ b/lib/spack/spack/test/mock_packages/fake.py @@ -5,7 +5,7 @@ class Fake(Package): url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz" versions = { '1.0' : 'foobarbaz' } - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/test/mock_packages/libdwarf.py b/lib/spack/spack/test/mock_packages/libdwarf.py index ccfff562869b52d21f2bad8dd97559d2951d0384..1bb9fbc889cca744857c1cfa955c972394e511aa 100644 --- a/lib/spack/spack/test/mock_packages/libdwarf.py +++ b/lib/spack/spack/test/mock_packages/libdwarf.py @@ -23,21 +23,21 @@ def clean(self): make('clean') - def install(self, prefix): + def install(self, spec, prefix): # dwarf build does not set arguments for ar properly make.add_default_arg('ARFLAGS=rcs') # Dwarf doesn't provide an install, so we have to do it. - mkdirp(bin, include, lib, man1) + mkdirp(prefix.bin, prefix.include, prefix.lib, prefix.man1) with working_dir('libdwarf'): configure("--prefix=%s" % prefix, '--enable-shared') make() - install('libdwarf.a', lib) - install('libdwarf.so', lib) - install('libdwarf.h', include) - install('dwarf.h', include) + install('libdwarf.a', prefix.lib) + install('libdwarf.so', prefix.lib) + install('libdwarf.h', prefix.include) + install('dwarf.h', prefix.include) with working_dir('dwarfdump2'): configure("--prefix=%s" % prefix) @@ -46,6 +46,6 @@ def install(self, prefix): # cause a race in parallel make(parallel=False) - install('dwarfdump', bin) - install('dwarfdump.conf', lib) - install('dwarfdump.1', man1) + install('dwarfdump', prefix.bin) + install('dwarfdump.conf', prefix.lib) + install('dwarfdump.1', prefix.man1) diff --git a/lib/spack/spack/test/mock_packages/libelf.py b/lib/spack/spack/test/mock_packages/libelf.py index 75948b26fba42cf117f191bdd3df449479562bd1..4d6b62b96bcc7f486ec64a84a3c799c77797e5e1 100644 --- a/lib/spack/spack/test/mock_packages/libelf.py +++ b/lib/spack/spack/test/mock_packages/libelf.py @@ -8,7 +8,7 @@ class Libelf(Package): '0.8.12' : 'e21f8273d9f5f6d43a59878dc274fec7', '0.8.10' : '9db4d36c283d9790d8fa7df1f4d7b4d9' } - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix, "--enable-shared", "--disable-dependency-tracking", diff --git a/lib/spack/spack/test/mock_packages/mpich.py b/lib/spack/spack/test/mock_packages/mpich.py index c2a479c07a1ad14051ee31a7d38aa589b1af2ef1..351d224dc029f086218a7a742509f86cb2ca7210 100644 --- a/lib/spack/spack/test/mock_packages/mpich.py +++ b/lib/spack/spack/test/mock_packages/mpich.py @@ -15,7 +15,7 @@ class Mpich(Package): provides('mpi@:3', when='@3:') provides('mpi@:1', when='@1:') - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/test/mock_packages/mpich2.py b/lib/spack/spack/test/mock_packages/mpich2.py index ecf99925ccac726b67bb046d3a66b9deb2011914..382cac977ab2bb61339dbb55f7ba6ca4bc595df5 100644 --- a/lib/spack/spack/test/mock_packages/mpich2.py +++ b/lib/spack/spack/test/mock_packages/mpich2.py @@ -17,7 +17,7 @@ class Mpich2(Package): provides('mpi@:2.1', when='@1.1:') provides('mpi@:2.2', when='@1.2:') - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/test/mock_packages/mpileaks.py b/lib/spack/spack/test/mock_packages/mpileaks.py index 6f9b143e9d1acb069f42ed6be2c469566378d2c4..da71ff65bb91eb777191ff559c3cb7f2a39172ec 100644 --- a/lib/spack/spack/test/mock_packages/mpileaks.py +++ b/lib/spack/spack/test/mock_packages/mpileaks.py @@ -12,7 +12,7 @@ class Mpileaks(Package): depends_on("mpi") depends_on("callpath") - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/test/mock_packages/zmpi.py b/lib/spack/spack/test/mock_packages/zmpi.py index 93b6193eecdb7e18c65fbae9938ffc70e115d440..ec7e6fcdab48217a34ed0fb624965547e7314f36 100644 --- a/lib/spack/spack/test/mock_packages/zmpi.py +++ b/lib/spack/spack/test/mock_packages/zmpi.py @@ -11,7 +11,7 @@ class Zmpi(Package): provides('mpi@:10.0') depends_on('fake') - def install(self, prefix): + def install(self, spec, prefix): configure("--prefix=%s" % prefix) make() make("install") diff --git a/lib/spack/spack/util/prefix.py b/lib/spack/spack/util/prefix.py new file mode 100644 index 0000000000000000000000000000000000000000..f0ab790a170fd193544686b67dc696522434eb09 --- /dev/null +++ b/lib/spack/spack/util/prefix.py @@ -0,0 +1,67 @@ +""" +This file contains utilities to help with installing packages. +""" +from spack.util.filesystem import new_path + +class Prefix(object): + """This class represents an installation prefix, but provides useful + attributes for referring to directories inside the prefix. + + For example, you can do something like this:: + + prefix = Prefix('/usr') + print prefix.lib + print prefix.lib64 + print prefix.bin + print prefix.share + print prefix.man4 + + This program would print: + + /usr/lib + /usr/lib64 + /usr/bin + /usr/share + /usr/share/man/man4 + + In addition, Prefix objects can be added to strings, e.g.: + + print "foobar " + prefix + + This prints 'foobar /usr". All of this is meant to make custom + installs easy. + """ + + def __init__(self, prefix): + self.prefix = prefix + self.bin = new_path(self.prefix, 'bin') + self.sbin = new_path(self.prefix, 'sbin') + self.etc = new_path(self.prefix, 'etc') + self.include = new_path(self.prefix, 'include') + self.lib = new_path(self.prefix, 'lib') + self.lib64 = new_path(self.prefix, 'lib64') + self.libexec = new_path(self.prefix, 'libexec') + self.share = new_path(self.prefix, 'share') + self.doc = new_path(self.share, 'doc') + self.info = new_path(self.share, 'info') + self.man = new_path(self.share, 'man') + self.man1 = new_path(self.man, 'man1') + self.man2 = new_path(self.man, 'man2') + self.man3 = new_path(self.man, 'man3') + self.man4 = new_path(self.man, 'man4') + self.man5 = new_path(self.man, 'man5') + self.man6 = new_path(self.man, 'man6') + self.man7 = new_path(self.man, 'man7') + self.man8 = new_path(self.man, 'man8') + + + def __str__(self): + return self.prefix + + + def __add__(self, other): + return str(self) + other + + + def __radd__(self, other): + return other + str(self)