Estructura Cargo
Cuando trabajamos con Rust, utilizamos Cargo como el sistema de gestión de paquetes y herramienta de construcción oficial. Cargo se encarga de muchas tareas esenciales como descargar dependencias, compilar el código y generar ejecutables.
Al crear un nuevo proyecto con Cargo, se genera automáticamente una estructura de directorios específica que sigue convenciones estándar. Esta organización facilita el desarrollo y mantenimiento de proyectos Rust.
Para crear un nuevo proyecto, abrimos una terminal y ejecutamos:
cargo new mi_proyecto
Este comando genera un nuevo directorio llamado mi_proyecto
con la siguiente estructura:
mi_proyecto/
├── Cargo.toml
└── src/
└── main.rs
Vamos a examinar cada elemento de esta estructura:
Directorio raíz del proyecto
El directorio raíz (en este caso mi_proyecto
) contiene todos los archivos y carpetas relacionados con nuestro proyecto. Este es el espacio de trabajo principal donde Cargo buscará la configuración y los archivos fuente.
Archivo Cargo.toml
El archivo Cargo.toml
es el manifiesto del proyecto y contiene la configuración y metadatos necesarios. TOML (Tom's Obvious, Minimal Language) es un formato de configuración simple y legible. Veamos un ejemplo básico:
[package]
name = "mi_proyecto"
version = "0.1.0"
edition = "2021"
[dependencies]
Las secciones principales son:
-
[package]: Contiene la información básica del proyecto:
-
name
: El nombre del proyecto -
version
: La versión actual siguiendo el formato de versionado semántico -
edition
: La edición de Rust que se utilizará (2015, 2018 o 2021) -
[dependencies]: Aquí se declaran las bibliotecas externas (crates) que nuestro proyecto utilizará. Inicialmente está vacía.
Directorio src/
El directorio src/
(source) es donde se almacena todo el código fuente de nuestro proyecto. Cargo espera encontrar aquí los archivos .rs
que contienen nuestro código Rust.
Archivo main.rs
Para un proyecto ejecutable (en contraposición a una biblioteca), Cargo crea automáticamente el archivo src/main.rs
. Este archivo contiene el punto de entrada de nuestro programa, la función main()
.
Otros archivos generados
Cuando compilamos nuestro proyecto, Cargo genera automáticamente algunos archivos y directorios adicionales:
-
target/: Directorio donde se almacenan los resultados de la compilación. Contiene:
-
Archivos objeto intermedios
-
Ejecutables finales
-
Documentación generada
-
Cargo.lock: Este archivo se genera automáticamente después de la primera compilación y registra las versiones exactas de todas las dependencias. Esto garantiza compilaciones reproducibles.
Estructura para proyectos más complejos
A medida que nuestro proyecto crece, podemos añadir más elementos a esta estructura básica:
- tests/: Directorio para pruebas de integración
- examples/: Ejemplos de uso de nuestra biblioteca
- benches/: Pruebas de rendimiento
- src/bin/: Múltiples ejecutables dentro del mismo proyecto
Para proyectos iniciales, la estructura básica es suficiente y nos permite concentrarnos en aprender el lenguaje sin preocuparnos por la organización de archivos.
Convenciones de nombres
Cargo sigue algunas convenciones importantes:
- Los nombres de proyectos usan guiones (
mi-proyecto
) enCargo.toml
- Los nombres de paquetes en el código Rust usan guiones bajos (
mi_proyecto
) - Los archivos de código usan snake_case (
mi_archivo.rs
)
Estas convenciones ayudan a mantener la consistencia entre proyectos Rust y facilitan la colaboración entre desarrolladores.
¿Te está gustando esta lección?
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
main.rs básico
Ahora que entendemos la estructura de un proyecto Rust, vamos a examinar el archivo main.rs
que Cargo ha generado automáticamente. Este archivo contiene el código inicial de nuestro programa y es el punto de partida para cualquier aplicación Rust.
Al abrir el archivo src/main.rs
con tu editor de código favorito, encontrarás el siguiente contenido:
fn main() {
println!("Hello, world!");
}
Aunque parece simple, este pequeño programa contiene varios elementos fundamentales de Rust que debemos entender:
Función main
La línea fn main() {
define la función principal de nuestro programa:
fn main() {
// Código de la función
}
fn
es la palabra clave que indica que estamos definiendo una funciónmain
es el nombre de la función - esta función específica es especial()
indica que la función no recibe parámetros{ }
son las llaves que delimitan el cuerpo de la función
La función main
es el punto de entrada de cualquier programa ejecutable en Rust. Cuando ejecutamos nuestro programa, el sistema operativo comienza la ejecución desde esta función. Sin una función main
, no tendríamos un programa ejecutable.
Instrucción println!
Dentro de la función main, encontramos esta línea:
println!("Hello, world!");
Esta instrucción muestra texto en la consola:
println!
es una macro de Rust (no una función normal)- Las macros en Rust se identifican por el signo de exclamación
!
"Hello, world!"
es una cadena de texto literal (string)- La instrucción termina con
;
(punto y coma), que marca el final de la expresión
¿Qué es una macro?
Las macros en Rust son diferentes de las funciones normales. Una macro es un tipo de código que escribe otro código (metaprogramación). No necesitas entender completamente las macros ahora, pero es importante saber que println!
es una macro que facilita la impresión de texto formateado en la consola.
Modificando nuestro primer programa
Podemos modificar este programa básico para que muestre un mensaje personalizado. Por ejemplo:
fn main() {
println!("¡Mi primer programa en Rust!");
}
También podemos añadir más llamadas a println!
para mostrar múltiples líneas:
fn main() {
println!("¡Mi primer programa en Rust!");
println!("Estoy aprendiendo un nuevo lenguaje.");
}
Imprimiendo valores variables
La macro println!
puede hacer más que simplemente imprimir texto estático. También puede formatear e imprimir valores:
fn main() {
let lenguaje = "Rust";
let año = 2023;
println!("Estoy aprendiendo {} en {}.", lenguaje, año);
}
En este ejemplo:
let lenguaje = "Rust";
crea una variable llamadalenguaje
con el valor "Rust"let año = 2023;
crea otra variable llamadaaño
con el valor numérico 2023- Las llaves
{}
dentro del string son marcadores de posición que serán reemplazados por los valores de las variables
Comentarios en Rust
Es una buena práctica añadir comentarios a tu código para explicar lo que hace. En Rust, los comentarios se escriben así:
fn main() {
// Esto es un comentario de una línea
/* Esto es un comentario
que abarca múltiples
líneas */
println!("¡Hola desde Rust!"); // Los comentarios pueden ir al final de una línea
}
Los comentarios son ignorados por el compilador y sirven como notas para los programadores.
Estructura básica completa
Juntando todo lo que hemos visto, un archivo main.rs
básico pero completo podría verse así:
// Mi primer programa en Rust
fn main() {
// Definimos algunas variables
let nombre = "Programador";
let lenguaje = "Rust";
// Imprimimos mensajes en la consola
println!("¡Hola, {}!", nombre);
println!("Bienvenido al mundo de {}.", lenguaje);
println!("Este es tu primer programa.");
}
Este programa muestra tres líneas de texto en la consola, incluyendo valores de variables. Es simple pero ilustra los conceptos básicos de un programa Rust.
Recuerda que cada instrucción en Rust termina con un punto y coma (;
), excepto cuando la última expresión de un bloque es el valor de retorno de ese bloque (algo que veremos más adelante).
Build y ejecución
Una vez que hemos creado nuestro proyecto y entendido la estructura básica del archivo main.rs
, el siguiente paso es compilar y ejecutar nuestro programa. Cargo nos proporciona varias herramientas para facilitar este proceso.
El ciclo de desarrollo en Rust
El ciclo de desarrollo típico en Rust sigue estos pasos:
- Escribir o modificar el código
- Comprobar que el código no tiene errores
- Compilar el código en un ejecutable
- Ejecutar el programa
- Repetir
Cargo nos ofrece comandos específicos para cada una de estas etapas, lo que simplifica enormemente nuestro flujo de trabajo.
Verificación del código con cargo check
Antes de compilar completamente nuestro programa, podemos usar cargo check
para verificar rápidamente si nuestro código tiene errores:
cargo check
Este comando analiza nuestro código sin generar un ejecutable, lo que lo hace mucho más rápido que una compilación completa. Es ideal para comprobar errores de sintaxis o problemas de tipado mientras estamos escribiendo código.
Si nuestro código no tiene errores, veremos un mensaje como:
Checking mi_proyecto v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Si hay errores, Cargo nos mostrará mensajes detallados indicando dónde están los problemas y sugerencias para solucionarlos.
Compilación con cargo build
Para compilar nuestro programa y generar un ejecutable, usamos:
cargo build
Este comando compila nuestro código y crea un ejecutable en el directorio target/debug/
. Por defecto, Cargo compila en modo de desarrollo, que incluye información de depuración pero no está optimizado para rendimiento.
Si la compilación es exitosa, veremos algo como:
Compiling mi_proyecto v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.72s
El ejecutable generado se encuentra en target/debug/mi_proyecto
(o target\debug\mi_proyecto.exe
en Windows).
Compilación para producción
Cuando nuestro programa está listo para ser distribuido, podemos compilarlo con optimizaciones usando la bandera --release
:
cargo build --release
Este comando genera un ejecutable optimizado en target/release/
que es más rápido pero tarda más en compilarse y no incluye información de depuración:
Compiling mi_proyecto v0.1.0
Finished release [optimized] target(s) in 1.21s
Ejecución del programa
Hay dos formas principales de ejecutar nuestro programa:
- Ejecutar directamente el archivo compilado:
# En sistemas Unix/Linux/macOS
./target/debug/mi_proyecto
# En Windows
.\target\debug\mi_proyecto.exe
- Usar el comando cargo run:
cargo run
El comando cargo run
es especialmente útil porque compila y ejecuta nuestro programa en un solo paso. Si el código ha cambiado desde la última compilación, Cargo lo recompilará automáticamente antes de ejecutarlo.
Si queremos ejecutar la versión optimizada:
cargo run --release
Ejemplo práctico
Veamos un ejemplo completo del flujo de trabajo:
- Modificamos nuestro programa en
src/main.rs
:
fn main() {
let mensaje = "¡Hola desde Rust!";
println!("{}", mensaje);
println!("Este es mi primer programa compilado y ejecutado.");
}
- Verificamos que no hay errores:
cargo check
- Compilamos y ejecutamos en un solo paso:
cargo run
Veremos una salida similar a esta:
Compiling mi_proyecto v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.42s
Running `target/debug/mi_proyecto`
¡Hola desde Rust!
Este es mi primer programa compilado y ejecutado.
Limpieza del proyecto
Con el tiempo, el directorio target/
puede crecer considerablemente. Para eliminar todos los archivos compilados y empezar desde cero:
cargo clean
Este comando elimina todo el directorio target/
, liberando espacio en disco.
Mensajes de error
Una de las características más destacadas de Rust es la calidad de sus mensajes de error. Si cometemos un error en nuestro código, Cargo nos proporcionará información detallada y útil.
Por ejemplo, si olvidamos un punto y coma:
fn main() {
let mensaje = "¡Hola desde Rust!" // Falta el punto y coma
println!("{}", mensaje);
}
Al ejecutar cargo check
o cargo build
, veremos un mensaje de error claro:
error: expected `;`, found `println`
--> src/main.rs:3:5
|
2 | let mensaje = "¡Hola desde Rust!"
| ^ help: add `;` here
3 | println!("{}", mensaje);
| ^^^^^^^ unexpected token
Estos mensajes no solo indican dónde está el error, sino que también sugieren cómo solucionarlo.
Resumen del flujo de trabajo
Para un desarrollo eficiente en Rust, podemos seguir este flujo de trabajo:
- Usar
cargo check
frecuentemente mientras escribimos código para detectar errores rápidamente - Usar
cargo run
para probar nuestro programa durante el desarrollo - Usar
cargo build --release
cuando estemos listos para crear la versión final optimizada
Este ciclo de desarrollo nos permite trabajar de manera eficiente y aprovechar al máximo las herramientas que Cargo nos proporciona.
Aprendizajes de esta lección
- Comprender la estructura básica de un proyecto Rust generado por Cargo.
- Identificar los archivos y directorios principales como Cargo.toml, src/main.rs y target/.
- Entender la función main y la macro println! para imprimir en consola.
- Aprender a compilar, verificar y ejecutar programas Rust usando comandos Cargo.
- Interpretar mensajes de error comunes y aplicar buenas prácticas como el uso de comentarios.
Completa Rust y certifícate
Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs