Feature Flags em Rust: Configuração Flexível sem Recompilação

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Feature Flags em Rust: a arma secreta para desenvolvimento flexível

\n\n

Imagine que você está escrevendo uma biblioteca para processamento de imagens. Uns usuários querem apenas redimensionamento básico, outros querem correção de cor avançada, e outros ainda querem integração com redes neurais. Como deixar todos felizes, sem inflar o código e sem criar dezenas de versões? A resposta é simples — feature flags (ou feature toggles).

\n\n

No mundo Rust, essa técnica se transforma em uma verdadeira arte. Graças ao poderoso sistema de macros e compilação condicional, você pode criar aplicações modulares e configuráveis que se adaptam a qualquer cenário. E sim, você não precisará recompilar o projeto inteiro por causa de uma pequena funcionalidade.

\n\n

Neste artigo, vamos explorar como funcionam os feature flags em Rust, mostrar suas vantagens com exemplos reais e dar dicas práticas. Vamos lá!

\n\n

O que são feature flags e para que servem?

\n\n

Feature flags (ou compilação condicional) é um mecanismo que permite ativar ou desativar partes específicas do código durante a compilação. Em Rust, isso é implementado através do sistema features no Cargo.toml e das diretivas #[cfg(feature = "...")].

\n\n

Para que serve? Aqui estão três cenários principais:

\n\n
    \n
  • Modularidade de bibliotecas — o usuário decide quais funcionalidades precisa.
  • \n
  • Funcionalidades experimentais — permite testar novas funcionalidades sem risco para produção.
  • \n
  • Dependência de plataforma — código diferente para Windows, Linux e macOS.
  • \n
\n\n

Ao contrário dos flags em tempo de execução (que são verificados durante a execução), as Cargo features funcionam em tempo de compilação. Isso significa que o código não utilizado nem entra no binário — você obtém desempenho máximo e tamanho mínimo.

\n\n

Como funcionam os feature flags em Rust: sintaxe básica

\n\n

Vamos direto ao código. Suponha que estamos escrevendo uma biblioteca image_tools com suporte opcional a WebP.

\n\n

Primeiro, definimos a feature no Cargo.toml:

\n\n
[package]\nname = "image_tools"\nversion = "0.1.0"\n\n[features]\ndefault = ["png"]\npng = []\nwebp = []\n
\n\n

Agora, no código, usamos o atributo #[cfg]:

\n\n
// src/lib.rs\n\n#[cfg(feature = "png")]\npub mod png_processor;\n\n#[cfg(feature = "webp")]\npub mod webp_processor;\n\npub mod common;\n\n// Dentro do módulo:\n#[cfg(feature = "webp")]\npub fn encode_webp(data: &[u8]) -> Vec<u8> {\n    // implementação para WebP\n    println!("Codificando WebP...");\n    data.to_vec()\n}\n\n#[cfg(not(feature = "webp"))]\npub fn encode_webp(data: &[u8]) -> Vec<u8> {\n    panic!("Suporte a WebP não ativado. Ative a feature 'webp'.");\n}\n
\n\n

Observe o truque inteligente: fornecemos um placeholder para o caso de a feature estar desativada. Isso permite manter a API unificada, mas ao tentar usar uma função não suportada — obter um erro claro.

\n\n

Técnicas avançadas: combinações e dependências

\n\n

Feature flags em Rust permitem criar hierarquias complexas. Por exemplo, você pode criar uma feature "full" que ativa várias de uma vez:

\n\n
[features]\ndefault = ["basic"]\nbasic = ["resize", "crop"]\nadvanced = ["color_correction", "filters"]\nfull = ["basic", "advanced", "webp"]\n
\n\n

E também é possível especificar dependências de crates externos:

\n\n
[features]\nwebp = ["dep:libwebp-sys"]  # inclui dependência do sistema\n\n[dependencies]\nlibwebp-sys = { version = "0.1", optional = true }\n
\n\n

Aqui, optional = true informa ao Cargo que o crate só é incluído quando a feature correspondente é ativada. Isso economiza tempo de compilação e espaço em disco.

\n\n

Feature flags em um projeto real: exemplo de servidor HTTP

\n\n

Vamos imaginar que estamos escrevendo um mini-framework p

Blogs

Book Recommendations