Repository: mesonbuild/meson

Issue:
ninja scan-build does not take --cross-file into account
I am using Meson to cross compile from Linux to a different [(non-mainstream) OS](https://github.com/managarm/managarm). `clang` is used as a compiler. This works fine, but `ninja scan-build` does not.

Output:
```
ninja -v scan-build
[0/1] /usr/local/bin/meson --internal scanbuild /home/korona/Projects/bootstrap-managarm/src/managarm /home/korona/Projects/bootstrap-managarm/build/pkg-builds/managarm-system /usr/local/bin/meson -Dbuild_drivers=true -Dbuild_kernel=false -Dbuild_tools=false
scan-build: Using '/home/korona/Projects/bootstrap-managarm/build/tools/host-llvm-toolchain/bin/clang-8' for static analysis
The Meson build system
Version: 0.50.1
Source dir: /home/korona/Projects/bootstrap-managarm/src/managarm
Build dir: /home/korona/Projects/bootstrap-managarm/build/pkg-builds/managarm-system/meson-private/tmpwe0du8ks
Build type: native build
Project name: managarm
Project version: undefined
Native C compiler: /home/korona/Projects/bootstrap-managarm/build/tools/host-llvm-toolchain/bin/../libexec/ccc-analyzer (gcc 6.3.0 "gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Native C++ compiler: /home/korona/Projects/bootstrap-managarm/build/tools/host-llvm-toolchain/bin/../libexec/c++-analyzer (gcc 6.3.0 "g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Build machine cpu family: x86_64
Build machine cpu: x86_64
```

Expected output:
- `meson` should configure its temporary build directory using the same cross file as the directory that `ninja scan-build` is invoked from. The cross file is required to pass arguments such as `-target` and `-gcc-toolchain` to `clang`.
- `meson` should realize that it is doing a `Build type: cross build` and not a `Build type: native build`.

Output during original configuration (correct):
```
The Meson build system
Version: 0.50.1
Source dir: /home/korona/Projects/bootstrap-managarm/src/managarm
Build dir: /home/korona/Projects/bootstrap-managarm/build/pkg-builds/managarm-system
Build type: cross build
Project name: managarm
Project version: undefined
Native C compiler: cc (gcc 6.3.0 "cc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Cross C compiler: clang (clang 8.0.0)
Native C++ compiler: c++ (gcc 6.3.0 "c++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Cross C++ compiler: clang++ (clang 8.0.0)
Host machine cpu family: x86_64
Host machine cpu: x86_64
Target machine cpu family: x86_64
Target machine cpu: x86_64
Build machine cpu family: x86_64
Build machine cpu: x86_64
```
ninja scan-build does not take --cross-file into account
I am using Meson to cross compile from Linux to a different [(non-mainstream) OS](https://github.com/managarm/managarm). `clang` is used as a compiler. This works fine, but `ninja scan-build` does not.

Output:
```
ninja -v scan-build
[0/1] /usr/local/bin/meson --internal scanbuild /home/korona/Projects/bootstrap-managarm/src/managarm /home/korona/Projects/bootstrap-managarm/build/pkg-builds/managarm-system /usr/local/bin/meson -Dbuild_drivers=true -Dbuild_kernel=false -Dbuild_tools=false
scan-build: Using '/home/korona/Projects/bootstrap-managarm/build/tools/host-llvm-toolchain/bin/clang-8' for static analysis
The Meson build system
Version: 0.50.1
Source dir: /home/korona/Projects/bootstrap-managarm/src/managarm
Build dir: /home/korona/Projects/bootstrap-managarm/build/pkg-builds/managarm-system/meson-private/tmpwe0du8ks
Build type: native build
Project name: managarm
Project version: undefined
Native C compiler: /home/korona/Projects/bootstrap-managarm/build/tools/host-llvm-toolchain/bin/../libexec/ccc-analyzer (gcc 6.3.0 "gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Native C++ compiler: /home/korona/Projects/bootstrap-managarm/build/tools/host-llvm-toolchain/bin/../libexec/c++-analyzer (gcc 6.3.0 "g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Build machine cpu family: x86_64
Build machine cpu: x86_64
```

Expected output:
- `meson` should configure its temporary build directory using the same cross file as the directory that `ninja scan-build` is invoked from. The cross file is required to pass arguments such as `-target` and `-gcc-toolchain` to `clang`.
- `meson` should realize that it is doing a `Build type: cross build` and not a `Build type: native build`.

Output during original configuration (correct):
```
The Meson build system
Version: 0.50.1
Source dir: /home/korona/Projects/bootstrap-managarm/src/managarm
Build dir: /home/korona/Projects/bootstrap-managarm/build/pkg-builds/managarm-system
Build type: cross build
Project name: managarm
Project version: undefined
Native C compiler: cc (gcc 6.3.0 "cc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Cross C compiler: clang (clang 8.0.0)
Native C++ compiler: c++ (gcc 6.3.0 "c++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516")
Cross C++ compiler: clang++ (clang 8.0.0)
Host machine cpu family: x86_64
Host machine cpu: x86_64
Target machine cpu family: x86_64
Target machine cpu: x86_64
Build machine cpu family: x86_64
Build machine cpu: x86_64
```


Discussion:
I'm also running into this issue. I reference the sys_root cross file property during the build, so when running ninja scan-build I get the following error.

```
meson.build:155:4: ERROR: Unknown cross property: sys_root.
```

@jpakkane any updates on this bug and/or suggestions on how to fix this? Is there a preferred method of transporting configuration options from the build directory to the temporary scan-build directory?

As far as I can see, the build directory is indeed passed to this function: https://github.com/mesonbuild/meson/blob/master/mesonbuild/scripts/scanbuild.py#L22 but not used at all.
Im running into this too, any updates?
I'm also running into this issue. I reference the sys_root cross file property during the build, so when running ninja scan-build I get the following error.

```
meson.build:155:4: ERROR: Unknown cross property: sys_root.
```

@jpakkane any updates on this bug and/or suggestions on how to fix this? Is there a preferred method of transporting configuration options from the build directory to the temporary scan-build directory?

As far as I can see, the build directory is indeed passed to this function: https://github.com/mesonbuild/meson/blob/master/mesonbuild/scripts/scanbuild.py#L22 but not used at all.
Im running into this too, any updates?

Resolving patch:
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -970,9 +970,9 @@ def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
 
     properties = OrderedDict()
     if options.cross_file:
-        properties['cross_file'] = options.cross_file
+        properties['cross_file'] = [os.path.abspath(f) for f in options.cross_file]
     if options.native_file:
-        properties['native_file'] = options.native_file
+        properties['native_file'] = [os.path.abspath(f) for f in options.native_file]
 
     config['options'] = cmd_line_options_to_string(options)
     config['properties'] = properties
diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py
--- a/mesonbuild/scripts/scanbuild.py
+++ b/mesonbuild/scripts/scanbuild.py
@@ -16,9 +16,11 @@
 import shutil
 import tempfile
 from ..environment import detect_ninja, detect_scanbuild
+from ..coredata import get_cmd_line_file, CmdLineFileParser
 from pathlib import Path
 import typing as T
-
+from ast import literal_eval
+import os
 
 def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, logdir: Path, args: T.List[str]) -> int:
     with tempfile.TemporaryDirectory(dir=str(privdir)) as scandir:
@@ -32,15 +34,27 @@ def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, l
 
 def run(args: T.List[str]) -> int:
     srcdir = Path(args[0])
-    blddir = Path(args[1])
+    bldpath = Path(args[1])
+    blddir = args[1]
     meson_cmd = args[2:]
-    privdir = blddir / 'meson-private'
-    logdir = blddir / 'meson-logs' / 'scanbuild'
+    privdir = bldpath / 'meson-private'
+    logdir = bldpath / 'meson-logs' / 'scanbuild'
     shutil.rmtree(str(logdir), ignore_errors=True)
 
+    # if any cross or native files are specified we should use them
+    cmd = get_cmd_line_file(blddir)
+    data = CmdLineFileParser()
+    data.read(cmd)
+
+    if 'cross_file' in data['properties']:
+        meson_cmd.extend([f'--cross-file={os.path.abspath(f)}' for f in literal_eval(data['properties']['cross_file'])])
+
+    if 'native_file' in data['properties']:
+        meson_cmd.extend([f'--native-file={os.path.abspath(f)}' for f in literal_eval(data['properties']['native_file'])])
+
     exelist = detect_scanbuild()
     if not exelist:
         print('Could not execute scan-build "%s"' % ' '.join(exelist))
         return 1
 
-    return scanbuild(exelist, srcdir, blddir, privdir, logdir, meson_cmd)
+    return scanbuild(exelist, srcdir, bldpath, privdir, logdir, meson_cmd)


Test patch: