- gccrs é um projeto iniciado em 2014 para implementar um compilador Rust dentro do GCC; ainda está longe de ficar pronto, mas avançou em direção à compilação da biblioteca padrão e à inclusão no GCC 14
- O projeto adotou Rust 1.49 como meta em vez de acompanhar o Rust mais recente em rápida mudança, mas por causa de dependências internas da biblioteca padrão acabou tendo de implementar recursos como
const generics - A compilação de
coreeallocainda está bloqueada por resolução de nomes de macros, macros decoradoras, intrinsics de compilador do LLVM que não existem no GCC e pela ausência de um borrow checker - rustc_codegen_gcc é uma abordagem mais madura que reutiliza partes do rustc e usa o GCC como backend de geração de código; em outubro de 2023 já conseguia compilar Rust for Linux sem patches adicionais
- O gccrs tem motivações claras, como plugins de segurança do GCC, análise estática, arquiteturas sem suporte do LLVM e Rust for Linux, mas sua utilidade prática ainda é mais limitada que a do
rustc_codegen_gcc
Objetivos do gccrs e situação atual
- gccrs é um projeto para implementar um compilador Rust dentro do GNU Compiler Collection (GCC)
- Começou em 2014 e, segundo um relatório do projeto após uma cobertura anterior da LWN, houve progresso
- Em 2022, a meta era entrar no GCC 13, mas isso não foi alcançado; no relatório mensal de novembro de 2023, a meta passou a ser a inclusão no GCC 14
- O GCC 14 é tratado como uma versão com possibilidade de lançamento em meados de 2024
- Na EuroRust 2023, em outubro de 2023, Arthur Cohen apresentou “The road to compiling the standard library with gccrs”, explicando o trabalho para compilar a biblioteca padrão do Rust e por que isso ainda não foi possível
- O vídeo da apresentação está disponível
Por que mirar no Rust 1.49
- O gccrs optou por mirar no Rust 1.49 em vez de tentar acompanhar continuamente a versão mais recente do Rust
- O Rust 1.49 foi lançado no fim de 2020 e é a última versão anterior ao suporte a
const generics, disponibilizado para uso geral no Rust 1.50 - O projeto tentou evitar
const generics, mas esse recurso já era usado internamente na biblioteca padrão do Rust 1.49, então acabou sendo impossível ignorá-lo const genericsfoi implementado por completo depois disso e não é mais um obstáculo- O gccrs não quer criar um superconjunto de Rust nem uma linguagem separada chamada “GNU Rust”
- O objetivo é reproduzir até a saída, os bugs e os comportamentos peculiares do
rustc - Para isso, usa tanto a suíte de testes do Rust quanto a do GCC
- O objetivo é reproduzir até a saída, os bugs e os comportamentos peculiares do
O que ainda bloqueia a compilação da biblioteca padrão
- A biblioteca padrão do Rust é composta por vários crates
- O gccrs está trabalhando no suporte à compilação dos dois crates mais importantes, core e alloc
coreimplementa recursos fundamentais da biblioteca padrão, como tipos primitivos e macrosalloclida com alocação de memória no heap e vários tipos de contêiner
- Hoje o gccrs ainda não consegue compilar esses crates por falta dos recursos abaixo
- O comportamento da resolução de nomes de macros ainda não está correto
- O suporte a macros decoradoras não está completo
- Não há borrow checker, então a segurança do código não pode ser verificada corretamente
- É preciso implementar intrinsics de compilador do LLVM que não existem no GCC
- A ausência do borrow checker não impede a compilação em si, mas impede a verificação adequada de segurança do código Rust
Macros procedurais e integração com o GCC
- No GNU Tools Cauldron de setembro de 2023, Pierre-Emmanuel Patry apresentou o progresso rumo à inclusão no GCC 14, com foco no trabalho com macros
- Os slides da apresentação estão disponíveis
- A forma de implementar macros procedurais (procedural macro) exige mudanças no sistema de build do GCC
- Em vez de gerar apenas texto-fonte simples como macros de C ou C++, macros procedurais são macros funcionais que emitem streams de tokens
- Em Rust, são implementadas pelo crate embutido proc_macro
- Macros procedurais são difíceis de implementar, mas permitem recursos poderosos
- Decoradores
#[attribute] - Decoradores
#[derive()] - Criação de linguagens específicas de domínio com avaliação em tempo de compilação
- Decoradores
- Segundo a apresentação no GNU Cauldron, o gccrs tinha mais de 800 commits que ainda precisavam ser enviados para upstream no GCC
Por que aproveitar o ecossistema do GCC para Rust
- Uma das principais motivações do gccrs é usar os plugins de segurança do GCC também em código Rust
- O GCC tem vários plugins que ajudam em depuração, análise estática e hardening, e eles operam sobre a representação intermediária do GCC
- O gccrs quer permitir um fluxo de trabalho em que desenvolvedores Rust reutilizem plugins já existentes do GCC
- Cohen deu como exemplo que programadores C há muito tempo cometem erros como esquecer de fechar descritores de arquivo, então existem muitos plugins para detectar isso
- O objetivo é aproveitar plugins e analisadores estáticos já existentes do GCC para encontrar bugs em código Rust
unsafe
Áreas em que ele já é usado parcialmente
- Segundo Cohen, a comunidade homebrew do Sega Dreamcast está usando o gccrs para criar novos jogos para o console Dreamcast
- O motivo do interesse é que o backend LLVM do
rustcnão oferece suporte à arquitetura Hitachi SH-4 do console, enquanto o GCC oferece - O gccrs ainda está incompleto, mas já ajuda nesse tipo de caso de uso embarcado
- Também já é possível fazer análise estática de código Rust
unsafeusando plugins do GCC - No processo de desenvolvimento do gccrs, surgiram recursos da linguagem cuja especificação ainda não estava suficientemente definida, como
Derefe resolução de nomes de macros, e o projeto pôde contribuir para a elaboração da especificação do Rust- Atualmente o Rust não tem uma especificação oficial, mas o trabalho está em andamento conforme o RFC 3355
Recursos centrais ainda em desenvolvimento
- O gccrs ainda não tem muitos recursos essenciais de um compilador Rust
- Entre os principais recursos ainda não implementados ou em desenvolvimento estão
async/await- Intrinsics do LLVM que não existem no GCC
- A macro
format_args!()usada por macros de saída comoprintln!() - O borrow checker, que aplica as regras de referências do Rust
- A solução mais promissora para o borrow checker é o projeto separado Polonius
- Cohen disse que é muito provável que o gccrs integre o Polonius em alguns meses
- Jakub Dupak fez progresso nesse trabalho nos últimos meses
- O Polonius é atualmente uma biblioteca que implementa um borrow checker semanticamente equivalente ao do
rustc- Usa um algoritmo diferente para calcular o tempo de vida das referências
- No longo prazo, o objetivo é resolver limitações e corner cases do borrow checker atual do
rustc - Quando amadurecer, é possível que o
rustctambém adote o Polonius no futuro
Por que format_args!() é necessário
- Segundo o relatório mensal do gccrs de novembro de 2023, o trabalho na macro
format_args!()foi iniciado format_args!()é uma macro auxiliar que monta os argumentos passados às macros de formatação de strings- Esse recurso está ligado aos traits Display e Debug
- Ele é necessário para preparar os argumentos entregues a macros como
format!()eprintln!() - Sem
format_args!(), programas Rust não conseguem produzir saída formatada - Portanto, esse recurso já é necessário antes mesmo de o gccrs conseguir compilar um programa “Hello, World”
- Como explicação aprofundada de
format_args!(), também é citado um post de blog de Mara Bos
Diferença em relação ao rustc_codegen_gcc
rustc_codegen_gccé outro projeto Rust baseado em GCC, diferente do gccrs- Ele é mais maduro que o gccrs, mas tem escopo mais limitado
- Não segue a abordagem de implementar um compilador Rust completo do zero
- Usa a biblioteca libgccjit para se conectar à API do backend LLVM do
rustc - Grande parte da compilação é feita pelo
rustc, e o GCC entra nas etapas posteriores - Embora
libgccjittenha “JIT” no nome, orustc_codegen_gcctem como objetivo a compilação ahead-of-time - O principal objetivo é permitir a geração de código Rust em plataformas sem suporte do LLVM
- Em outubro de 2023, o
rustc_codegen_gccjá conseguia compilar Rust for Linux sem patches adicionais - No último ano, o projeto adicionou suporte a SIMD e otimização em tempo de link
- Esses dois recursos haviam sido apontados anteriormente como causa de falhas nos testes
- Na apresentação da EuroRust, Cohen recomendou várias vezes usar
rustc_codegen_gccpor enquanto, em vez do gccrs - O
rustc_codegen_gccjá entrou no repositório upstream da linguagem Rust
Rust for Linux e a diferença de versões
- Rust for Linux é uma iniciativa para adicionar suporte a Rust ao kernel Linux
- Cohen apontou o kernel Linux como uma motivação central do projeto gccrs
- Isso porque muitas pessoas ligadas ao kernel preferem que ele possa ser compilado apenas com a toolchain GNU
- Atualmente, o projeto Rust for Linux documenta como formas de compilar o código Rust do kernel o rustc ou o rustc_codegen_gcc
- O kernel também documenta versões mínimas suportadas para várias ferramentas de build
- O
rustcnão é tratado como versão mínima, mas como uma versão que precisa corresponder exatamente - A versão de
rustcatualmente suportada é a 1.73.0, lançada em outubro de 2023
- O
- Há uma grande diferença entre o Rust 1.49 que o gccrs tem como alvo e o Rust 1.73.0 exigido pelo Rust for Linux
- O suporte ao Rust for Linux é um objetivo declarado do gccrs, mas essa diferença de versões mostra que ele ainda está bem distante
Avaliação geral
- O repositório do gccrs tem mais de 3.000 commits desde 1º de janeiro de 2023
- No último ano, o projeto mostrou progresso considerável
- Mas, como o escopo de implementar um compilador Rust completo do zero é enorme, ele ainda não está em um estado utilizável para quase qualquer finalidade prática
- O
rustc_codegen_gccjá foi integrado ao repositório upstream do Rust e está em uso real no Rust for Linux - Ainda não chegamos ao ponto em que a linguagem Rust tem várias implementações independentes de compilador, mas estamos nos aproximando dessa direção
1 comentários
Opiniões do Hacker News
Só pelas afirmações do texto, a motivação do gccrs parece um tanto fraca
Plugins de segurança do GCC ou a preferência da comunidade do kernel Linux pela toolchain GNU explicam por que alguém gostaria de usar o GCC como backend, mas não explicam por que é necessário um frontend duplicado
Espero que Rust não repita o erro do C++, em que o desenvolvimento multiplataforma fica difícil por causa de diferenças entre opções de compiladores, níveis de suporte à linguagem e bugs específicos de plataforma
Por isso seria bom explicar por que o gccrs é uma abordagem melhor que
rustc_codegen_gcc; esta última parece capaz de atingir o mesmo objetivo com muito menos esforço e riscoSe você encontra um bug de compilador no MSVC, pode reportá-lo e depois mudar para o GCC para continuar trabalhando, mas em Rust hoje não existe essa opção
Como foi citado, o cuidado para não se tornar um superset de Rust é um exemplo disso
O problema de C/C++ surgiu porque fornecedores de compiladores competiam entre si para serem “melhores”, e múltiplos frontends geralmente têm a vantagem de revelar muitos bugs e implementações incorretas
Rust não é sagrado em nenhum sentido que proíba uma reescrita do frontend, e fazer bootstrap de Rust em novas arquiteturas ainda é doloroso
Em arquiteturas não suportadas pelo LLVM, também não há um compilador Rust funcional
codegen_rust_gcctem o mesmo problema de bootstrap do compilador Rust existente, e seria preciso adicionar suporte de arquitetura em várias partes de Rust, algo que os mantenedores de Rust têm evitadoEntão, se em um futuro próximo houver um compilador Rust utilizável de imediato, permitindo voltar a compilar bibliotecas reescritas em Rust em arquiteturas como Alpha sem grande sofrimento, isso seria muito bem-vindo
Já existiam GCC, G++, libstdc++, o frontend C++ da EDG
GCC, Clang, MSVC e outros compiladores se complementam, atendem a objetivos e mercados diferentes, e ajudam a tornar a linguagem robusta conforme a especificação, em vez de depender de características acidentais de uma única implementação
O GNU Toolchain Project, o LLVM Project e o projeto Rust já tiveram problemas, então é melhor não depender de um ponto único de falha; redundância e antifragilidade são nossas amigas
É confuso ver alguém encarar padrões de linguagem como algo ruim e preferir dizer “este código funciona no binário/fonte do rustc com hash SHA256
e49d560cd008344edf745b8052ef714b07595808898c835f17f962a10012f964” em vez de “este código é C99/C++11”Rust precisa de um padrão de linguagem
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
Há muitas organizações e indústrias que não vão adotar Rust até que exista um padrão
C, C++, C# e até JavaScript (ECMAScript) têm padrões de linguagem; não há motivo para Rust não ter
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...
O progresso é frustrantemente lento, mas o projeto está vivo, e há chance de ganhar velocidade no ano que vem
https://blog.rust-lang.org/inside-rust/2023/11/15/spec-visio...
https://go.dev/ref/spec
Não vejo por que mudar algo que funciona bem
É surpreendente haver tanta reação negativa ao GCC-RS
Acho que uma linguagem fica bem pobre se não tiver múltiplas implementações
O consenso da comunidade Rust parece ser que o modelo atual — um único compilador que é o padrão por definição, muita documentação, uma especificação mínima para uso industrial crítico em segurança e especificações de alguns subdomínios de módulos — traz a maior parte das vantagens de múltiplas implementações evitando as desvantagens
Isso acontece de fato em C, e C++ já está quase sem salvação por causa de uma complexidade absurda e esquisita
Sem isso, é difícil surgir uma implementação alternativa realista
O toolchain GNU é uma bagunça, e eu realmente não sei como alguém desenvolve sobre ele
Não é uma questão ideológica; literalmente não entendo como configurar o ambiente de desenvolvimento do próprio GCC
Tive o azar de fazer bootstrap algumas vezes, e foi a coisa com pior comportamento que já vi em software
Gosto da parte em que a comunidade homebrew do Sega Dreamcast cria jogos novos com gccrs, e em que dá para fazer análise estática de código Rust unsafe com plugins do GCC
A arquitetura Hitachi SH-4 do Dreamcast não é suportada pelo backend LLVM do
rustc, mas é suportada pelo GCC, então mesmo o gccrs inacabado ajuda nesse tipo de uso embarcadoPara isso, não é necessário um frontend GCC; basta o backend GCC
Agora talvez vejamos suporte a Rust também em arquiteturas como Alpha, SuperH e VAX, que o LLVM não suporta e o GCC suporta
rustcabandonou recentemente depois de tentar, sem sucesso, obter financiamento/recursos da Loongsonhttps://github.com/rust-lang/compiler-team/issues/648
O maior problema da mentalidade do LLVM é usar suporte a arquiteturas como meio de extrair apoio de empresas de hardware, isto é, vagas de desenvolvedores pagos
O GNU pode ter critérios irritantemente altos para mesclar mudanças, mas, uma vez que algo entra e passa a ser suportado, ele é mantido no longo prazo
É como a diferença entre comprar e alugar; leva muito mais tempo de desenvolvimento para colocar suporte no GCC, mas, uma vez que entra, permanece
Por exemplo, soube recentemente que, em RISC-V, o GCC suporta o alvo RV32E, mas o LLVM não
Da última vez que verifiquei, a compilação C standalone ainda funcionava no GCC
Pela minha experiência, é um grande erro o gccrs não criar uma linguagem especial chamada “GNU Rust” e tentar replicar a saída do
rustc, inclusive seus bugs e peculiaridadesRust não tem uma especificação; há documentação de referência, mas ela explicitamente não é normativa
Uma linguagem não documentada, exceto por uma única implementação de referência, tem uma fraqueza de longo prazo
O objetivo de garantir que código existente funcione nas duas implementações é razoável, mas, se prometerem até compatibilidade com bugs, acabarão fossilizando decisões ruins e bugs
A Microsoft emprega muita gente para manter programas antigos funcionando ao mesmo tempo em que corrige bugs de segurança e confiabilidade, mas Rust não precisa assumir esse fardo tão cedo em seu ciclo de vida
Se quiser evoluir a linguagem, é preciso aceitar garantia e controle de qualidade
Qualidade não pode ser injetada depois com testes; é preciso fazê-la funcionar corretamente, e, mesmo quando falhar, falhar na direção certa, por meio de processos como arquitetura e design, revisão de design e de código
Padrões fortes como Common Lisp, C++ e FORTRAN aceitaram essa crença, e linguagens fracas, quase como padrões de fato, como Python, também podem se tornar populares, mas sua dificuldade de mudança aparece na longa transição do Python 2 para o 3 e no pequeno número de implementações
Estou comentando tarde nesta thread, mas isso talvez não seja necessariamente uma coisa boa
As distribuições já têm dificuldade de usar
rustcou Go como pacotes da própria distro porque não conseguem acompanhar linguagens que lançam versões novas a cada poucos mesesHoje, surpreendentemente, há sistemas que removeram o GCC por ele não ser mais necessário e mantêm apenas Go e Rust upstream para atualizar softwares existentes
Alguns meses atrás, quando atualizei Go por causa de um CVE, foi um pesadelo ver que apps baseados em Go guardavam seus próprios ambientes Go em quatro lugares diferentes
Se quiser, o Linux já pode ser compilado com Clang e usar um toolchain inteiramente baseado em LLVM
Esse esforço duplicado de desenvolver e manter isso pela “pureza” GNU não parece valer a pena
A comunidade ClangBuiltLinux argumentou que o Linux não deveria depender de um único compilador, mas, quando Rust chegou, muitos dessas mesmas pessoas de repente passaram a achar que um único compilador tudo bem
Não se trata de prender o kernel exclusivamente ao GNU, mas apenas de permitir a escolha de um toolchain GNU puro