diff --git a/crossenv/__init__.py b/crossenv/__init__.py index b1119f1..cad190e 100644 --- a/crossenv/__init__.py +++ b/crossenv/__init__.py @@ -463,19 +463,17 @@ def run_compiler(arg): expected, ) - def _split_apple_os_version(self, value): - # Split the Apple OS version from the OS name prefix. - if value.startswith("ios"): - offset = 3 - elif value.startswith("tvos"): - offset = 4 - elif value.startswith("watchos"): - offset = 7 - else: - raise ValueError("Unknown Apple compiler triple.") + @staticmethod + def _split_apple_os_version(value): + # Split the Apple OS version from the OS name prefix (e.g. ios13.0 -> + # ios, 13.0). No Apple OS name contains a digit, so the version starts + # at the first one. On macOS the version is the Darwin kernel version + # (e.g. darwin23.4.0), not the macOS version. + offset = next((i for i, c in enumerate(value) if c.isdigit()), len(value)) return value[:offset], value[offset:] - def _clean_triple(self, triple): + @classmethod + def _clean_triple(cls, triple): # Triples are in the form cpu-vendor-kernel-system or cpu-kernel-system. So we'll # get something like: x86_64-linux-gnu or x86_64-pc-linux-gnu. We won't # overcomplicate this, since it's just to generate a warning. @@ -490,7 +488,7 @@ def _clean_triple(self, triple): parts[0] = "aarch64" # Remove any version identifier from the OS (e.g., ios13.0 -> ios) - parts[2], _ = self._split_apple_os_version(parts[2]) + parts[2], _ = cls._split_apple_os_version(parts[2]) if len(parts) == 4 and parts[1] != "apple": # 4-part "triples" are expected for Apple simulators; diff --git a/tests/test_triples.py b/tests/test_triples.py new file mode 100644 index 0000000..c94da9f --- /dev/null +++ b/tests/test_triples.py @@ -0,0 +1,52 @@ +################################################# +# Compiler triple parsing (no crossenv required) +################################################# + +from crossenv import CrossEnvBuilder + + +def test_split_apple_os_version(): + expected = { + "ios13.0": ("ios", "13.0"), + "ios": ("ios", ""), + "tvos17.0": ("tvos", "17.0"), + "tvos": ("tvos", ""), + "watchos10.0": ("watchos", "10.0"), + "watchos": ("watchos", ""), + "darwin23.4.0": ("darwin", "23.4.0"), + "darwin": ("darwin", ""), + # Previously rejected as unknown + "macos14.0": ("macos", "14.0"), + "macosx14.0": ("macosx", "14.0"), + "xros1.0": ("xros", "1.0"), + } + actual = { + value: CrossEnvBuilder._split_apple_os_version(value) for value in expected + } + assert actual == expected + + +def test_clean_triple(): + expected = { + # Apple: arm64 -> aarch64, OS version removed. The clang -dumpmachine + # and HOST_GNU_TYPE forms must clean to the same value. + "arm64-apple-ios13.0": ["aarch64", "apple", "ios"], + "aarch64-apple-ios": ["aarch64", "apple", "ios"], + "arm64-apple-tvos17.0": ["aarch64", "apple", "tvos"], + "arm64-apple-watchos10.0": ["aarch64", "apple", "watchos"], + "arm64-apple-darwin23.4.0": ["aarch64", "apple", "darwin"], + "aarch64-apple-darwin": ["aarch64", "apple", "darwin"], + "x86_64-apple-darwin23.4.0": ["x86_64", "apple", "darwin"], + # Apple simulator: 4 parts, not compared + "arm64-apple-ios13.0-simulator": None, + # Non-Apple: vendor dropped from 4-part triples + "x86_64-linux-gnu": ["x86_64", "linux", "gnu"], + "x86_64-pc-linux-gnu": ["x86_64", "linux", "gnu"], + "aarch64-unknown-linux-gnu": ["aarch64", "linux", "gnu"], + # Other forms + "x86_64": None, + "aarch64-linux": None, + "a-b-c-d-e": None, + } + actual = {triple: CrossEnvBuilder._clean_triple(triple) for triple in expected} + assert actual == expected