- gccrs es un proyecto iniciado en 2014 para implementar un compilador de Rust dentro de GCC; todavía está lejos de completarse, pero ha avanzado hacia la compilación de la biblioteca estándar y su inclusión en GCC 14
- El proyecto tomó como objetivo Rust 1.49 en lugar de seguir el ritmo de las versiones más recientes de Rust, pero debido a dependencias internas de la biblioteca estándar, al final también tuvo que implementar funciones como
const generics - La compilación de
coreyallocsigue bloqueada por la resolución de nombres de macros, las macros decoradoras, los intrinsics del compilador de LLVM que no existen en GCC y la ausencia de un borrow checker - rustc_codegen_gcc es un enfoque más maduro que reutiliza partes de rustc y usa GCC para la generación de código en el backend; desde octubre de 2023 puede compilar Rust for Linux sin parches adicionales
- gccrs tiene motivaciones claras como los plugins de seguridad de GCC, el análisis estático, las arquitecturas no compatibles con LLVM y Rust for Linux, pero su utilidad práctica aún es más limitada que la de
rustc_codegen_gcc
Objetivo de gccrs y su situación actual
- gccrs es un proyecto que busca implementar un compilador de Rust dentro de la GNU Compiler Collection (GCC)
- Comenzó en 2014 y, según reportes del proyecto posteriores a la cobertura previa de LWN, ha mostrado avances
- En 2022 apuntaba a ser incluido en GCC 13, pero no lo logró; según el informe mensual de noviembre de 2023, ahora apunta a GCC 14
- GCC 14 se maneja como una versión con posible lanzamiento a mediados de 2024
- En EuroRust 2023, en octubre de 2023, Arthur Cohen presentó “The road to compiling the standard library with gccrs”, donde explicó el trabajo para compilar la biblioteca estándar de Rust y por qué aún no puede compilarse
- Está disponible el video de la charla
Por qué eligieron apuntar a Rust 1.49
- gccrs tomó como objetivo Rust 1.49 en vez de seguir continuamente la versión más reciente de Rust
- Rust 1.49 fue lanzado a finales de 2020 y es la última versión anterior al soporte de
const generics, que pasó a estar disponible de forma general en Rust 1.50 - El proyecto intentó evitar
const generics, pero como ya se usaba internamente incluso en la biblioteca estándar de Rust 1.49, terminó siendo imposible ignorarlo const genericsya fue implementado por completo y dejó de ser un obstáculo- gccrs no busca crear un superconjunto de Rust ni un lenguaje separado llamado “GNU Rust”
- La meta es reproducir incluso la salida, los bugs y los comportamientos peculiares de
rustc - Para ello usa tanto la suite de pruebas de Rust como la de GCC
- La meta es reproducir incluso la salida, los bugs y los comportamientos peculiares de
Bloqueos en la compilación de la biblioteca estándar
- La biblioteca estándar de Rust está compuesta por varios crates
- gccrs está trabajando en el soporte para compilar los dos crates más importantes, core y alloc
coreimplementa funciones base de la biblioteca estándar, como tipos primitivos y macrosallocse encarga de la asignación de memoria en el heap y de varios tipos de contenedores
- Actualmente gccrs no puede compilar estos crates por la falta de las siguientes funciones
- La resolución de nombres de macros no funciona correctamente
- El soporte para macros decoradoras no está completo
- No hay borrow checker, por lo que no puede verificarse correctamente la seguridad del código
- Hay que implementar intrinsics del compilador de LLVM que no existen en GCC
- La ausencia del borrow checker no impide compilar como tal, pero sí evita comprobar adecuadamente la seguridad del código Rust
Macros procedurales e integración con GCC
- En GNU Tools Cauldron de septiembre de 2023, Pierre-Emmanuel Patry presentó los avances hacia la inclusión en GCC 14, con foco en el trabajo sobre macros
- Están disponibles las diapositivas de la charla
- La implementación de macros procedurales (procedural macro) requiere cambios en el sistema de compilación de GCC
- Las macros procedurales son macros funcionales que emiten un flujo de tokens, no texto fuente simple como las macros de C o C++
- En Rust se implementan con el crate integrado proc_macro
- Son difíciles de implementar, pero permiten funciones muy potentes
- Decoradores
#[attribute] - Decoradores
#[derive()] - Generación de lenguajes específicos de dominio basada en evaluación en tiempo de compilación
- Decoradores
- Según la charla de GNU Cauldron, gccrs tenía más de 800 commits pendientes de upstream hacia GCC
Por qué quieren aprovechar el ecosistema GCC para Rust
- Una de las principales motivaciones de gccrs es poder aprovechar los plugins de seguridad de GCC también en código Rust
- GCC cuenta con varios plugins que ayudan con depuración, análisis estático y hardening, y todos operan sobre la representación intermedia de GCC
- gccrs quiere permitir un flujo de trabajo en el que desarrolladores de Rust puedan reutilizar plugins existentes de GCC
- Cohen dio como ejemplo que durante mucho tiempo los programadores de C han cometido errores como no cerrar descriptores de archivo, por lo que existen muchos plugins para detectar eso
- El objetivo es poder usar plugins existentes de GCC y analizadores estáticos para detectar bugs en código Rust
unsafe
Áreas donde ya se está usando parcialmente
- Según Cohen, la comunidad homebrew de Sega Dreamcast ya está usando gccrs para crear juegos nuevos para la consola Dreamcast
- El interés de esa comunidad se debe a que el backend LLVM de
rustcno soporta la arquitectura Hitachi SH-4 de la consola, mientras que GCC sí - gccrs sigue incompleto, pero aun así resulta útil en este tipo de casos de uso embebidos
- Ya es posible hacer análisis estático de código Rust
unsafeusando plugins de GCC - En el proceso de desarrollo de gccrs quedaron expuestas funciones del lenguaje cuya especificación no estaba suficientemente definida, como
Derefy la resolución de nombres de macros, y el proyecto también ha podido contribuir a ampliar la especificación de Rust- Rust todavía no tiene una especificación oficial, pero se está trabajando en ella según RFC 3355
Funciones clave que siguen en desarrollo
- A gccrs todavía le faltan muchas funciones centrales de un compilador de Rust
- Entre las principales funciones no implementadas o aún en desarrollo están
async/await- Intrinsics de LLVM que no existen en GCC
- La macro
format_args!()que usan macros de salida comoprintln!() - El borrow checker que hace cumplir las reglas de referencias de Rust
- La solución más prometedora para el borrow checker es el proyecto separado Polonius
- Cohen dijo que es muy probable que gccrs integre Polonius en los próximos meses
- Jakub Dupak ha logrado avances en este trabajo en los últimos meses
- Polonius es una biblioteca que implementa un borrow checker semánticamente equivalente al borrow checker actual de
rustc- Usa un algoritmo distinto para calcular la duración de las referencias
- A largo plazo busca resolver limitaciones y casos borde del borrow checker actual de
rustc - Si madura lo suficiente, es posible que
rustctambién adopte Polonius en el futuro
Por qué se necesita format_args!()
- Según el informe mensual de gccrs de noviembre de 2023, ya comenzó el trabajo sobre la macro
format_args!() format_args!()es una macro auxiliar que construye los argumentos que se pasan a macros de formateo de cadenas- Esta función está relacionada con los traits Display y Debug
- Se necesita para preparar los argumentos que se pasan a macros como
format!()yprintln!() - Sin
format_args!(), un programa Rust no puede generar salida con formato - Por eso es una función necesaria incluso antes de que gccrs pueda compilar un programa “Hello, World”
- También se menciona como referencia un artículo de blog de Mara Bos que explica
format_args!()en profundidad
Diferencias frente a rustc_codegen_gcc
rustc_codegen_gcces otro proyecto de Rust basado en GCC, distinto de gccrs- Es más maduro que gccrs, pero su alcance es más limitado
- No consiste en implementar por completo un compilador de Rust desde cero
- Usa la biblioteca libgccjit para conectarse con la API del backend LLVM de
rustc - Gran parte de la compilación la realiza
rustc, y en etapas posteriores se utiliza GCC - Aunque el nombre
libgccjitincluye JIT,rustc_codegen_gccestá orientado a compilación ahead-of-time - Su objetivo principal es permitir la generación de código Rust en plataformas que LLVM no soporta
- En octubre de 2023,
rustc_codegen_gccya podía compilar Rust for Linux sin parches adicionales - Durante el último año añadió soporte para SIMD y optimización en tiempo de enlazado
- Ambas funciones habían sido señaladas antes como causa de fallos en las pruebas
- En su charla de EuroRust, Cohen recomendó varias veces usar
rustc_codegen_gccpor ahora en lugar de gccrs rustc_codegen_gccya fue integrado upstream en el repositorio del lenguaje Rust
Rust for Linux y la brecha de versiones
- Rust for Linux es una iniciativa para añadir soporte de Rust al kernel de Linux
- Cohen mencionó el kernel de Linux como una motivación central del proyecto gccrs
- Esto se debe a que muchas personas vinculadas al kernel prefieren que el kernel pueda compilarse usando únicamente la toolchain GNU
- Actualmente el proyecto Rust for Linux documenta como métodos para compilar el código Rust del kernel a rustc o a rustc_codegen_gcc
- El kernel también documenta versiones mínimas soportadas para varias herramientas de compilación
- En el caso de
rustc, no se maneja una versión mínima sino una versión que debe coincidir exactamente - La versión actualmente soportada de
rustces 1.73.0, lanzada en octubre de 2023
- En el caso de
- Entre Rust 1.49, que es el objetivo de gccrs, y Rust 1.73.0, que requiere Rust for Linux, existe una gran diferencia
- El soporte para Rust for Linux es una meta explícita de gccrs, pero esa brecha de versiones hace que todavía esté bastante lejos
Evaluación general
- El repositorio de gccrs tiene más de 3,000 commits desde el 1 de enero de 2023
- Durante el último año, el proyecto ha mostrado avances considerables
- Pero como el alcance de implementar un compilador completo de Rust desde cero es enorme, todavía no está en un estado utilizable para casi ningún propósito práctico
rustc_codegen_gccya fue fusionado en el repositorio upstream de Rust y se está usando de verdad en Rust for Linux- Aún no se ha llegado al punto de tener varias implementaciones independientes del compilador de Rust en uso amplio, pero se está más cerca de esa dirección
1 comentarios
Comentarios de Hacker News
Solo con lo que afirma el artículo, la motivación de gccrs se ve algo débil
La preferencia por los plugins de seguridad de GCC o por el toolchain GNU en el kernel de Linux explica por qué alguien querría usar GCC como backend, pero no explica por qué hace falta un frontend duplicado
Ojalá Rust no repita el error de C++, donde el desarrollo multiplataforma se complica por diferencias en switches entre compiladores, niveles de soporte del lenguaje y bugs específicos de cada plataforma
Así que estaría bien que explicaran por qué gccrs es un mejor enfoque que
rustc_codegen_gcc; este último parece poder lograr el mismo objetivo con mucho menos esfuerzo y riesgoSi te topas con un bug del compilador en MSVC, puedes reportarlo y seguir trabajando cambiándote a GCC, pero en Rust hoy no existe esa opción
Como se cita, un ejemplo es el cuidado de no querer convertirse en un superconjunto de Rust
El problema de C/C++ surgió porque los proveedores de compiladores competían entre sí por ser “mejores”, y múltiples frontends suelen tener la ventaja de sacar a la luz muchos bugs e implementaciones incorrectas
No es que Rust sea sagrado en algún sentido y esté prohibido reescribir el frontend, y seguir haciendo bootstrap de Rust en arquitecturas nuevas continúa siendo doloroso
En arquitecturas que LLVM no soporta, tampoco hay un compilador de Rust que funcione
codegen_rust_gcctambién tiene el mismo problema de bootstrap que el compilador actual de Rust, y hay que agregar soporte de arquitectura en varias partes de Rust, algo que sus mantenedores han sido reacios a hacerAsí que si en un futuro cercano aparece un compilador de Rust utilizable de inmediato y eso permite volver a compilar bibliotecas escritas en Rust incluso en arquitecturas como Alpha sin demasiado dolor, sería muy bienvenido
Ya existían GCC, G++, libstdc++, y el frontend C++ de EDG
GCC, Clang, MSVC y otros compiladores se complementan entre sí, atienden distintos objetivos y mercados, y ayudan a que el lenguaje se fortalezca conforme a la especificación en lugar de depender de las características accidentales de una sola implementación
El GNU Toolchain Project, el LLVM Project y el proyecto Rust han tenido problemas, así que es mejor no depender de un solo punto de falla, y la redundancia y la antifragilidad son aliadas
Me resulta confuso preferir ver mal los estándares de lenguaje y no decir “este código es C99/C++11”, sino “este código funciona en el binario/código fuente de rustc con hash SHA256
e49d560cd008344edf745b8052ef714b07595808898c835f17f962a10012f964”Rust necesita un estándar del lenguaje
https://blog.m-ou.se/rust-standard/
https://rust-lang.github.io/rfcs/3355-rust-spec.html
https://github.com/rust-lang/rfcs/pull/3355
Hay muchas organizaciones e industrias que no adoptarán Rust hasta que exista un estándar
C, C++, C#, e incluso JavaScript (ECMAScript) tienen un estándar del lenguaje, así que no hay razón para que Rust no lo tenga
C: https://www.iso.org/standard/74528.html
C++: https://isocpp.org/std/the-standard
C#: https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
JavaScript / ECMAScript: https://ecma-international.org/publications-and-standards/st...
El progreso ha sido decepcionantemente lento, pero el proyecto sigue vivo y es posible que el próximo año tome velocidad
https://blog.rust-lang.org/inside-rust/2023/11/15/spec-visio...
https://go.dev/ref/spec
No veo por qué habría que cambiar algo que está funcionando
Me sorprende que haya tantas reacciones negativas a GCC-RS
Considero que un lenguaje sin múltiples implementaciones es bastante pobre
El consenso en la comunidad de Rust parece ser que el enfoque actual —un solo compilador que por definición es el estándar, mucha documentación, una especificación mínima para industrias donde la seguridad es esencial y especificaciones para algunas subáreas de módulos— conserva la mayoría de las ventajas de tener varias implementaciones y evita sus desventajas
En C eso se ha sufrido de verdad, y C++ ya está casi más allá de toda salvación por su complejidad absurda y extraña
Sin eso, es difícil que aparezcan implementaciones alternativas realistas
La toolchain de GNU es un desastre y no entiendo cómo se desarrolla realmente sobre ella
No lo digo por ideología; literalmente no entiendo cómo se arma el entorno de desarrollo del propio GCC
He tenido la mala suerte de hacer bootstrap unas cuantas veces, y fue de lo peor que he visto funcionar en software
Me gusta la parte sobre que la comunidad homebrew de Sega Dreamcast pueda crear juegos nuevos con gccrs, y que se pueda hacer análisis estático de código Rust unsafe con plugins de GCC
El backend LLVM de
rustcno soporta la arquitectura Hitachi SH-4 de la Dreamcast, pero GCC sí, así que incluso gccrs en estado incompleto sirve para este tipo de uso embebidoPara eso no hace falta un frontend de GCC, basta con el backend de GCC
Ahora probablemente veremos soporte de Rust también en arquitecturas como Alpha, SuperH y VAX, que LLVM no soporta pero GCC sí
rustcabandonó recientemente después de no lograr conseguir financiamiento/recursos de Loongsonhttps://github.com/rust-lang/compiler-team/issues/648
El mayor problema de la forma de pensar al estilo LLVM es que usa el soporte de arquitecturas como una manera de sacar apoyo de las empresas de hardware, es decir, puestos de desarrolladores pagados
GNU puede tener criterios de integración molestamente altos, pero una vez que algo entra y queda soportado, lo mantiene a largo plazo
Es como la diferencia entre comprar y rentar: meter soporte en GCC cuesta mucho más tiempo de desarrollo, pero una vez dentro, se queda
Por ejemplo, hace poco me enteré de que en RISC-V GCC soporta el objetivo RV32E, mientras que LLVM no
La última vez que revisé, en GCC todavía funcionaba la compilación independiente de C
Por experiencia, me parece un gran error que gccrs intente replicar la salida de
rustc, incluidos sus bugs y rarezas, en vez de crear un lenguaje especial “GNU Rust”Rust no tiene una especificación; hay documentos de referencia, pero explícitamente no son normativos
Un lenguaje no documentado más allá de una única implementación de referencia tiene una debilidad a largo plazo
El objetivo de asegurar que el código existente funcione en ambas implementaciones es razonable, pero prometer compatibilidad de bugs es una mala decisión porque fosiliza malas decisiones y errores
Microsoft dedica mucho personal a corregir bugs de seguridad y confiabilidad sin dejar de ejecutar programas viejos, y Rust no necesita cargar con eso tan temprano en su vida
Si quieres que el lenguaje evolucione, tienes que aceptar aseguramiento y control de calidad
La calidad no se puede inyectar después con pruebas; hay que hacer que funcione bien desde la arquitectura y el diseño, y mediante procesos como revisiones de diseño y de código, de modo que aunque falle, falle en la dirección correcta
Estándares fuertes como Common Lisp, C++ y FORTRAN aceptaron esa idea, y lenguajes débiles pero cercanos a un estándar de facto, como Python, también pueden ganar popularidad, pero que cambiar sea difícil se ve en la larga transición de Python 2 a 3 y en la poca cantidad de implementaciones
Me sumo tarde en esta parte del hilo, pero esto no necesariamente es algo bueno
Las distribuciones no pueden seguir el ritmo de lenguajes que sacan versiones nuevas cada pocos meses, así que ya es difícil usar
rustco Go como paquetes de la distribuciónAhora mismo, de forma sorprendente, hay sistemas donde GCC dejó de hacer falta y fue eliminado, y solo se mantienen Go y Rust upstream para actualizar software existente
Hace unos meses, cuando actualicé Go por un CVE, fue una pesadilla ver que las apps basadas en Go habían guardado su propio entorno de Go en hasta cuatro lugares distintos
Linux ya se puede compilar con Clang si uno quiere, y usar una toolchain completamente basada en LLVM
No parece que el esfuerzo duplicado de desarrollar y mantener esto por la “pureza” de GNU valga la pena
La comunidad ClangBuiltLinux argumentaba que Linux no debía depender de un solo compilador, pero cuando llegó Rust, bastantes de esas mismas personas de pronto empezaron a ver bien depender de uno solo
No se trata de atar el kernel exclusivamente a GNU, sino solo de permitir elegir una toolchain GNU pura