Adrianistán

El blog de Adrián Arroyo


Cargo y módulos en Rust

- Adrián Arroyo Calle

El software va creciendo poco a poco en un proyecto y es vital que esté bien organizado. Rust incluye un potente sistema de módulos para manejar estas situaciones y Cargo nos ayuda a gestionar las dependencias del proyecto.

Módulos


Los módulos se definen con la palabra reservada mod y por defecto todo es privado. Es necesario indicar pub para hacer esos campos públicos. Con use podemos acortar la manera con la que hacemos referencia a los componentes del módulo. Así pues, use es similar a using namespace de C++.


mod network{
pub fn version() -> String{
String::from("Network 1.0.0")
}
pub mod server{
fn private_thing(){

}
pub fn public_thing(){

}
}
}

fn main() {
println!("{}",network::version());
{
use network::server::public_thing;
public_thing();
}
}


Los módulos resultan una opción más interesante si tenemos múltiples archivos. Por norma general, si un módulo se define en el fichero de entrada del compilador, este se busca en dos sitios:

  • Un fichero nombre_del_modulo.rs

  • Un fichero nombre_del_modulo/mod.rs (opción recomendada para módulos de varios archivos)


Por lo que el código anterior puede sustituirse por esto en el fichero principal:


mod network;

fn main() {
println!("{}",network::version());
{
use network::server::public_thing;
public_thing();
}
}


Y esto en un fichero network.rs


pub fn version() -> String{
String::from("Network 1.0.0")
}
pub mod server{
fn private_thing(){

}
pub fn public_thing(){

}
}


Podemos usar use-as para modificar el nombre con el que se importa una función.


mod network;

fn main() {
println!("{}",network::version());
{
use network::server::public_thing as super_thing;
super_thing();
}
}


 

Crates


El código en Rust se organiza en crates, que son colecciones de módulos que se distribuyen. Piensa en ello como si fuesen gemas de Ruby o librerías de C++. Las crates se pueden compartir con la gente. El mayor repositorio de crates de la comunidad Rust es crates.io.

Las crates se pueden generar con rustc o con cargo, aunque es habitual usar la segunda opción. Vamos a ver primero como usaríamos una crate externa. En este caso voy a usar regex. Sé que en esta parte no vas a saber como descargar regex y usarla, pero voy a explicar el código.


extern crate regex;

use regex::Regex;

fn main() {
let r = Regex::new(r"([A-Za-z0-9])([.]|[_]|[A-Za-z0-9])+@gmail.com").unwrap();
if r.is_match("pucela_segunda@gmail.com") {
println!("Correo válido de Gmail");
}else{
println!("Correo no válido de Gmail");
}
}


Básicamente se usa extern crate para importar una crate externa, en este caso regex. Con use lo único que hacemos es acortar la manera de llamar a las funciones. Si no estuviese podríamos poner perfectamente regex::Regex::new en vez de Regex::new y funcionaría.

Cargo


Cargo es una herramienta que cumple dos funciones dentro del ecosistema Rust. Por un lado es un gestor de dependencias y por otro lado gestiona también las compilaciones.

En su parte de gestor de dependencias nos permite especificar que crates necesita el proyecto para compilar, su versión y si la crate lo soporta, con qué características activadas.

En su parte de gestor de compilaciones, realiza la compilación con rustc y añade las flags pertinentes al compilador. También se le pueden especificar cosas más complejas, aunque en Rust no suele ser habitual tener configuraciones de compilación excesivamente complejas.

Todo lo relativo a Cargo se define en el archivo Cargo.toml. Que tiene una estructura similar a esta:


[package]
name = "super_app"
version = "0.1.0"
authors = ["Adrián Arroyo Calle"]

[dependencies]
regex = "0.2.2"


En la sección dependencies puedes añadir línea por línea la crate que te haga falta. Consulta la documentación de cada crate para esto, pues puede haber variaciones.

Comandos básicos de Cargo


Crear un proyecto con Cargo


cargo new --bin mi_proyecto # si queremos que sea ejecutable

cargo new mi_crate # si queremos que sea una crate

Compilar y ejecutar


cargo run

cargo build # solo compilar

cargo build --release # compilar en modo Release

Cargo automáticamente se encarga de obtener las dependencias en la fase de compilación.

Instalar aplicaciones


cargo install APLICACION

Muchas herramientas de pueden distribuir a través de Cargo. Por ejemplo, Racer, un programa que sirve de autocompletado para IDEs como Eclipse o Visual Studio.

Ejecutar tests


cargo test

Generar documentación


cargo doc

Plugins de Cargo


Cargo es extensible gracias a plugins. Algunos interesantes son Clippy, cargo-audit, rustfmt, ...

Comentarios

Añadir comentario

Todos los comentarios están sujetos a moderación