diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2023-01-13 10:27:07 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-13 10:27:07 -0800 |
commit | 88a604e7f4bfc1ba79eacd430e97d7c6846cf3c2 (patch) | |
tree | 74a671e185128224ff0ae798e766fc015593f65b /lib | |
parent | 33859d3d5f3500597f5008b5ab41f8553ff37a01 (diff) | |
download | spack-88a604e7f4bfc1ba79eacd430e97d7c6846cf3c2.tar.gz spack-88a604e7f4bfc1ba79eacd430e97d7c6846cf3c2.tar.bz2 spack-88a604e7f4bfc1ba79eacd430e97d7c6846cf3c2.tar.xz spack-88a604e7f4bfc1ba79eacd430e97d7c6846cf3c2.zip |
config: make path replacements lazy (#34758)
Currently, all of the replacements in `spack.util.path.replacements()` get evaluated for
each replacement. This makes it easy to get bootstrap issues, because config is used
very early on in Spack.
Right now, if I run `test_autotools_gnuconfig_replacement_no_gnuconfig` on my M1 mac, I
get the circular reference error below. This fixes the issue by making all of the path
replacements lazy lambdas.
As a bonus, this cleans up the way we do substitution for `$env` -- it's consistent with
other substitutions now.
- [x] make all path `replacements()` lazy
- [x] clean up handling of `$env`
```console
> spack unit-test -k test_autotools_gnuconfig_replacement_no_gnuconfig
...
==> [2022-12-31-15:44:21.771459] Error: AttributeError:
The 'autotools-config-replacement' package cannot find an attribute while trying to build from sources. This might be due to a change in Spack's package format to support multiple build-systems for a single package. You can fix this by updating the build recipe, and you can also report the issue as a bug. More information at https://spack.readthedocs.io/en/latest/packaging_guide.html#installation-procedure
/Users/gamblin2/src/spack/lib/spack/spack/package_base.py:1332, in prefix:
1330 @property
1331 def prefix(self):
>> 1332 """Get the prefix into which this package should be installed."""
1333 return self.spec.prefix
Traceback (most recent call last):
File "/Users/gamblin2/src/spack/lib/spack/spack/build_environment.py", line 1030, in _setup_pkg_and_run
kwargs["env_modifications"] = setup_package(
^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/build_environment.py", line 757, in setup_package
set_module_variables_for_package(pkg)
File "/Users/gamblin2/src/spack/lib/spack/spack/build_environment.py", line 596, in set_module_variables_for_package
m.std_cmake_args = spack.build_systems.cmake.CMakeBuilder.std_args(pkg)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/build_systems/cmake.py", line 241, in std_args
define("CMAKE_INSTALL_PREFIX", pkg.prefix),
^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/package_base.py", line 1333, in prefix
return self.spec.prefix
^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/spec.py", line 1710, in prefix
self.prefix = spack.store.layout.path_for_spec(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/directory_layout.py", line 336, in path_for_spec
path = self.relative_path_for_spec(spec)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/directory_layout.py", line 106, in relative_path_for_spec
projection = spack.projections.get_projection(self.projections, spec)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/projections.py", line 13, in get_projection
if spec.satisfies(spec_like, strict=True):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/spec.py", line 3642, in satisfies
if not self.virtual and other.virtual:
^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/spec.py", line 1622, in virtual
return spack.repo.path.is_virtual(self.name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/repo.py", line 890, in is_virtual
return have_name and pkg_name in self.provider_index
^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/repo.py", line 770, in provider_index
self._provider_index.merge(repo.provider_index)
^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/repo.py", line 1096, in provider_index
return self.index["providers"]
~~~~~~~~~~^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/repo.py", line 592, in __getitem__
self._build_all_indexes()
File "/Users/gamblin2/src/spack/lib/spack/spack/repo.py", line 607, in _build_all_indexes
self.indexes[name] = self._build_index(name, indexer)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/spack/repo.py", line 616, in _build_index
index_mtime = self.cache.mtime(cache_filename)
^^^^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/llnl/util/lang.py", line 826, in __getattr__
return getattr(self.instance, name)
^^^^^^^^^^^^^
File "/Users/gamblin2/src/spack/lib/spack/llnl/util/lang.py", line 825, in __getattr__
raise AttributeError()
AttributeError
```
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/util/path.py | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/lib/spack/spack/util/path.py b/lib/spack/spack/util/path.py index 9434fc5af4..d07bae3be5 100644 --- a/lib/spack/spack/util/path.py +++ b/lib/spack/spack/util/path.py @@ -51,26 +51,32 @@ def get_user(): return getpass.getuser() +# return value for replacements with no match +NOMATCH = object() + + # Substitutions to perform def replacements(): - # break circular import from spack.util.executable + # break circular imports + import spack.environment as ev import spack.paths arch = architecture() return { - "spack": spack.paths.prefix, - "user": get_user(), - "tempdir": tempfile.gettempdir(), - "user_cache_path": spack.paths.user_cache_path, - "architecture": str(arch), - "arch": str(arch), - "platform": str(arch.platform), - "operating_system": str(arch.os), - "os": str(arch.os), - "target": str(arch.target), - "target_family": str(arch.target.microarchitecture.family), - "date": date.today().strftime("%Y-%m-%d"), + "spack": lambda: spack.paths.prefix, + "user": lambda: get_user(), + "tempdir": lambda: tempfile.gettempdir(), + "user_cache_path": lambda: spack.paths.user_cache_path, + "architecture": lambda: arch, + "arch": lambda: arch, + "platform": lambda: arch.platform, + "operating_system": lambda: arch.os, + "os": lambda: arch.os, + "target": lambda: arch.target, + "target_family": lambda: arch.target.microarchitecture.family, + "date": lambda: date.today().strftime("%Y-%m-%d"), + "env": lambda: ev.active_environment().path if ev.active_environment() else NOMATCH, } @@ -293,20 +299,14 @@ def substitute_config_variables(path): replaced if there is an active environment, and should only be used in environment yaml files. """ - import spack.environment as ev # break circular - _replacements = replacements() - env = ev.active_environment() - if env: - _replacements.update({"env": env.path}) - else: - # If a previous invocation added env, remove it - _replacements.pop("env", None) # Look up replacements def repl(match): - m = match.group(0).strip("${}") - return _replacements.get(m.lower(), match.group(0)) + m = match.group(0) + key = m.strip("${}").lower() + repl = _replacements.get(key, lambda: m)() + return m if repl is NOMATCH else str(repl) # Replace $var or ${var}. return re.sub(r"(\$\w+\b|\$\{\w+\})", repl, path) |