Repository: spack/spack

Issue:
Compiler environment (PATH) not loaded when `modules` is empty
### Steps to reproduce

See current develop pipeline genrate steps for aws-pcluster-x86_64_v4 stack, e.g. https://gitlab.spack.io/spack/spack/-/jobs/10937087

The error seems to be related to the [early return in compiler_environment when no modules](https://github.com/spack/spack/pull/29441). 

While [compiling a test file](https://github.com/spack/spack/blob/4a40a76291f05fdd76e12497b1891c5ad1705ebe/lib/spack/spack/compiler.py#L496) the `$PATH` is not set although the correct `compilers.yaml` file is read. This results in the wrong `binutils` being used and the compilation fails.


If I add some dummy `modules: [foo/bar]` to the `%onapi` compiler the issue disappears.

### Error message

```
==> Warning: cannot detect libc from oneapi@=2023.2.0. The compiler will not be used during concretization.
```

### Information on your system

```
bash-4.2# spack debug report
* **Spack:** 0.22.0.dev0 (7d87369ead99046f04211cd95047cabf1e2b30c1)
* **Python:** 3.7.16
* **Platform:** linux-amzn2-zen2
* **Concretizer:** clingo
```
I only had a `zen2` machine handy. The error is the same with the `x86_64_v3` target, but you need to remove the `x86_64_v4` target from the stacks `spack.yaml` to reproduce on this machine.

### 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:

Resolving patch:
diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
--- a/lib/spack/spack/compiler.py
+++ b/lib/spack/spack/compiler.py
@@ -20,6 +20,7 @@
 
 import spack.compilers
 import spack.error
+import spack.schema.environment
 import spack.spec
 import spack.util.executable
 import spack.util.libc
@@ -683,8 +684,8 @@ def __str__(self):
 
     @contextlib.contextmanager
     def compiler_environment(self):
-        # yield immediately if no modules
-        if not self.modules:
+        # Avoid modifying os.environ if possible.
+        if not self.modules and not self.environment:
             yield
             return
 
@@ -701,13 +702,9 @@ def compiler_environment(self):
                 spack.util.module_cmd.load_module(module)
 
             # apply other compiler environment changes
-            env = spack.util.environment.EnvironmentModifications()
-            env.extend(spack.schema.environment.parse(self.environment))
-            env.apply_modifications()
+            spack.schema.environment.parse(self.environment).apply_modifications()
 
             yield
-        except BaseException:
-            raise
         finally:
             # Restore environment regardless of whether inner code succeeded
             os.environ.clear()


Test patch:
diff --git a/lib/spack/spack/test/compilers/basics.py b/lib/spack/spack/test/compilers/basics.py
--- a/lib/spack/spack/test/compilers/basics.py
+++ b/lib/spack/spack/test/compilers/basics.py
@@ -943,3 +943,17 @@ def test_detection_requires_c_compiler(detected_versions, expected_length):
     """
     result = spack.compilers.make_compiler_list(detected_versions)
     assert len(result) == expected_length
+
+
+def test_compiler_environment(working_env):
+    """Test whether environment modifications from compilers are applied in compiler_environment"""
+    os.environ.pop("TEST", None)
+    compiler = Compiler(
+        "gcc@=13.2.0",
+        operating_system="ubuntu20.04",
+        target="x86_64",
+        paths=["/test/bin/gcc", "/test/bin/g++"],
+        environment={"set": {"TEST": "yes"}},
+    )
+    with compiler.compiler_environment():
+        assert os.environ["TEST"] == "yes"