Repository: spack/spack

Issue:
Inherited packages break module-scoped variables
### Steps to reproduce

Under an unknown set of conditions, running `spack install llvm+python` will generate this error.

### Error message

```
==> [2022-08-22-17:03:28.606870] llvm: Executing phase: 'cmake'
==> [2022-08-22-17:04:48.618765] llvm: Executing phase: 'build'
==> [2022-08-22-17:33:24.980516] llvm: Executing phase: 'install'
==> [2022-08-22-17:34:22.572029] Error: NameError: name 'python_platlib' is not defined

/usr/WS2/sly1/tce/spack/var/spack/repos/builtin/packages/llvm/package.py:760, in post_install:
        757                ninja()
        758                ninja("install")
        759        if "+python" in self.spec:
  >>    760            install_tree("llvm/bindings/python", python_platlib)
        761
        762            if "+clang" in self.spec:
        763                install_tree("clang/bindings/python", python_platlib)

See build log for details:
  /var/tmp/sly1/spack-stage-alastor/spack-stage-llvm-12.0.1-gxtmcgu3kn34e3d2n53wzbduw4i3ukg3/spack-build-out.txt

Traceback (most recent call last):
  File "/my/path/spack/lib/spack/spack/build_environment.py", line 1062, in _setup_pkg_and_run
    return_value = function(pkg, kwargs)
  File "/my/path/spack/lib/spack/spack/installer.py", line 2013, in build_process
    return installer.run()
  File "/my/path/spack/lib/spack/spack/installer.py", line 1875, in run
    self._real_install()
  File "/my/path/spack/lib/spack/spack/installer.py", line 1974, in _real_install
    phase(pkg.spec, pkg.prefix)
  File "/my/path/spack/lib/spack/spack/package_base.py", line 150, in phase_wrapper
    callback(instance)
  File "/my/path/spack/var/spack/repos/builtin/packages/llvm/package.py", line 761, in post_install
NameError: name 'python_platlib' is not defined
==> [2022-08-22-17:34:22.572342] Flagging llvm-12.0.1-gxtmcgu3kn34e3d2n53wzbduw4i3ukg3 as failed: NameError: name 'python_platlib' is not defined
```

### Information on your system

```
* **Spack:** 0.19.0.dev0 (c64b2a00395394cc767538eede9cdd3359b2705e)
* **Python:** 3.9.12
* **Platform:** linux-rhel8-ivybridge
* **Concretizer:** clingo
```

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output


Discussion:
The set of conditions that triggers this is installing `myrepo.llvm`, when `myrepo.llvm` inherits from `builtin.llvm`.

Resolving patch:
diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py
--- a/lib/spack/spack/build_environment.py
+++ b/lib/spack/spack/build_environment.py
@@ -64,6 +64,7 @@
 import spack.subprocess_context
 import spack.user_environment
 import spack.util.path
+import spack.util.pattern
 from spack.error import NoHeadersError, NoLibrariesError
 from spack.installer import InstallError
 from spack.util.cpus import cpus_available
@@ -993,8 +994,24 @@ def add_modifications_for_dep(dep):
             dpkg = dep.package
             if set_package_py_globals:
                 set_module_variables_for_package(dpkg)
+
             # Allow dependencies to modify the module
-            dpkg.setup_dependent_package(spec.package.module, spec)
+            # Get list of modules that may need updating
+            modules = []
+            for cls in inspect.getmro(type(spec.package)):
+                module = cls.module
+                if module == spack.package_base:
+                    break
+                modules.append(module)
+
+            # Execute changes as if on a single module
+            # copy dict to ensure prior changes are available
+            changes = spack.util.pattern.Bunch()
+            dpkg.setup_dependent_package(changes, spec)
+
+            for module in modules:
+                module.__dict__.update(changes.__dict__)
+
             if context == "build":
                 dpkg.setup_dependent_build_environment(env, spec)
             else:
diff --git a/var/spack/repos/builtin.mock/packages/cmake-client-inheritor/package.py b/var/spack/repos/builtin.mock/packages/cmake-client-inheritor/package.py
new file mode 100644
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/cmake-client-inheritor/package.py
@@ -0,0 +1,11 @@
+# Copyright 2013-2022 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)
+
+from spack.package import *  # noqa: F401
+from spack.pkg.builtin.mock.cmake_client import CmakeClient
+
+
+class CmakeClientInheritor(CmakeClient):
+    """A dumy package that inherits from one using cmake."""


Test patch:
diff --git a/lib/spack/spack/test/build_environment.py b/lib/spack/spack/test/build_environment.py
--- a/lib/spack/spack/test/build_environment.py
+++ b/lib/spack/spack/test/build_environment.py
@@ -177,6 +177,14 @@ def _set_wrong_cc(x):
     assert os.environ["ANOTHER_VAR"] == "THIS_IS_SET"
 
 
+def test_setup_dependent_package_inherited_modules(
+    config, working_env, mock_packages, install_mockery, mock_fetch
+):
+    # This will raise on regression
+    s = spack.spec.Spec("cmake-client-inheritor").concretized()
+    s.package.do_install()
+
+
 @pytest.mark.parametrize(
     "initial,modifications,expected",
     [