Introdução ao Cargo: O Coração do Rust
Cargo é o gerenciador de pacotes e sistema de build oficial do Rust, responsável por compilar código, gerenciar dependências, executar testes e publicar bibliotecas. Se você vem de linguagens como Python (pip) ou JavaScript (npm), Cargo funciona de forma similar, mas com integração profunda na toolchain do Rust. Nesta aula, você aprenderá desde conceitos fundamentais até práticas avançadas que o tornarão capaz de gerenciar projetos profissionais com confiança.
Estrutura do Projeto e Configuração Básica
Criando um Projeto
Todo projeto Rust começa com Cargo. Use cargo new para gerar a estrutura padrão:
cargo new meu_projeto
cd meu_projeto
Isso cria uma estrutura como:
meu_projeto/
├── Cargo.toml # Manifesto do projeto
├── Cargo.lock # Lock file (gerado automaticamente)
└── src/
└── main.rs # Ponto de entrada
O Arquivo Cargo.toml
O Cargo.toml é um arquivo TOML que define metadados e dependências. Aqui está um exemplo real:
[package]
name = "meu_projeto"
version = "0.1.0"
edition = "2021"
authors = ["seu_nome <seu_email@example.com>"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.35", features = ["full"] }
reqwest = "0.11"
[dev-dependencies]
criterion = "0.5"
[[bin]]
name = "app"
path = "src/main.rs"
[profile.release]
opt-level = 3
lto = true
Cada dependência pode especificar versão, features (características opcionais) e fonte personalizada. O Cargo.lock garante reprodutibilidade, fixando versões exatas usadas na última compilação bem-sucedida.
Gerenciamento de Dependências
Adicionando e Atualizando Dependências
Use cargo add para instalar pacotes diretamente:
cargo add serde --features derive
cargo add tokio --features full
Ou edite Cargo.toml manualmente. Para atualizar, execute:
cargo update # Atualiza respeitando Cargo.toml
cargo update serde --precise 1.0.200 # Versão específica
Entendendo Versionamento Semântico
Rust segue semver (Semantic Versioning). Na especificação "1.2.3":
"1.2.3"— exatamente esta versão"^1.2.3"— compatível (1.2.3 até <2.0.0)"~1.2"— patch flexível (1.2.x até <1.3.0)"*"— qualquer versão (evite em produção)
Exemplo prático em Cargo.toml:
[dependencies]
serde = "1.0" # ^1.0 implícito
log = "~0.4" # 0.4.x apenas
uuid = { version = "1.0", optional = true }
[features]
with_uuid = ["uuid"] # Feature que ativa uuid
Sistema de Build e Compilação
Perfis de Compilação
Cargo fornece perfis pré-configurados para diferentes cenários:
cargo build # Debug (padrão, desenvolvimento)
cargo build --release # Release (otimizado, produção)
cargo build --profile custom # Perfil customizado
O exemplo abaixo mostra um Cargo.toml com perfis personalizados:
[profile.dev]
opt-level = 0 # Sem otimizações
debug = true # Informações de debug
[profile.release]
opt-level = 3 # Máxima otimização
lto = true # Link Time Optimization
codegen-units = 1 # Otimização agressiva (compilação mais lenta)
strip = true # Remove símbolos de debug
[profile.bench]
inherits = "release" # Herda configurações de release
Compilando e Executando
cargo build --release # Compila em release
cargo run # Compila (se necessário) e executa
cargo run --release -- arg1 arg2 # Executa com argumentos
cargo check # Verifica sem gerar binário
Testes, Documentação e Publicação
Executando Testes
cargo test # Executa todos os testes
cargo test --release # Em modo release
cargo test -- --nocapture # Mostra println! durante testes
Exemplo de teste em Rust:
// src/lib.rs
pub fn soma(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testa_soma() {
assert_eq!(soma(2, 2), 4);
}
#[test]
#[should_panic]
fn testa_panic() {
panic!("Esta função deve falhar");
}
}
Documentação
Gere documentação automática com comentários ///:
/// Calcula a soma de dois números.
///
/// # Exemplos
///
/// ```
/// let resultado = soma(2, 3);
/// assert_eq!(resultado, 5);
/// ```
pub fn soma(a: i32, b: i32) -> i32 {
a + b
}
cargo doc --open # Gera e abre documentação no navegador
Publicando no crates.io
Para publicar sua biblioteca em https://crates.io, registre-se e obtenha um token. Depois:
cargo login <seu_token>
cargo publish
Seu Cargo.toml deve incluir descrição e licença:
[package]
name = "minha_lib"
version = "0.1.0"
description = "Uma biblioteca incrível"
license = "MIT"
repository = "https://github.com/usuario/minha_lib"
Conclusão
Dominado Cargo, você controla toda a ciclo de vida de projetos Rust: desde a criação até publicação. Os três pilares essenciais são: (1) Cargo.toml como fonte única de verdade sobre dependências e configuração, (2) gerenciamento de versões usando semver para evitar conflitos, e (3) perfis de build para otimizar conforme o contexto (desenvolvimento vs. produção). Pratique criando projetos pequenos e publique uma biblioteca para solidificar o aprendizado.