Repository: mesonbuild/meson

Issue:
Unknown CPU family 'aarch64_be'
Trying to build qemu-6.0.0, I got this message:
```
WARNING: Unknown CPU family 'aarch64_be', please report this at https://github.com/mesonbuild/meson/issues/new with the output of `uname -a` and `cat /proc/cpuinfo`
```
Well, ok.
```
temari ~ # uname -a
Linux temari 5.10.52-gentoo-big #1 SMP PREEMPT Sun Aug 29 17:27:11 CEST 2021 aarch64_be GNU/Linux
temari ~ # cat /proc/cpuinfo 
processor       : 0
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 1
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 2
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 3
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 4
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 5
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 6
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 7
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

temari ~ # 
```


Discussion:

Resolving patch:
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -314,6 +314,9 @@ def detect_cpu_family(compilers: CompilersDict) -> str:
         trial = 'x86'
     elif trial == 'arm64':
         trial = 'aarch64'
+    elif trial.startswith('aarch64'):
+        # This can be `aarch64_be`
+        trial = 'aarch64'
     elif trial.startswith('arm') or trial.startswith('earm'):
         trial = 'arm'
     elif trial.startswith(('powerpc64', 'ppc64')):
@@ -359,7 +362,7 @@ def detect_cpu_family(compilers: CompilersDict) -> str:
 
     return trial
 
-def detect_cpu(compilers: CompilersDict):
+def detect_cpu(compilers: CompilersDict) -> str:
     if mesonlib.is_windows():
         trial = detect_windows_arch(compilers)
     elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_aix():
@@ -373,10 +376,13 @@ def detect_cpu(compilers: CompilersDict):
         # Same check as above for cpu_family
         if any_compiler_has_define(compilers, '__i386__'):
             trial = 'i686' # All 64 bit cpus have at least this level of x86 support.
-    elif trial == 'aarch64':
+    elif trial.startswith('aarch64'):
         # Same check as above for cpu_family
         if any_compiler_has_define(compilers, '__arm__'):
             trial = 'arm'
+        else:
+            # for aarch64_be
+            trial = 'aarch64'
     elif trial.startswith('earm'):
         trial = 'arm'
     elif trial == 'e2k':
@@ -387,20 +393,22 @@ def detect_cpu(compilers: CompilersDict):
             trial = 'mips'
         else:
             trial = 'mips64'
+    elif trial == 'ppc':
+        # AIX always returns powerpc, check here for 64-bit
+        if any_compiler_has_define(compilers, '__64BIT__'):
+            trial = 'ppc64'
 
     # Add more quirks here as bugs are reported. Keep in sync with
     # detect_cpu_family() above.
     return trial
 
-def detect_system():
+def detect_system() -> str:
     if sys.platform == 'cygwin':
         return 'cygwin'
     return platform.system().lower()
 
-def detect_msys2_arch():
-    if 'MSYSTEM_CARCH' in os.environ:
-        return os.environ['MSYSTEM_CARCH']
-    return None
+def detect_msys2_arch() -> T.Optional[str]:
+    return os.environ.get('MSYSTEM_CARCH', None)
 
 def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo:
     """Detect the machine we're running on
diff --git a/unittests/internaltests.py b/unittests/internaltests.py
--- a/unittests/internaltests.py
+++ b/unittests/internaltests.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import contextlib
 import stat
 import subprocess
 import json
@@ -1422,3 +1423,97 @@ def test_typed_kwarg_evolve(self) -> None:
         self.assertEqual(k.required, v.required)
         self.assertEqual(k.default, 'foo')
         self.assertEqual(v.default, 'bar')
+
+    def test_detect_cpu_family(self) -> None:
+        """Test the various cpu familes that we detect and normalize.
+
+        This is particularly useful as both documentation, and to keep testing
+        platforms that are less common.
+        """
+
+        @contextlib.contextmanager
+        def mock_trial(value: str) -> T.Iterable[None]:
+            """Mock all of the ways we could get the trial at once."""
+            mocked = mock.Mock(return_value=value)
+
+            with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \
+                    mock.patch('mesonbuild.environment.platform.processor', mocked), \
+                    mock.patch('mesonbuild.environment.platform.machine', mocked):
+                yield
+
+        cases = [
+            ('x86', 'x86'),
+            ('i386', 'x86'),
+            ('bepc', 'x86'),  # Haiku
+            ('earm', 'arm'),  # NetBSD
+            ('arm', 'arm'),
+            ('ppc64', 'ppc64'),
+            ('powerpc64', 'ppc64'),
+            ('powerpc', 'ppc'),
+            ('ppc', 'ppc'),
+            ('macppc', 'ppc'),
+            ('power macintosh', 'ppc'),
+            ('mips64el', 'mips64'),
+            ('mips64', 'mips64'),
+            ('mips', 'mips'),
+            ('mipsel', 'mips'),
+            ('ip30', 'mips64'),
+            ('ip35', 'mips64'),
+            ('parisc64', 'parisc'),
+            ('sun4u', 'sparc64'),
+            ('sun4v', 'sparc64'),
+            ('amd64', 'x86_64'),
+            ('x64', 'x86_64'),
+            ('i86pc', 'x86_64'),  # Solaris
+            ('aarch64', 'aarch64'),
+            ('aarch64_be', 'aarch64'),
+        ]
+
+        with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)):
+            for test, expected in cases:
+                with self.subTest(test, has_define=False), mock_trial(test):
+                    actual = mesonbuild.environment.detect_cpu_family({})
+                    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')]:
+                with self.subTest(test, has_define=True), mock_trial(test):
+                    actual = mesonbuild.environment.detect_cpu_family({})
+                    self.assertEqual(actual, expected)
+
+    def test_detect_cpu(self) -> None:
+
+        @contextlib.contextmanager
+        def mock_trial(value: str) -> T.Iterable[None]:
+            """Mock all of the ways we could get the trial at once."""
+            mocked = mock.Mock(return_value=value)
+
+            with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \
+                    mock.patch('mesonbuild.environment.platform.processor', mocked), \
+                    mock.patch('mesonbuild.environment.platform.machine', mocked):
+                yield
+
+        cases = [
+            ('amd64', 'x86_64'),
+            ('x64', 'x86_64'),
+            ('i86pc', 'x86_64'),
+            ('earm', 'arm'),
+            ('mips64el', 'mips64'),
+            ('mips64', 'mips64'),
+            ('mips', 'mips'),
+            ('mipsel', 'mips'),
+            ('aarch64', 'aarch64'),
+            ('aarch64_be', 'aarch64'),
+        ]
+
+        with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)):
+            for test, expected in cases:
+                with self.subTest(test, has_define=False), mock_trial(test):
+                    actual = mesonbuild.environment.detect_cpu({})
+                    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')]:
+                with self.subTest(test, has_define=True), mock_trial(test):
+                    actual = mesonbuild.environment.detect_cpu({})
+                    self.assertEqual(actual, expected)


Test patch: