Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Cargo: il package manager di Rust

Cargo: cos'è e come funziona il package manager di Rust, uno strumento fondamentale quando dobbiamo gestire le dipendenze del nostro progetto
Cargo: cos'è e come funziona il package manager di Rust, uno strumento fondamentale quando dobbiamo gestire le dipendenze del nostro progetto
Link copiato negli appunti

A questo punto, dopo aver trattato librerie e moduli, è arrivato il momento di conoscere uno dei tool di uso più quotidiano per lo sviluppatore Rust: cargo, il package manager.

Abbiamo preferito ritardare la presentazione di questo approccio in modo da guadagnare un po' di esperienza con il linguaggio sebbene avremmo potuto fare uso di cargo sin dall'inizio. Tuttavia, considerando che non necessitavamo di librerie da integrare ma solo di normale compilazione dei nostri esempi ed esercizi abbiamo preferito rivolgerci al compilatore in sé stesso ovvero rustc.

Cosa fa esattamente cargo?

Il fatto che cargo sia il principale package manager di Rust significa che questo strumento svolge tutti i principali ruoli per la cura di un progetto tra cui:

  • inizializzazione che definirà il progetto in sé come un insieme di codici, risorse, configurazioni, tutte racchiuse in una gerarchia ben strutturata di cartelle, da trattare come un'unica unità che rappresenterà il nostro progetto Rust;
  • compilazione dei sorgenti per fare in modo che, in maniera organizzata e ben congegnata tra librerie, main e funzionalità varie, l'insieme di codice che abbiamo scritto diventi un eseguibile;
  • preparazione alla distribuzione visto che, in genere, il programma che sviluppiamo non sarà destinato alla produzione sulla macchina in cui l'abbiamo creato ma sarà destinato ad un deployment ovvero ad essere distribuito in qualche forma;
  • gestione delle dipendenze, aspetto sul quale torneremo presto.

Dipendenze

Il tool cargo diventa uno strumento fondamentale soprattutto quando dobbiamo gestire le dipendenze del nostro progetto ovvero quando questo, per funzionare, necessita di funzionalità messe a disposizione da altre librerie. Ciò, come si apprenderà presto, capita molto comunemente per lavorare in rete, accedere a database, codificare/decodificare dati e, in generale, per gestire funzionalità non di base senza "reinventare la ruota". Gestire le dipendenze comporta una serie di problematiche:

  • ogni dipendenza risolve problematiche complesse quindi è costituita da un progetto a sé stante, voluminoso ed in continua evoluzione;
  • ogni dipendenza spesso non nasce da zero ma si fonda sulle "proprie" dipendenze;
  • le dipendenze (nonché le dipendenze delle dipendenze a cascata) vanno raccordate tra loro e con il progetto scegliendone bene le versioni da adottare;
  • non solo negli ambienti di sviluppo e test ma soprattutto in quelli di produzione ci vorrebbe un modo comodo per poter installare ed eventualmente aggiornare tutto l'ecosistema delle dipedenze senza incorrere in errori.

Per tutto questo ed altro ancora, cargo facilita il lavoro richiedendo essenzialmente di saper utilizzare i suoi comandi e scrivere un file di configurazione, testuale, caratterizzato dall'estensione .toml.

Un progetto con cargo

Per iniziare a lavorare con questo tool lo dobbiamo avere innanzitutto a disposizione. Tipicamente, ci verrà già fornito usando lo script rustup per la preparazione dell'ambiente di sviluppo altrimenti potremo procedere con la sua installazione indipendente via sorgenti.

Una volta pronti, creeremo il nostro primo progetto con:

$ cargo new mioprogetto

Dove mioprogetto è il nome che vorremo assegnare al progetto e che, presumibilmente, sarà personalizzato di volta in volta secondo i propri gusti.

Il risultato dell'operazione sarà, per lo più, composto da due elementi. Il primo è una cartella di nome src contenente un tipico programma in stile Hello world, di nome main.rs contenente quanto segue:

fn main() {
    println!("Hello, world!");
}

Il secondo è un file di nome Cargo.toml costituito da una configurazione suddivisa in più sezioni (ogni sezione inizia con una sorta di etichetta tra parentesi quadre) di cui la prima, package, contiene informazioni generiche sul progetto e la seconda, dependencies, inizialmente vuota, sarà lo spazio che potremo dedicare alle dipendenze:

[package]
name = "mioprogetto"
version = "0.1.0"
authors = ["tom"]
[dependencies]

Compilazione di un progetto

Eseguiamo la nostra prima compilazione modificando, tanto per personalizzarla, il codice Rust come segue:

fn main() {
    println!("Il nostro primo esperimento con cargo!");
}

Per la compilazione esistono due modalità. La prima è la modalità debug, avviabile con il comando:

$ cargo build

che ci farà ottenere come risultato una sottocartella target/debug con all'interno un eseguibile denominato come il nostro progetto (mioprogetto nel nostro caso). Potremo eseguirlo direttamente o invocando:

$ cargo run
Il nostro primo esperimento con cargo!

Per eseguire invece una compilazione nella seconda modalità, release, faremo:

$ cargo build --release

ottenendo la cartella target/release con all'interno un eseguibile ancora con lo stesso nome del progetto. Anche in questo caso potremo avviarne l'esecuzione con:

$ cargo run --release
Il nostro primo esperimento con cargo!

La differenza tra le due modalità può essere intuita dai loro nomi. La modalità release genera un eseguibile finale, pronto per il rilascio, di dimensioni minori e ottimizzato. Questa sarà da preferire per la distribuzione del software. La modalità di debug sarà destinata alla preparazione di un eseguibile di sperimentazione per una versione non definitiva, dotata ancora di una certa quantità di "metadati" per essere ispezionata alla ricerca di bug.

Ti consigliamo anche