prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Should arm64 runners build both universal2 and arm64 wheels by default?
  Continuing the discussion from https://github.com/pypa/cibuildwheel/pull/1191#discussion_r928749039
  
  The current situation is that arm64 runners builds universal2 and arm64 by default. This discussion is whether we change that to just arm64.
  
  > @joerick: The question of whether to default building both universal2 and arm64 on the arm runner is still open, in my mind. I'm still mostly of the opinion that building both is good, because universal2 packages are preferred in some contexts (e.g. distributable GUI apps), and that most packages are small and the extra build time isn't much of a hit. Of course, people building big libraries would be wise to change this to just build arm64.
  
  > @henryiii: Personally, I think the default should be native only. Eventually no one will care about Intel / universal and will only produce native binaries again. Also, there are still workarounds related to cross compiling for universal (like requiring all dependencies to also be universal). And we don’t support it yet, but there are two ways to make a universal binary, the default way and merging two native binaries. And finally universal vs. native is a choice, and I’d you pick universal, you don’t need native. You can always add tags for the native arch’s to a universal binary. And pip won’t even ever download universal if both native wheels exist.
  > 
  > So I’d recommend native being default, and only producing native binaries with it.
  
  Let's get a decision on this before we release CirrusCI support, which would be our first officially supported arm64 CI.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `cibuildwheel/architecture.py`
  Content:
  ```
  1 from __future__ import annotations
  2 
  3 import functools
  4 import platform as platform_module
  5 import re
  6 from enum import Enum
  7 
  8 from .typing import Final, Literal, PlatformName, assert_never
  9 
  10 PRETTY_NAMES: Final = {"linux": "Linux", "macos": "macOS", "windows": "Windows"}
  11 
  12 
  13 @functools.total_ordering
  14 class Architecture(Enum):
  15     value: str
  16 
  17     # mac/linux archs
  18     x86_64 = "x86_64"
  19 
  20     # linux archs
  21     i686 = "i686"
  22     aarch64 = "aarch64"
  23     ppc64le = "ppc64le"
  24     s390x = "s390x"
  25 
  26     # mac archs
  27     universal2 = "universal2"
  28     arm64 = "arm64"
  29 
  30     # windows archs
  31     x86 = "x86"
  32     AMD64 = "AMD64"
  33     ARM64 = "ARM64"
  34 
  35     # Allow this to be sorted
  36     def __lt__(self, other: Architecture) -> bool:
  37         return self.value < other.value
  38 
  39     @staticmethod
  40     def parse_config(config: str, platform: PlatformName) -> set[Architecture]:
  41         result = set()
  42         for arch_str in re.split(r"[\s,]+", config):
  43             if arch_str == "auto":
  44                 result |= Architecture.auto_archs(platform=platform)
  45             elif arch_str == "native":
  46                 result.add(Architecture(platform_module.machine()))
  47             elif arch_str == "all":
  48                 result |= Architecture.all_archs(platform=platform)
  49             elif arch_str == "auto64":
  50                 result |= Architecture.bitness_archs(platform=platform, bitness="64")
  51             elif arch_str == "auto32":
  52                 result |= Architecture.bitness_archs(platform=platform, bitness="32")
  53             else:
  54                 result.add(Architecture(arch_str))
  55         return result
  56 
  57     @staticmethod
  58     def auto_archs(platform: PlatformName) -> set[Architecture]:
  59         native_architecture = Architecture(platform_module.machine())
  60         result = {native_architecture}
  61 
  62         if platform == "linux" and native_architecture == Architecture.x86_64:
  63             # x86_64 machines can run i686 containers
  64             result.add(Architecture.i686)
  65 
  66         if platform == "windows" and native_architecture == Architecture.AMD64:
  67             result.add(Architecture.x86)
  68 
  69         if platform == "macos" and native_architecture == Architecture.arm64:
  70             # arm64 can build and test both archs of a universal2 wheel.
  71             result.add(Architecture.universal2)
  72 
  73         return result
  74 
  75     @staticmethod
  76     def all_archs(platform: PlatformName) -> set[Architecture]:
  77         all_archs_map = {
  78             "linux": {
  79                 Architecture.x86_64,
  80                 Architecture.i686,
  81                 Architecture.aarch64,
  82                 Architecture.ppc64le,
  83                 Architecture.s390x,
  84             },
  85             "macos": {Architecture.x86_64, Architecture.arm64, Architecture.universal2},
  86             "windows": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},
  87         }
  88         return all_archs_map[platform]
  89 
  90     @staticmethod
  91     def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> set[Architecture]:
  92         archs_32 = {Architecture.i686, Architecture.x86}
  93         auto_archs = Architecture.auto_archs(platform)
  94 
  95         if bitness == "64":
  96             return auto_archs - archs_32
  97         elif bitness == "32":
  98             return auto_archs & archs_32
  99         else:
  100             assert_never(bitness)
  101 
  102 
  103 def allowed_architectures_check(
  104     platform: PlatformName,
  105     architectures: set[Architecture],
  106 ) -> None:
  107 
  108     allowed_architectures = Architecture.all_archs(platform)
  109 
  110     msg = f"{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment."
  111 
  112     if platform != "linux":
  113         msg += " If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead."
  114 
  115     if not architectures <= allowed_architectures:
  116         msg = f"Invalid archs option {architectures}. " + msg
  117         raise ValueError(msg)
  118 
  119     if not architectures:
  120         msg = "Empty archs option set. " + msg
  121         raise ValueError(msg)
  122
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/cibuildwheel/architecture.py b/cibuildwheel/architecture.py
  --- a/cibuildwheel/architecture.py
  +++ b/cibuildwheel/architecture.py
  @@ -66,10 +66,6 @@
           if platform == "windows" and native_architecture == Architecture.AMD64:
               result.add(Architecture.x86)
   
  -        if platform == "macos" and native_architecture == Architecture.arm64:
  -            # arm64 can build and test both archs of a universal2 wheel.
  -            result.add(Architecture.universal2)
  -
           return result
   
       @staticmethod
  
verification_info: {"golden_diff": "diff --git a/cibuildwheel/architecture.py b/cibuildwheel/architecture.py\n--- a/cibuildwheel/architecture.py\n+++ b/cibuildwheel/architecture.py\n@@ -66,10 +66,6 @@\n         if platform == \"windows\" and native_architecture == Architecture.AMD64:\n             result.add(Architecture.x86)\n \n-        if platform == \"macos\" and native_architecture == Architecture.arm64:\n-            # arm64 can build and test both archs of a universal2 wheel.\n-            result.add(Architecture.universal2)\n-\n         return result\n \n     @staticmethod\n", "issue": "Should arm64 runners build both universal2 and arm64 wheels by default?\nContinuing the discussion from https://github.com/pypa/cibuildwheel/pull/1191#discussion_r928749039\r\n\r\nThe current situation is that arm64 runners builds universal2 and arm64 by default. This discussion is whether we change that to just arm64.\r\n\r\n> @joerick: The question of whether to default building both universal2 and arm64 on the arm runner is still open, in my mind. I'm still mostly of the opinion that building both is good, because universal2 packages are preferred in some contexts (e.g. distributable GUI apps), and that most packages are small and the extra build time isn't much of a hit. Of course, people building big libraries would be wise to change this to just build arm64.\r\n\r\n> @henryiii: Personally, I think the default should be native only. Eventually no one will care about Intel / universal and will only produce native binaries again. Also, there are still workarounds related to cross compiling for universal (like requiring all dependencies to also be universal). And we don\u2019t support it yet, but there are two ways to make a universal binary, the default way and merging two native binaries. And finally universal vs. native is a choice, and I\u2019d you pick universal, you don\u2019t need native. You can always add tags for the native arch\u2019s to a universal binary. And pip won\u2019t even ever download universal if both native wheels exist.\r\n> \r\n> So I\u2019d recommend native being default, and only producing native binaries with it.\r\n\r\nLet's get a decision on this before we release CirrusCI support, which would be our first officially supported arm64 CI.\r\n\n", "before_files": [{"content": "from __future__ import annotations\n\nimport functools\nimport platform as platform_module\nimport re\nfrom enum import Enum\n\nfrom .typing import Final, Literal, PlatformName, assert_never\n\nPRETTY_NAMES: Final = {\"linux\": \"Linux\", \"macos\": \"macOS\", \"windows\": \"Windows\"}\n\n\n@functools.total_ordering\nclass Architecture(Enum):\n    value: str\n\n    # mac/linux archs\n    x86_64 = \"x86_64\"\n\n    # linux archs\n    i686 = \"i686\"\n    aarch64 = \"aarch64\"\n    ppc64le = \"ppc64le\"\n    s390x = \"s390x\"\n\n    # mac archs\n    universal2 = \"universal2\"\n    arm64 = \"arm64\"\n\n    # windows archs\n    x86 = \"x86\"\n    AMD64 = \"AMD64\"\n    ARM64 = \"ARM64\"\n\n    # Allow this to be sorted\n    def __lt__(self, other: Architecture) -> bool:\n        return self.value < other.value\n\n    @staticmethod\n    def parse_config(config: str, platform: PlatformName) -> set[Architecture]:\n        result = set()\n        for arch_str in re.split(r\"[\\s,]+\", config):\n            if arch_str == \"auto\":\n                result |= Architecture.auto_archs(platform=platform)\n            elif arch_str == \"native\":\n                result.add(Architecture(platform_module.machine()))\n            elif arch_str == \"all\":\n                result |= Architecture.all_archs(platform=platform)\n            elif arch_str == \"auto64\":\n                result |= Architecture.bitness_archs(platform=platform, bitness=\"64\")\n            elif arch_str == \"auto32\":\n                result |= Architecture.bitness_archs(platform=platform, bitness=\"32\")\n            else:\n                result.add(Architecture(arch_str))\n        return result\n\n    @staticmethod\n    def auto_archs(platform: PlatformName) -> set[Architecture]:\n        native_architecture = Architecture(platform_module.machine())\n        result = {native_architecture}\n\n        if platform == \"linux\" and native_architecture == Architecture.x86_64:\n            # x86_64 machines can run i686 containers\n            result.add(Architecture.i686)\n\n        if platform == \"windows\" and native_architecture == Architecture.AMD64:\n            result.add(Architecture.x86)\n\n        if platform == \"macos\" and native_architecture == Architecture.arm64:\n            # arm64 can build and test both archs of a universal2 wheel.\n            result.add(Architecture.universal2)\n\n        return result\n\n    @staticmethod\n    def all_archs(platform: PlatformName) -> set[Architecture]:\n        all_archs_map = {\n            \"linux\": {\n                Architecture.x86_64,\n                Architecture.i686,\n                Architecture.aarch64,\n                Architecture.ppc64le,\n                Architecture.s390x,\n            },\n            \"macos\": {Architecture.x86_64, Architecture.arm64, Architecture.universal2},\n            \"windows\": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},\n        }\n        return all_archs_map[platform]\n\n    @staticmethod\n    def bitness_archs(platform: PlatformName, bitness: Literal[\"64\", \"32\"]) -> set[Architecture]:\n        archs_32 = {Architecture.i686, Architecture.x86}\n        auto_archs = Architecture.auto_archs(platform)\n\n        if bitness == \"64\":\n            return auto_archs - archs_32\n        elif bitness == \"32\":\n            return auto_archs & archs_32\n        else:\n            assert_never(bitness)\n\n\ndef allowed_architectures_check(\n    platform: PlatformName,\n    architectures: set[Architecture],\n) -> None:\n\n    allowed_architectures = Architecture.all_archs(platform)\n\n    msg = f\"{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment.\"\n\n    if platform != \"linux\":\n        msg += \" If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.\"\n\n    if not architectures <= allowed_architectures:\n        msg = f\"Invalid archs option {architectures}. \" + msg\n        raise ValueError(msg)\n\n    if not architectures:\n        msg = \"Empty archs option set. \" + msg\n        raise ValueError(msg)\n", "path": "cibuildwheel/architecture.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport functools\nimport platform as platform_module\nimport re\nfrom enum import Enum\n\nfrom .typing import Final, Literal, PlatformName, assert_never\n\nPRETTY_NAMES: Final = {\"linux\": \"Linux\", \"macos\": \"macOS\", \"windows\": \"Windows\"}\n\n\n@functools.total_ordering\nclass Architecture(Enum):\n    value: str\n\n    # mac/linux archs\n    x86_64 = \"x86_64\"\n\n    # linux archs\n    i686 = \"i686\"\n    aarch64 = \"aarch64\"\n    ppc64le = \"ppc64le\"\n    s390x = \"s390x\"\n\n    # mac archs\n    universal2 = \"universal2\"\n    arm64 = \"arm64\"\n\n    # windows archs\n    x86 = \"x86\"\n    AMD64 = \"AMD64\"\n    ARM64 = \"ARM64\"\n\n    # Allow this to be sorted\n    def __lt__(self, other: Architecture) -> bool:\n        return self.value < other.value\n\n    @staticmethod\n    def parse_config(config: str, platform: PlatformName) -> set[Architecture]:\n        result = set()\n        for arch_str in re.split(r\"[\\s,]+\", config):\n            if arch_str == \"auto\":\n                result |= Architecture.auto_archs(platform=platform)\n            elif arch_str == \"native\":\n                result.add(Architecture(platform_module.machine()))\n            elif arch_str == \"all\":\n                result |= Architecture.all_archs(platform=platform)\n            elif arch_str == \"auto64\":\n                result |= Architecture.bitness_archs(platform=platform, bitness=\"64\")\n            elif arch_str == \"auto32\":\n                result |= Architecture.bitness_archs(platform=platform, bitness=\"32\")\n            else:\n                result.add(Architecture(arch_str))\n        return result\n\n    @staticmethod\n    def auto_archs(platform: PlatformName) -> set[Architecture]:\n        native_architecture = Architecture(platform_module.machine())\n        result = {native_architecture}\n\n        if platform == \"linux\" and native_architecture == Architecture.x86_64:\n            # x86_64 machines can run i686 containers\n            result.add(Architecture.i686)\n\n        if platform == \"windows\" and native_architecture == Architecture.AMD64:\n            result.add(Architecture.x86)\n\n        return result\n\n    @staticmethod\n    def all_archs(platform: PlatformName) -> set[Architecture]:\n        all_archs_map = {\n            \"linux\": {\n                Architecture.x86_64,\n                Architecture.i686,\n                Architecture.aarch64,\n                Architecture.ppc64le,\n                Architecture.s390x,\n            },\n            \"macos\": {Architecture.x86_64, Architecture.arm64, Architecture.universal2},\n            \"windows\": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},\n        }\n        return all_archs_map[platform]\n\n    @staticmethod\n    def bitness_archs(platform: PlatformName, bitness: Literal[\"64\", \"32\"]) -> set[Architecture]:\n        archs_32 = {Architecture.i686, Architecture.x86}\n        auto_archs = Architecture.auto_archs(platform)\n\n        if bitness == \"64\":\n            return auto_archs - archs_32\n        elif bitness == \"32\":\n            return auto_archs & archs_32\n        else:\n            assert_never(bitness)\n\n\ndef allowed_architectures_check(\n    platform: PlatformName,\n    architectures: set[Architecture],\n) -> None:\n\n    allowed_architectures = Architecture.all_archs(platform)\n\n    msg = f\"{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment.\"\n\n    if platform != \"linux\":\n        msg += \" If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.\"\n\n    if not architectures <= allowed_architectures:\n        msg = f\"Invalid archs option {architectures}. \" + msg\n        raise ValueError(msg)\n\n    if not architectures:\n        msg = \"Empty archs option set. \" + msg\n        raise ValueError(msg)\n", "path": "cibuildwheel/architecture.py"}]}