Repository: spack/spack

Issue:
`spack location -b` returns wrong build directory for CMake packages
### Steps to reproduce

The output of `spack location -b` for a CMake packages is incorrect.
Indeed, it returns the source directory, instead of the build one.

```console
➜  spack git:(develop) ✗ spack location -b pika
.../spack-stage/spack-stage-pika-0.8.0-eyk2xyxmuznxprdr3aipa2masqxvrqh6/spack-src
```

I started investigating the problem by bisecting with the aim to find when the behaviour has changed, and it can be seen, the following commit is the last one that still works correctly, i.e. it reports the correct build directory for the package.

```console
➜  spack git:(develop) ✗ git checkout 30c9ff50dd048573e3cd7a63a8ab9c05c0bee339^
...
HEAD is now at 83ee500108 py-torchmetrics: add v0.10.1 (#33535)
➜  spack git:(83ee500108) ✗ spack location -b pika
.../spack-stage/spack-stage-pika-0.8.0-eyk2xyxmuznxprdr3aipa2masqxvrqh6/spack-build-eyk2xyx
```

I'm going to add more details about my findings in the first comment in order to not clutter this bug report.

### Error message

It outputs the fallback source directory
```
.../spack-stage/spack-stage-pika-0.8.0-eyk2xyxmuznxprdr3aipa2masqxvrqh6/spack-src
```

instead of the (expected) build directory
```
.../spack-stage/spack-stage-pika-0.8.0-eyk2xyxmuznxprdr3aipa2masqxvrqh6/spack-build-eyk2xyx
```

### Information on your system

* **Spack:** 0.19.0.dev0 (078767946c1290b225a7b8e0d64241944dbfa1db)
* **Python:** 3.8.9
* **Platform:** darwin-bigsur-skylake
* **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:
Investigating this issue, I realised that the problem has been introduced by #30738.

Testing the commit before that one, it works as expected, as reported above

```console
# note: see the ^ at the end of the hash, indicating that it is switching to its parent
➜  spack git:(develop) ✗ git checkout 30c9ff50dd048573e3cd7a63a8ab9c05c0bee339^
...
HEAD is now at 83ee500108 py-torchmetrics: add v0.10.1 (#33535)
➜  spack git:(83ee500108) ✗ spack location -b pika
.../spack-stage/spack-stage-pika-0.8.0-eyk2xyxmuznxprdr3aipa2masqxvrqh6/spack-build-eyk2xyx
```

Looking at how `spack location -b` works, the relevant part is

https://github.com/spack/spack/blob/078767946c1290b225a7b8e0d64241944dbfa1db/lib/spack/spack/cmd/location.py#L142-L152

and in particular at line 144 where it checks for the attribute `build_directory`, otherwise it fallbacks to the source directory (as it actually happens currently).

I quickly looked at the PR, specifically for the CMake part, and it (mainly) splits the CMake build system in `CMakePackage` and `CMakeBuilder`. Unfortunately, the `build_directory` attribute has been moved to `CMakeBuilder`, 

https://github.com/spack/spack/blob/078767946c1290b225a7b8e0d64241944dbfa1db/lib/spack/spack/build_systems/cmake.py#L377-L380

which seems to be used internally by `CMakePackage` but it doesn't get exposed (I see it is mentioned as "legacy attribute", but I didn't follow this track yet).

https://github.com/spack/spack/blob/078767946c1290b225a7b8e0d64241944dbfa1db/lib/spack/spack/build_systems/cmake.py#L163-L174

This results in a missing attribute and so in falling back to source directory for `location -b`.

I didn't check if any other build system is affected.

@alalazo let me know if I can be of any help with this 😉

Resolving patch:
diff --git a/lib/spack/spack/cmd/location.py b/lib/spack/spack/cmd/location.py
--- a/lib/spack/spack/cmd/location.py
+++ b/lib/spack/spack/cmd/location.py
@@ -9,6 +9,7 @@
 
 import llnl.util.tty as tty
 
+import spack.builder
 import spack.cmd
 import spack.cmd.common.arguments as arguments
 import spack.environment as ev
@@ -134,6 +135,7 @@ def location(parser, args):
     # Either concretize or filter from already concretized environment
     spec = spack.cmd.matching_spec_from_env(spec)
     pkg = spec.package
+    builder = spack.builder.create(pkg)
 
     if args.stage_dir:
         print(pkg.stage.path)
@@ -141,10 +143,10 @@ def location(parser, args):
 
     if args.build_dir:
         # Out of source builds have build_directory defined
-        if hasattr(pkg, "build_directory"):
+        if hasattr(builder, "build_directory"):
             # build_directory can be either absolute or relative to the stage path
             # in either case os.path.join makes it absolute
-            print(os.path.normpath(os.path.join(pkg.stage.path, pkg.build_directory)))
+            print(os.path.normpath(os.path.join(pkg.stage.path, builder.build_directory)))
             return
 
         # Otherwise assume in-source builds


Test patch: