1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from typing import List
import llnl.util.lang
import spack.builder
import spack.installer
import spack.relocate
import spack.spec
import spack.store
def sanity_check_prefix(builder: spack.builder.Builder):
"""Check that specific directories and files are created after installation.
The files to be checked are in the ``sanity_check_is_file`` attribute of the
package object, while the directories are in the ``sanity_check_is_dir``.
Args:
builder: builder that installed the package
"""
pkg = builder.pkg
def check_paths(path_list, filetype, predicate):
if isinstance(path_list, str):
path_list = [path_list]
for path in path_list:
abs_path = os.path.join(pkg.prefix, path)
if not predicate(abs_path):
msg = "Install failed for {0}. No such {1} in prefix: {2}"
msg = msg.format(pkg.name, filetype, path)
raise spack.installer.InstallError(msg)
check_paths(pkg.sanity_check_is_file, "file", os.path.isfile)
check_paths(pkg.sanity_check_is_dir, "directory", os.path.isdir)
ignore_file = llnl.util.lang.match_predicate(spack.store.STORE.layout.hidden_file_regexes)
if all(map(ignore_file, os.listdir(pkg.prefix))):
msg = "Install failed for {0}. Nothing was installed!"
raise spack.installer.InstallError(msg.format(pkg.name))
def apply_macos_rpath_fixups(builder: spack.builder.Builder):
"""On Darwin, make installed libraries more easily relocatable.
Some build systems (handrolled, autotools, makefiles) can set their own
rpaths that are duplicated by spack's compiler wrapper. This fixup
interrogates, and postprocesses if necessary, all libraries installed
by the code.
It should be added as a @run_after to packaging systems (or individual
packages) that do not install relocatable libraries by default.
Args:
builder: builder that installed the package
"""
spack.relocate.fixup_macos_rpaths(builder.spec)
def ensure_build_dependencies_or_raise(
spec: spack.spec.Spec, dependencies: List[spack.spec.Spec], error_msg: str
):
"""Ensure that some build dependencies are present in the concrete spec.
If not, raise a RuntimeError with a helpful error message.
Args:
spec: concrete spec to be checked.
dependencies: list of abstract specs to be satisfied
error_msg: brief error message to be prepended to a longer description
Raises:
RuntimeError: when the required build dependencies are not found
"""
assert spec.concrete, "Can ensure build dependencies only on concrete specs"
build_deps = [d.name for d in spec.dependencies(deptype="build")]
missing_deps = [x for x in dependencies if x not in build_deps]
if not missing_deps:
return
# Raise an exception on missing deps.
msg = (
"{0}: missing dependencies: {1}.\n\nPlease add "
"the following lines to the package:\n\n".format(
error_msg, ", ".join(str(d) for d in missing_deps)
)
)
for dep in missing_deps:
msg += ' depends_on("{0}", type="build", when="@{1} {2}")\n'.format(
dep, spec.version, "build_system=autotools"
)
msg += '\nUpdate the version (when="@{0}") as needed.'.format(spec.version)
raise RuntimeError(msg)
def execute_build_time_tests(builder: spack.builder.Builder):
"""Execute the build-time tests prescribed by builder.
Args:
builder: builder prescribing the test callbacks. The name of the callbacks is
stored as a list of strings in the ``build_time_test_callbacks`` attribute.
"""
if not builder.pkg.run_tests or not builder.build_time_test_callbacks:
return
builder.pkg.tester.phase_tests(builder, "build", builder.build_time_test_callbacks)
def execute_install_time_tests(builder: spack.builder.Builder):
"""Execute the install-time tests prescribed by builder.
Args:
builder: builder prescribing the test callbacks. The name of the callbacks is
stored as a list of strings in the ``install_time_test_callbacks`` attribute.
"""
if not builder.pkg.run_tests or not builder.install_time_test_callbacks:
return
builder.pkg.tester.phase_tests(builder, "install", builder.install_time_test_callbacks)
class BaseBuilder(spack.builder.Builder):
"""Base class for builders to register common checks"""
# Check that self.prefix is there after installation
spack.builder.run_after("install")(sanity_check_prefix)
|