Un Workspace de Cargo es una característica diseñada para gestionar múltiples paquetes (crates) que forman parte de un mismo proyecto, permitiendo tratarlos como un único “monorepo”. En lugar de gestionar cada crate con su propio archivo de bloqueo y directorio de compilación, los workspaces agrupan los crates para que compartan un único archivo Cargo.lock y un único directorio target.
Esta arquitectura es fundamental cuando el proyecto crece. Se utiliza para separar la lógica de negocio (una librería) de la interfaz de usuario (un binario), para dividir herramientas auxiliares o para separar el código de pruebas de integración en crates especializados. Si se gestionan crates relacionados de forma aislada, se corre el riesgo de sufrir “conflictos de versiones de dependencias”, donde dos crates usan versiones distintas de la misma librería (por ejemplo, serde), aumentando el tiempo de compilación y el tamaño del binario final.
El uso de [workspace.dependencies] (introducido en Cargo 1.64) permite centralizar las versiones de las dependencias en la raíz, evitando que cada crate tenga que declarar manualmente la versión de una librería externa. De igual forma, [workspace.package] permite compartir metadatos como la versión del proyecto o el autor.
// NOTA: En un Workspace real, estos módulos residirían en archivos/directorios distintos.
// Este bloque simula la estructura de un workspace para ser compilable en un solo archivo.
// --- ESTRUCTURA SIMULADA DEL WORKSPACE ---
// /proyecto_raiz
// ├── Cargo.toml (Define el [workspace])
// ├── core_lib/ (Crate de librería)
// │ └── Cargo.toml (Depende de las dependencias del workspace)
// └── cli_app/ (Crate binario)
// └── Cargo.toml (Depende de core_lib mediante path)
// Simulación del módulo 'core_lib' (Crate de librería central)
mod core_lib {
/// Calcula el doble de un valor.
/// En un workspace, esta función sería pública para otros crates.
pub fn procesar_dato(valor: i32) -> i32 {
valor * 2
}
}
// Simulación del módulo 'cli_app' (Crate binario que consume la librería)
mod cli_app {
// En un workspace real, esta importación se haría mediante el nombre del crate:
// use core_lib;
use crate::core_lib;
pub fn ejecutar_comando() {
let entrada = 42;
let resultado = core_lib::procesar_dato(entrada);
println!("--- Ejecutando CLI ---");
println!("Entrada: {}, Resultado: {}", entrada, resultado);
}
}
// Punto de entrada principal
fn main() {
// El binario principal delega la ejecución al crate de la aplicación
cli_app::ejecutar_comando();
}
Análisis del código
mod core_lib: Representa un crate de tipo librería. En un monorepo real, este sería un directorio independiente con su propioCargo.toml. Contiene la lógica fundamental reutilizable.pub fn procesar_dato(valor: i32): Es una función pública dentro decore_lib. La palabra clavepubes esencial para que otros crates del workspace puedan acceder a ella.mod cli_app: Simula el crate binario. En un entorno real, suCargo.tomlincluiría una dependencia local mediante la ruta del directorio:core_lib = { path = "../core_lib" }.use crate::core_lib: Dentro del módulocli_app, simulamos la importación de la librería. En un workspace real, Cargo resolvería esto automáticamente mediante el nombre del paquete.cli_app::ejecutar_comando(): Llama a la función principal de la aplicación, la cual a su vez orquestra la lógica de la librería.fn main(): Es el punto de entrada del binario. En un workspace con múltiples binarios, estemainpertenecería al crate designado como ejecutable.
N° 77