summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/basic_usage.rst9
-rw-r--r--lib/spack/docs/case_studies.rst167
-rw-r--r--lib/spack/docs/index.rst1
-rw-r--r--lib/spack/docs/packaging_guide.rst5
-rw-r--r--lib/spack/spack/cmd/info.py2
-rw-r--r--lib/spack/spack/compilers/clang.py2
-rw-r--r--lib/spack/spack/modules.py57
-rw-r--r--lib/spack/spack/package.py6
-rw-r--r--lib/spack/spack/test/operating_system.py75
9 files changed, 231 insertions, 93 deletions
diff --git a/lib/spack/docs/basic_usage.rst b/lib/spack/docs/basic_usage.rst
index a42d941791..a5478d10c2 100644
--- a/lib/spack/docs/basic_usage.rst
+++ b/lib/spack/docs/basic_usage.rst
@@ -6,6 +6,15 @@ Basic usage
The ``spack`` command has many *subcommands*. You'll only need a
small subset of them for typical usage.
+Note that Spack colorizes output. ``less -R`` should be used with
+Spack to maintian this colorization. Eg::
+
+ spack find | less -R
+
+It is recommend that the following be put in your ``.bashrc`` file::
+
+ alias less='less -R'
+
Listing available packages
------------------------------
diff --git a/lib/spack/docs/case_studies.rst b/lib/spack/docs/case_studies.rst
new file mode 100644
index 0000000000..bcd754fdcd
--- /dev/null
+++ b/lib/spack/docs/case_studies.rst
@@ -0,0 +1,167 @@
+Using Spack for CMake-based Development
+==========================================
+
+These are instructions on how to use Spack to aid in the development
+of a CMake-based project. Spack is used to help find the dependencies
+for the project, configure it at development time, and then package it
+it in a way that others can install. Using Spack for CMake-based
+development consists of three parts:
+
+1. Setting up the CMake build in your software
+2. Writing the Spack Package
+3. Using it from Spack.
+
+
+Setting Up the CMake Build
+---------------------------------------
+
+You should follow standard CMake conventions in setting up your
+software, your CMake build should NOT depend on or require Spack to
+build. See here for an example:
+ https://github.com/citibeth/icebin
+
+Note that there's one exception here to the rule I mentioned above.
+In ``CMakeLists.txt``, I have the following line::
+
+ include_directories($ENV{CMAKE_TRANSITIVE_INCLUDE_PATH})
+
+
+This is a hook into Spack, and it ensures that all transitive
+dependencies are included in the include path. It's not needed if
+everything is in one tree, but it is (sometimes) in the Spack world;
+when running without Spack, it has no effect.
+
+Note that this "feature" is controversial, could break with future
+versions of GNU ld, and probably not the best to use. The best
+practice is that you make sure that anything you #include is listed as
+a dependency in your CMakeLists.txt.
+
+To be more specific: if you #inlcude something from package A and an
+installed HEADER FILE in A #includes something from package B, then
+you should also list B as a dependency in your CMake build. If you
+depend on A but header files exported by A do NOT #include things from
+B, then you do NOT need to list B as a dependency --- even if linking
+to A links in libB.so as well.
+
+I also recommend that you set up your CMake build to use RPATHs
+correctly. Not only is this a good idea and nice, but it also ensures
+that your package will build the same with or without ``spack
+install``.
+
+Writing the Spack Package
+---------------------------------------
+
+Now that you have a CMake build, you want to tell Spack how to
+configure it. This is done by writing a Spack package for your
+software. See here for example:
+ https://github.com/citibeth/spack/blob/efischer/develop/var/spack/repos/builtin/packages/icebin/package.py
+
+You need to subclass ``CMakePackage``, as is done in this example.
+This enables advanced features of Spack for helping you in configuring
+your software (keep reading...). Instead of an ``install()`` method
+used when subclassing ``Package``, you write ``configure_args()``.
+See here for more info on how this works:
+ https://github.com/LLNL/spack/pull/543/files
+
+NOTE: if your software is not publicly available, you do not need to
+set the URL or version. Or you can set up bogus URLs and
+versions... whatever causes Spack to not crash.
+
+
+Using it from Spack
+--------------------------------
+
+Now that you have a Spack package, you can get Spack to setup your
+CMake project for you. Use the following to setup, configure and
+build your project::
+
+ cd myproject
+ spack spconfig myproject@local
+ mkdir build; cd build
+ ../spconfig.py ..
+ make
+ make install
+
+
+Everything here should look pretty familiar here from a CMake
+perspective, except that ``spack spconfig`` creates the file
+``spconfig.py``, which calls CMake with arguments appropriate for your
+Spack configuration. Think of it as the equivalent to running a bunch
+of ``spack location -i`` commands. You will run ``spconfig.py``
+instead of running CMake directly.
+
+If your project is publicly available (eg on GitHub), then you can
+ALSO use this setup to "just install" a release version without going
+through the manual configuration/build step. Just do:
+
+1. Put tag(s) on the version(s) in your GitHub repo you want to be release versions.
+
+2. Set the ``url`` in your ``package.py`` to download a tarball for
+ the appropriate version. (GitHub will give you a tarball for any
+ version in the repo, if you tickle it the right way). For example::
+
+ https://github.com/citibeth/icebin/tarball/v0.1.0
+
+ Set up versions as appropriate in your ``package.py``. (Manually
+ download the tarball and run ``md5sum`` to determine the
+ appropriate checksum for it).
+
+3. Now you should be able to say ``spack install myproject@version``
+ and things "just work."
+
+NOTE... in order to use the features outlined in this post, you
+currently need to use the following branch of Spack:
+ https://github.com/citibeth/spack/tree/efischer/develop
+
+There is a pull request open on this branch (
+https://github.com/LLNL/spack/pull/543 ) and we are working to get it
+integrated into the main ``develop`` branch.
+
+
+Activating your Software
+-------------------------------------
+
+Once you've built your software, you will want to load it up. You can
+use ``spack load mypackage@local`` for that in your ``.bashrc``, but
+that is slow. Try stuff like the following instead:
+
+The following command will load the Spack-installed packages needed
+for basic Python use of IceBin::
+
+ module load `spack module find tcl icebin netcdf cmake@3.5.1`
+ module load `spack module find --dependencies tcl py-basemap py-giss`
+
+
+You can speed up shell startup by turning these into ``module load`` commands.
+
+1. Cut-n-paste the script ``make_spackenv``::
+
+ #!/bin/sh
+ #
+ # Generate commands to load the Spack environment
+
+ SPACKENV=$HOME/spackenv.sh
+
+ spack module find --shell tcl git icebin@local ibmisc netcdf cmake@3.5.1 >$SPACKENV
+ spack module find --dependencies --shell tcl py-basemap py-giss >>$SPACKENV
+
+2. Add the following to your ``.bashrc`` file::
+
+ source $HOME/spackenv.sh
+ # Preferentially use your checked-out Python source
+ export PYTHONPATH=$HOME/icebin/pylib:$PYTHONPATH
+
+3. Run ``sh make_spackenv`` whenever your Spack installation changes (including right now).
+
+
+Giving Back
+-------------------
+
+If your software is publicly available, you should submit the
+``package.py`` for it as a pull request to the main Spack GitHub
+project. This will ensure that anyone can install your software
+(almost) painlessly with a simple ``spack install`` command. See here
+for how that has turned into detailed instructions that have
+successfully enabled collaborators to install complex software:
+
+ https://github.com/citibeth/icebin/blob/develop/README.rst
diff --git a/lib/spack/docs/index.rst b/lib/spack/docs/index.rst
index 98ed9ff0fe..a5bbd4e23b 100644
--- a/lib/spack/docs/index.rst
+++ b/lib/spack/docs/index.rst
@@ -49,6 +49,7 @@ Table of Contents
mirrors
configuration
developer_guide
+ case_studies
command_index
package_list
API Docs <spack>
diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst
index a082b85efa..879beb2476 100644
--- a/lib/spack/docs/packaging_guide.rst
+++ b/lib/spack/docs/packaging_guide.rst
@@ -401,10 +401,11 @@ the ``url`` declaration. For example:
:linenos:
class Foo(Package):
+ version('8.2.1', '4136d7b4c04df68b686570afa26988ac')
+ ...
def url_for_version(self, version):
return 'http://example.com/version_%s/foo-%s.tar.gz' \
% (version, version)
- version('8.2.1', '4136d7b4c04df68b686570afa26988ac')
...
If a URL cannot be derived systematically, you can add an explicit URL
@@ -433,7 +434,7 @@ executables and other custom archive types), you can add
.. code-block:: python
version('8.2.1', '4136d7b4c04df68b686570afa26988ac',
- url='http://example.com/foo-8.2.1-special-version.tar.gz', 'expand=False')
+ url='http://example.com/foo-8.2.1-special-version.tar.gz', expand=False)
When ``expand`` is set to ``False``, Spack sets the current working
directory to the directory containing the downloaded archive before it
diff --git a/lib/spack/spack/cmd/info.py b/lib/spack/spack/cmd/info.py
index 498518057b..2fa3a07525 100644
--- a/lib/spack/spack/cmd/info.py
+++ b/lib/spack/spack/cmd/info.py
@@ -87,7 +87,7 @@ def print_text_info(pkg):
for deptype in ('build', 'link', 'run'):
print
print "%s Dependencies:" % deptype.capitalize()
- deps = pkg.dependencies_of_type(deptype)
+ deps = sorted(pkg.dependencies_of_type(deptype))
if deps:
colify(deps, indent=4)
else:
diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py
index 4cf65222ae..36c91f6670 100644
--- a/lib/spack/spack/compilers/clang.py
+++ b/lib/spack/spack/compilers/clang.py
@@ -101,7 +101,7 @@ class Clang(Compiler):
ver = match.group(1) + '-apple'
else:
# Normal clang compiler versions are left as-is
- match = re.search(r'^clang version ([^ )]+)', output)
+ match = re.search(r'clang version ([^ )]+)', output)
if match:
ver = match.group(1)
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index debc6752b4..70c3c35d8c 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -530,13 +530,6 @@ class Dotkit(EnvModule):
class TclModule(EnvModule):
name = 'tcl'
path = join_path(spack.share_path, "modules")
- environment_modifications_formats = {
- PrependPath: 'prepend-path --delim "{separator}" {name} \"{value}\"\n',
- AppendPath: 'append-path --delim "{separator}" {name} \"{value}\"\n',
- RemovePath: 'remove-path --delim "{separator}" {name} \"{value}\"\n',
- SetEnv: 'setenv {name} \"{value}\"\n',
- UnsetEnv: 'unsetenv {name}\n'
- }
autoload_format = ('if ![ is-loaded {module_file} ] {{\n'
' puts stderr "Autoloading {module_file}"\n'
@@ -556,11 +549,13 @@ class TclModule(EnvModule):
def header(self):
timestamp = datetime.datetime.now()
# TCL Modulefile header
- header = '#%Module1.0\n'
- header += '## Module file created by spack (https://github.com/LLNL/spack) on %s\n' % timestamp
- header += '##\n'
- header += '## %s\n' % self.spec.short_spec
- header += '##\n'
+ header = """\
+#%%Module1.0
+## Module file created by spack (https://github.com/LLNL/spack) on %s
+##
+## %s
+##
+""" % (timestamp, self.spec.short_spec)
# TODO : category ?
# Short description
@@ -575,6 +570,44 @@ class TclModule(EnvModule):
header += '}\n\n'
return header
+ def process_environment_command(self, env):
+ environment_modifications_formats_colon = {
+ PrependPath: 'prepend-path {name} \"{value}\"\n',
+ AppendPath: 'append-path {name} \"{value}\"\n',
+ RemovePath: 'remove-path {name} \"{value}\"\n',
+ SetEnv: 'setenv {name} \"{value}\"\n',
+ UnsetEnv: 'unsetenv {name}\n'
+ }
+ environment_modifications_formats_general = {
+ PrependPath:
+ 'prepend-path --delim "{separator}" {name} \"{value}\"\n',
+ AppendPath:
+ 'append-path --delim "{separator}" {name} \"{value}\"\n',
+ RemovePath:
+ 'remove-path --delim "{separator}" {name} \"{value}\"\n',
+ SetEnv: 'setenv {name} \"{value}\"\n',
+ UnsetEnv: 'unsetenv {name}\n'
+ }
+ for command in env:
+ # Token expansion from configuration file
+ name = command.args.get('name', '').format(**self.upper_tokens)
+ value = str(command.args.get('value', '')).format(**self.tokens)
+ command.update_args(name=name, value=value)
+ # Format the line int the module file
+ try:
+ if command.args.get('separator', ':') == ':':
+ yield environment_modifications_formats_colon[type(
+ command)].format(**command.args)
+ else:
+ yield environment_modifications_formats_general[type(
+ command)].format(**command.args)
+ except KeyError:
+ message = ('Cannot handle command of type {command}: '
+ 'skipping request')
+ details = '{context} at {filename}:{lineno}'
+ tty.warn(message.format(command=type(command)))
+ tty.warn(details.format(**command.args))
+
def module_specific_content(self, configuration):
naming_tokens = self.tokens
# Conflict
diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py
index ff8c8e96bc..8c1204402a 100644
--- a/lib/spack/spack/package.py
+++ b/lib/spack/spack/package.py
@@ -143,8 +143,10 @@ class Package(object):
informational URL, so that users know what they're
installing.
- url
- URL of the source archive that spack will fetch.
+ url or url_for_version(self, version)
+ If url, then the URL of the source archive that spack will fetch.
+ If url_for_version(), then a method returning the URL required
+ to fetch a particular version.
install()
This function tells spack how to build and install the
diff --git a/lib/spack/spack/test/operating_system.py b/lib/spack/spack/test/operating_system.py
deleted file mode 100644
index 8723f7244d..0000000000
--- a/lib/spack/spack/test/operating_system.py
+++ /dev/null
@@ -1,75 +0,0 @@
-##############################################################################
-# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
-# Produced at the Lawrence Livermore National Laboratory.
-#
-# This file is part of Spack.
-# Created 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 Lesser General Public License (as
-# published by the Free Software Foundation) version 2.1, 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 Lesser 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
-##############################################################################
-""" Test checks if the operating_system class is created correctly and that
-the functions are using the correct operating_system. Also checks whether
-the operating_system correctly uses the compiler_strategy
-"""
-import unittest
-from spack.platforms.cray_xc import CrayXc
-from spack.platforms.linux import Linux
-from spack.platforms.darwin import Darwin
-from spack.operating_system.linux_distro import LinuxDistro
-from spack.operating_system.cnl import ComputeNodeLinux
-
-
-class TestOperatingSystem(unittest.TestCase):
-
- def setUp(self):
- cray_xc = CrayXc()
- linux = Linux()
- darwin = Darwin()
- self.cray_operating_sys = cray_xc.operating_system('front_os')
- self.cray_default_os = cray_xc.operating_system('default_os')
- self.cray_back_os = cray_xc.operating_system('back_os')
- self.darwin_operating_sys = darwin.operating_system('default_os')
- self.linux_operating_sys = linux.operating_system('default_os')
-
- def test_cray_front_end_operating_system(self):
- self.assertIsInstance(self.cray_operating_sys, LinuxDistro)
-
- def test_cray_front_end_compiler_strategy(self):
- self.assertEquals(self.cray_operating_sys.compiler_strategy, "PATH")
-
- def test_cray_back_end_operating_system(self):
- self.assertIsInstance(self.cray_back_os, ComputeNodeLinux)
-
- def test_cray_back_end_compiler_strategy(self):
- self.assertEquals(self.cray_back_os.compiler_strategy, "MODULES")
-
- def test_linux_operating_system(self):
- self.assertIsInstance(self.linux_operating_sys, LinuxDistro)
-
- def test_linux_compiler_strategy(self):
- self.assertEquals(self.linux_operating_sys.compiler_strategy, "PATH")
-
- def test_cray_front_end_compiler_list(self):
- """ Operating systems will now be in charge of finding compilers.
- So, depending on which operating system you want to build for
- or which operating system you are on, then you could detect
- compilers in a certain way. Cray linux environment on the front
- end is just a regular linux distro whereas the Cray linux compute
- node is a stripped down version which modules are important
- """
- self.assertEquals(True, False)