TL;DR: El propio binario incorpora información sobre qué arquitectura es, y el SO lo mira para decidir cómo ejecutarlo. arch
sólo se requiere para forzar el uso de una variante arquitectónica específica de un binario universal.
Todos los formatos modernos de archivos ejecutables, incluido el formato Mach-O utilizado por MacOS, el formato ELF utilizado por la mayoría de los demás sistemas tipo UNIX y el formato PE utilizado por Windows y UEFI, incorporan información en la cabecera del archivo sobre la arquitectura de la CPU para la que está destinado el código del archivo y el entorno (o sistema operativo) en el que debe ejecutarse.
Cuando se invoca un ejecutable, lo primero que ocurre es que una parte del sistema operativo conocida como "cargador de ejecutables" echa un vistazo al archivo y decide cómo cargarlo en memoria y cómo ejecutarlo. El cargador de ejecutables suele ser razonablemente inteligente, y normalmente puede determinar que necesita utilizar un intérprete o una capa de traducción antes incluso de cargar el código en la memoria. Un ejemplo trivial de esto es el manejo de scripts que comienzan con un #!
el cargador de ejecutables en el sistema operativo ve que #!
y sabe que significa ejecutar el comando después de eso y pasar la ruta al script como argumento posicional.
La misma lógica se aplica a esta información sobre la arquitectura de la CPU para la que es el ejecutable. En MacOS para el silicio de Apple, hay un caso especial en el código del cargador de ejecutables que intentará ejecutar binarios para CPUs x86_64 utilizando Rosetta 2 si está instalado. Si Rosetta 2 no está instalado, sólo obtendrá un mensaje de error de que el ejecutable no se pudo ejecutar, pero si lo está, el ejecutable se ejecutará sin problemas sin molestarle.
El arch
existe principalmente para el caso especial de ejecutar binarios universales. Con el formato Mach-O y el código cargador estándar de MacOS, el sistema operativo ejecutará la primera versión válida de un programa en un binario universal que coincida con la CPU anfitriona. Al utilizar arch
Sin embargo, se puede forzar explícitamente al sistema a ejecutar la versión x86_64 en un sistema con Rosetta 2 instalado. Lo mismo podría hacerse históricamente para ejecutar explícitamente la versión de 32 bits de un binario en un sistema de 64 bits. Esto parece un poco inútil, pero es útil para que los desarrolladores verifiquen que sus binarios universales funcionan correctamente cuando sólo tienen acceso a un tipo de hardware.
Por otro lado, este mismo tipo de flexibilidad en tiempo de ejecución puede ampliarse aún más en algunas plataformas. Linux, por ejemplo, tiene una característica llamada binfmt_misc
que permite asociar intérpretes arbitrarios con tipos de archivo arbitrarios. Históricamente, esto se originó para soportar cosas como el tratamiento de archivos JAR como ejecutables regulares, pero se utiliza activamente hoy en día junto con la emulación del espacio de usuario QEMU para hacer el mismo tipo de cosas que MacOS está haciendo con Rosetta 2 para aún más arquitecturas de CPU.