Monorepositório com Rust: organização de código para iniciantes

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

Introdução: Por que um monorepositório em Rust?



Quando você começa a aprender Rust, a primeira coisa que encontra é um projeto único, criado com cargo new. Mas o que fazer quando seu projeto cresce: surgem bibliotecas compartilhadas, vários arquivos executáveis (por exemplo, servidor e cliente) ou você deseja extrair código repetitivo para um pacote separado?



É aí que entra o monorepositório (monorepo) — uma abordagem onde o código de vários projetos inter-relacionados (bibliotecas e executáveis) é armazenado em um único repositório. O Rust fornece uma solução integrada para isso: Cargo Workspaces (espaços de trabalho).



Neste artigo, vamos explorar como organizar um monorepositório em Rust do zero: desde a estrutura de pastas até exemplos práticos. Você aprenderá como dividir corretamente o código em módulos, conectar dependências locais e gerenciar a compilação.



1. O que é um Cargo Workspace e como criá-lo?



Um workspace (espaço de trabalho) é um conjunto de crates que compartilham o mesmo arquivo Cargo.lock e o diretório target comum. Isso evita conflitos de versão de dependências e acelera a compilação.



Criando a estrutura do monorepositório



Vamos criar um monorepositório simples com dois crates: uma biblioteca utils e um arquivo executável app.



mkdir my_monorepocd my_monorepocargo new utils --libcargo new app


Agora, crie o arquivo raiz Cargo.toml que declarará o workspace:



[workspace]members = [    "utils",    "app",]


Importante: Certifique-se de que nos arquivos utils/Cargo.toml e app/Cargo.toml não haja uma seção [package] com o campo workspace — ela não é necessária. O Cargo entenderá automaticamente que fazem parte do workspace.



Estrutura do projeto



Após a criação, você terá a seguinte estrutura:



my_monorepo/├── Cargo.toml          # workspace raiz├── utils/│   ├── Cargo.toml│   └── src/│       └── lib.rs└── app/    ├── Cargo.toml    └── src/        └── main.rs


2. Organização do código: bibliotecas e módulos



Agora, vamos adicionar código à biblioteca utils. Suponha que queremos criar funções comuns para trabalhar com números e strings.



Código da biblioteca (utils/src/lib.rs)



pub mod math;pub mod strings;


Crie os arquivos dos módulos:



// utils/src/math.rspub fn add(a: i32, b: i32) -> i32 {    a + b}

pub fn multiply(a: i32, b: i32) -> i32 { a * b}


// utils/src/strings.rspub fn greet(name: &str) -> String {    format!("Olá, {}!", name)}

pub fn to_uppercase(text: &str) -> String { text.to_uppercase()}


Conectando a biblioteca no arquivo executável



No arquivo app/Cargo.toml, especifique a dependência do crate local:



[package]name = "app"version = "0.1.0"edition = "2021"

[dependencies]utils = { path = "../utils" }


Agora, em app/src/main.rs, podemos usar as funções de utils:



use utils::math;use utils::strings;

fn main() { let sum = math::add(5, 10); println!("5 + 10 = {}", sum);

let greeting = strings::greet("Mundo"); println!("{}", greeting);

let upper = strings::to_uppercase("rust rocks"); println!("{}", upper);}


Execute o projeto a partir da raiz do monorepositório com o comando:



cargo run -p app


Você verá a saída:



5 + 10 = 15Olá, Mundo!RUST ROCKS


3. Organização avançada: múltiplos arquivos executáveis



Frequentemente, em um monorepositório, é necessário ter vários

Blogs

Book Recommendations