Monorepositorio con Rust: organización de código para principiantes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿Por qué necesitas un monorepositorio en Rust?



Cuando empiezas a aprender Rust, lo primero con lo que te encuentras es un proyecto individual creado con cargo new. Pero, ¿qué hacer cuando tu proyecto crece: aparecen librerías compartidas, varios archivos ejecutables (por ejemplo, un servidor y un cliente) o quieres extraer código repetitivo en un paquete separado?



Aquí es donde entra en juego el monorepositorio (monorepo) — un enfoque en el que el código de varios proyectos interrelacionados (librerías y archivos ejecutables) se almacena en un solo repositorio. Rust proporciona una solución integrada para esto: Cargo Workspaces (espacios de trabajo).



En este artículo, analizaremos cómo organizar un monorepositorio en Rust desde cero: desde la estructura de carpetas hasta ejemplos prácticos. Aprenderás cómo dividir correctamente el código en módulos, conectar dependencias locales y gestionar la compilación.



1. ¿Qué es un Cargo Workspace y cómo crearlo?



Un espacio de trabajo (workspace) es un conjunto de crates que utilizan el mismo archivo Cargo.lock y un directorio target compartido. Esto permite evitar conflictos de versiones de dependencias y acelera la compilación.



Creación de la estructura del monorepositorio



Creemos un monorepositorio simple con dos crates: una librería utils y un archivo ejecutable app.



mkdir my_monorepocd my_monorepocargo new utils --libcargo new app


Ahora creemos el archivo raíz Cargo.toml que declarará el workspace:



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


Importante: Asegúrate de que en los archivos utils/Cargo.toml y app/Cargo.toml no haya una sección [package] con el campo workspace — no es necesaria. Cargo entenderá por sí mismo que son parte del workspace.



Estructura del proyecto



Después de la creación, obtendrás una estructura como esta:



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


2. Organización del código: librerías y módulos



Ahora agreguemos código a la librería utils. Supongamos que queremos crear funciones comunes para trabajar con números y cadenas.



Código de la librería (utils/src/lib.rs)



pub mod math;pub mod strings;


Creemos los archivos de los 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!("¡Hola, {}!", name)}

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


Conexión de la librería en el archivo ejecutable



En el archivo app/Cargo.toml indicaremos la dependencia del crate local:



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

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


Ahora en app/src/main.rs podemos usar las funciones 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);}


Ejecuta el proyecto desde la raíz del monorepositorio con el comando:



cargo run -p app


Verás la salida:



5 + 10 = 15¡Hola, Mundo!RUST ROCKS


3. Organización avanzada: múltiples archivos ejecutables



A menudo en un monorepositorio es necesario tener varios

Blogs

Book Recommendations