Repository: mesonbuild/meson

Issue:
Meson misjudges mips32el userland running on mips64el machine as mips64
**Describe the bug**

We have a mipsel building environment running on a mips64el machine. 

When using Meson we discovered that Meson can not detect such combination as it just uses the output of `uname -m` without further detection: it detects host architecture as `mips64` instead of expected `mips`.

PS: Patch is available, please wait for a PR.

**To Reproduce**

On mips32el userland running on a mips64el machine:
1. Create an empty directory
2. Create a `meson.build` as follows
3. Create a shadow build directory and cd into it
4. Run `meson ..`
5. Meson exits with failure as assertion is false:
```
~/meson_test/build# dpkg --print-architecture
mipsel
~/meson_test/build# meson ..
The Meson build system
Version: 1.0.1
Source dir: /root/meson_test
Build dir: /root/meson_test/build
Build type: native build
Project name: a
Project version: undefined
C compiler for the host machine: cc (gcc 12.2.0 "cc (Debian 12.2.0-14) 12.2.0")
C linker for the host machine: cc ld.bfd 2.40
Host machine cpu family: mips64
Host machine cpu: mips64

../meson.build:3:0: ERROR: Assert failed: Wrong CPU type was detected.

A full log can be found at /root/meson_test/build/meson-logs/meson-log.txt
WARNING: Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated.
```

Contents of `meson.build`:

```meson
project('test', 'c')

assert((host_machine.cpu() == 'mips'), 'Wrong CPU type was detected')
```

**Expected behavior**

With this combination Meson should detect the host CPU type and family as `mips` instead of `mips64`.

This is the result after the patch and it is expected:

```
$ meson ..
The Meson build system
Version: 1.0.1
Source dir: /root/meson_test
Build dir: /root/meson_test/build
Build type: native build
Project name: a
Project version: undefined
C compiler for the host machine: cc (gcc 12.2.0 "cc (Debian 12.2.0-14) 12.2.0")
C linker for the host machine: cc ld.bfd 2.40
Host machine cpu family: mips
Host machine cpu: mips
Build targets in project: 0

Found ninja-1.11.1 at /usr/bin/ninja
WARNING: Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated.

```

**System parameters**
*OS*: Debian 12.0 bookworm
*Meson version*: 1.0.1
*Python version*: 3.11.2
Ninja is not involved.



Discussion:

Resolving patch:
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -339,6 +339,11 @@ def detect_cpu_family(compilers: CompilersDict) -> str:
         # AIX always returns powerpc, check here for 64-bit
         if any_compiler_has_define(compilers, '__64BIT__'):
             trial = 'ppc64'
+    # MIPS64 is able to run MIPS32 code natively, so there is a chance that
+    # such mixture mentioned above exists.
+    elif trial == 'mips64':
+        if not any_compiler_has_define(compilers, '__mips64'):
+            trial = 'mips'
 
     if trial not in known_cpu_families:
         mlog.warning(f'Unknown CPU family {trial!r}, please report this at '
@@ -377,7 +382,10 @@ def detect_cpu(compilers: CompilersDict) -> str:
         if '64' not in trial:
             trial = 'mips'
         else:
-            trial = 'mips64'
+            if not any_compiler_has_define(compilers, '__mips64'):
+                trial = 'mips'
+            else:
+                trial = 'mips64'
     elif trial == 'ppc':
         # AIX always returns powerpc, check here for 64-bit
         if any_compiler_has_define(compilers, '__64BIT__'):
diff --git a/unittests/internaltests.py b/unittests/internaltests.py
--- a/unittests/internaltests.py
+++ b/unittests/internaltests.py
@@ -1579,12 +1579,12 @@ def mock_trial(value: str) -> T.Iterable[None]:
             ('ppc', 'ppc'),
             ('macppc', 'ppc'),
             ('power macintosh', 'ppc'),
-            ('mips64el', 'mips64'),
-            ('mips64', 'mips64'),
+            ('mips64el', 'mips'),
+            ('mips64', 'mips'),
             ('mips', 'mips'),
             ('mipsel', 'mips'),
-            ('ip30', 'mips64'),
-            ('ip35', 'mips64'),
+            ('ip30', 'mips'),
+            ('ip35', 'mips'),
             ('parisc64', 'parisc'),
             ('sun4u', 'sparc64'),
             ('sun4v', 'sparc64'),
@@ -1602,7 +1602,7 @@ def mock_trial(value: str) -> T.Iterable[None]:
                     self.assertEqual(actual, expected)
 
         with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)):
-            for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64')]:
+            for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]:
                 with self.subTest(test, has_define=True), mock_trial(test):
                     actual = mesonbuild.environment.detect_cpu_family({})
                     self.assertEqual(actual, expected)
@@ -1624,8 +1624,8 @@ def mock_trial(value: str) -> T.Iterable[None]:
             ('x64', 'x86_64'),
             ('i86pc', 'x86_64'),
             ('earm', 'arm'),
-            ('mips64el', 'mips64'),
-            ('mips64', 'mips64'),
+            ('mips64el', 'mips'),
+            ('mips64', 'mips'),
             ('mips', 'mips'),
             ('mipsel', 'mips'),
             ('aarch64', 'aarch64'),
@@ -1639,7 +1639,7 @@ def mock_trial(value: str) -> T.Iterable[None]:
                     self.assertEqual(actual, expected)
 
         with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)):
-            for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64')]:
+            for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]:
                 with self.subTest(test, has_define=True), mock_trial(test):
                     actual = mesonbuild.environment.detect_cpu({})
                     self.assertEqual(actual, expected)


Test patch: