Change sanity_check_[file|dir] to sanity_check_is_[file|dir], per #554

- Add documentation as well.
This commit is contained in:
Todd Gamblin 2016-03-17 18:49:58 -07:00
parent 63f9f4291a
commit 90268876f7
3 changed files with 84 additions and 25 deletions

View File

@ -2160,6 +2160,62 @@ package, this allows us to avoid race conditions in the library's
build system.
.. _sanity-checks:
Sanity checking an intallation
--------------------------------
By default, Spack assumes that a build has failed if nothing is
written to the install prefix, and that it has succeeded if anything
(a file, a directory, etc.) is written to the install prefix after
``install()`` completes.
Consider a simple autotools build like this:
.. code-block:: python
def install(self, spec, prefix):
configure("--prefix=" + prefix)
make()
make("install")
If you are using using standard autotools or CMake, ``configure`` and
``make`` will not write anything to the install prefix. Only ``make
install`` writes the files, and only once the build is already
complete. Not all builds are like this. Many builds of scientific
software modify the install prefix *before* ``make install``. Builds
like this can falsely report that they were successfully installed if
an error occurs before the install is complete but after files have
been written to the ``prefix``.
``sanity_check_is_file`` and ``sanity_check_is_dir``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can optionally specify *sanity checks* to deal with this problem.
Add properties like this to your package:
.. code-block:: python
class MyPackage(Package):
...
sanity_check_is_file = ['include/libelf.h']
sanity_check_is_dir = [lib]
def install(self, spec, prefix):
configure("--prefix=" + prefix)
make()
make("install")
Now, after ``install()`` runs, Spack will check whether
``$prefix/include/libelf.h`` exists and is a file, and whether
``$prefix/lib`` exists and is a directory. If the checks fail, then
the build will fail and the install prefix will be removed. If they
succeed, Spack considers the build succeeful and keeps the prefix in
place.
.. _file-manipulation:
File manipulation functions

View File

@ -318,16 +318,17 @@ class SomePackage(Package):
"""Most packages are NOT extendable. Set to True if you want extensions."""
extendable = False
"""List of prefix-relative file paths. If these do not exist after
install, or if they exist but are not files, sanity checks fail.
"""List of prefix-relative file paths (or a single path). If these do
not exist after install, or if they exist but are not files,
sanity checks fail.
"""
sanity_check_files = []
sanity_check_is_file = []
"""List of prefix-relative directory paths. If these do not exist
after install, or if they exist but are not directories, sanity
checks will fail.
"""List of prefix-relative directory paths (or a single path). If
these do not exist after install, or if they exist but are not
directories, sanity checks will fail.
"""
sanity_check_dirs = []
sanity_check_is_dir = []
def __init__(self, spec):
@ -966,14 +967,17 @@ def build_process():
def sanity_check_prefix(self):
"""This function checks whether install succeeded."""
def check_paths(path_list, filetype, predicate):
if isinstance(path_list, basestring):
path_list = [path_list]
for path in path_list:
abs_path = os.path.join(self.prefix, path)
if not predicate(abs_path):
raise InstallError("Install failed for %s. No such %s in prefix: %s"
% (self.name, filetype, path))
check_paths(self.sanity_check_files, 'file', os.path.isfile)
check_paths(self.sanity_check_dirs, 'directory', os.path.isdir)
check_paths(self.sanity_check_is_file, 'file', os.path.isfile)
check_paths(self.sanity_check_is_dir, 'directory', os.path.isdir)
installed = set(os.listdir(self.prefix))
installed.difference_update(spack.install_layout.hidden_file_paths)

View File

@ -38,8 +38,7 @@ class Libelf(Package):
provides('elf')
sanity_check_files = ['include/libelf.h']
sanity_check_dirs = ['lib']
sanity_check_is_file = 'include/libelf.h'
def install(self, spec, prefix):
configure("--prefix=" + prefix,