La decisione
QuickRust è nato come uno strato sopra qualunque Cargo e rustup ci fossero su una macchina. Il 12 ottobre 2026 questo è cambiato: QuickRust è diventato l’unica cosa che uno sviluppatore installa. Le decisioni prese allora sono state:
- Possedere tutto tranne il motore. Il binario
cargodella toolchain resta il motore di build, come componente interno che nessuno ha bisogno di conoscere. QuickRust possiede la directory home, le toolchain, le directory di build, le installazioni, i download e l’output. I pezzi del motore stesso potranno essere sostituiti in seguito, uno alla volta, dove le misurazioni mostrino un guadagno. - Niente nel progetto. Nessuna
target/accanto ai sorgenti, nemmeno un collegamento simbolico. Gli strumenti trovano gli output della build nel modo in cui glielo indica Cargo:CARGO_TARGET_DIR,cargo metadata,qrust path. - Un taglio netto, con un’unica importazione. QuickRust non chiama mai rustup. Quando viene configurato, copia una sola volta da
~/.cargole credenziali e le impostazioni dei registry, dice che cosa ha importato e da quel momento usa solo le proprie. - Una cache che si gestisce da sola. Tutto ciò che QuickRust può ricompilare o scaricare di nuovo vive in un’unica cache, che resta entro una dimensione e lascia spazio libero sul disco, senza che l’utente debba mai eseguire un comando di pulizia.
Il motivo è che le funzionalità per cui QuickRust è costruito ne hanno bisogno. Una cache degli artefatti globale condivisa da ogni checkout, l’early cut-off tramite un driver del compilatore compilato per ciascuna toolchain, un verdetto “aggiornato” che dipende dal sapere quale release indica un canale: ognuna di queste cose è fragile quando è un altro programma a decidere quale compilatore viene eseguito, dove finiscono gli output e quando spariscono i download. Possedere l’ambiente trasforma queste incognite in fatti che QuickRust controlla.
Toolchain senza rustup
QuickRust legge gli stessi segnali che legge rustup, nell’ordine di rustup: +toolchain sulla riga di comando, RUSTUP_TOOLCHAIN (il nome che editor e strumenti già impostano), rust-toolchain.toml o rust-toolchain nella directory più vicina, e infine la toolchain predefinita. Mantenere i nomi e la precedenza di rustup significa che progetti esistenti, editor e script di CI non hanno bisogno di modifiche. Una toolchain viene scaricata dal server di distribuzione di Rust al primo utilizzo, con ogni manifest verificato rispetto al suo SHA-256 pubblicato e ogni archivio rispetto a quello del manifest, e installata in ~/.qrust/toolchains con i componenti e i target che il progetto richiede.
Possedere le toolchain permette anche a QuickRust di mantenere aggiornati i canali senza che nessuno debba eseguire un aggiornamento. Una volta al giorno, dopo una build che ha usato un canale come stable, un processo separato e a bassa priorità controlla il checksum di 64 byte del manifest del canale; quando è cambiato, la nuova release viene installata in background e il canale passa a quella per la build successiva, mai durante una build. Una release abbandonata da un canale viene rimossa quando nulla la indica più ed è passato un giorno senza che sia stata usata; una release richiesta con il suo nome, come 1.98.1, non viene mai rimossa da QuickRust. In CI non c’è mai aggiornamento automatico, perché un’esecuzione di CI deve usare ciò che le è stato detto di usare.
Ciò che si perde sono gli override per directory di rustup (rustup override set), che non hanno equivalente; un file di toolchain nel progetto svolge lo stesso compito e viaggia con il repository. Una toolchain compilata altrove, come un checkout locale di rustc, si aggiunge con qrust toolchain link.
Una Cargo home tutta sua
Ogni Cargo eseguito da QuickRust riceve CARGO_HOME=~/.qrust/cargo. L’indice del registry, i crate scaricati, i checkout git, le credenziali e la configurazione di Cargo stesso vivono lì, condivisi da tutti i progetti. Tenerla separata da ~/.cargo è ciò che rende reale il taglio netto: il Cargo di rustup e QuickRust non si contendono mai lo stesso lock dell’indice, e QuickRust può gestire la dimensione di quella directory senza sorprendere un altro strumento. L’importazione una tantum al momento della configurazione porta con sé ciò che gli utenti dovrebbero altrimenti rifare: le credenziali e le tabelle [registries], [registry], [source], [net] e [http]. Le altre tabelle restano dove sono e vengono segnalate come non importate, perché impostazioni come [build] appartengono ai progetti sotto quella directory, che Cargo continua a leggere da lì.
Directory di build fuori dal progetto
Cargo scrive ogni build di un workspace in <workspace>/target, ed è per questo che ogni progetto Rust su un disco si porta dietro gigabyte di output di build che nulla rimuove mai. QuickRust compila ogni workspace (quello indicato da cargo locate-project --workspace) in ~/.qrust/cache/builds/<name>-<id>/ e lo comunica a Cargo, e a ogni strumento eseguito sotto di esso, tramite CARGO_TARGET_DIR e CARGO_BUILD_BUILD_DIR. cargo metadata riporta poi quella directory, così gli strumenti che la chiedono, come fanno rust-analyzer, nextest e cargo llvm-cov, la trovano senza sapere che QuickRust esiste.
Mettere l’output di build nella cache invece che nel progetto ha diverse conseguenze su cui QuickRust fa affidamento. Le directory di build stanno sullo stesso file system della cache degli artefatti, quindi ripristinare un’unità può essere una copia economica, o un reflink sui file system che lo supportano. Sono usa e getta per progetto: la cache può rimuoverne una che non viene usata da un po’, e la build successiva la ricrea, con le sue dipendenze che tornano dalla cache degli artefatti. Un progetto spostato o cancellato lascia un orfano che la cache riconosce e rimuove per primo. Ogni worktree git è un workspace a sé e riceve la propria directory.
Una directory target che scegli tu è tua: --target-dir, --config build.target-dir=... sulla riga di comando, o CARGO_TARGET_DIR impostata nell’ambiente vengono usate così come sono, e QuickRust non le gestisce né le rimuove mai. build.target-dir in un file di configurazione di Cargo viene invece scavalcata. È una valutazione: un’impostazione in un file di configurazione è tipicamente un’abitudine consolidata, spesso valida per tutta la macchina e pensata per tenere target/ fuori dai progetti, cosa che QuickRust fa già; rispettarla riporterebbe l’output di ogni progetto in un unico posto non gestito, mentre una directory target indicata per un singolo comando è una scelta deliberata per quel comando.
Il costo ricade sugli script che scrivono in modo fisso ./target/debug/app. Devono invece chiederlo, con qrust path o cargo metadata; Come trovare gli output di build mostra come. Tornare al Cargo puro non ne risente: compila in target/ da zero, e i due non toccano mai gli artefatti l’uno dell’altro.
Una cache che si mantiene piccola da sola
Tutto il contenuto di ~/.qrust/cache può essere ricompilato o scaricato di nuovo: directory di build, cache degli artefatti, driver del compilatore, sorgenti dei programmi installati, download delle toolchain e risposte memorizzate. Viene mantenuto entro due limiti: cache.max-size, il massimo che usa (per impostazione predefinita il 10% del disco, tra 10 e 100 GiB), e cache.min-free, lo spazio libero che lascia sul disco (per impostazione predefinita il 5%, tra 2 e 20 GiB). Il secondo limite conta quanto il primo: una cache entro la propria dimensione è comunque un problema su un disco che qualcos’altro ha riempito.
Il controllo non costa quasi nulla: dopo un comando, QuickRust confronta lo spazio libero con il suo ultimo conteggio, al prezzo di una statvfs e della lettura di un piccolo file. Quando è il momento di una pulizia, questa viene eseguita in un processo separato con la priorità più bassa, così il comando che l’ha innescata non viene rallentato. Solo quando il disco è quasi pieno, sotto un quarto di cache.min-free, un comando fa pulizia prima di essere eseguito, per al massimo dieci secondi, e lo segnala.
Una pulizia rimuove le cose in un ordine che riflette quanto costa recuperarle:
- Prima, qualunque cosa nulla possa più usare, indipendentemente dallo spazio: directory di build di workspace che non esistono più, driver di toolchain che non ci sono più, download e risposte memorizzate non più validi, residui.
- Poi, finché la cache supera la propria dimensione o il disco scende sotto il suo spazio libero, ciò che si può ricompilare in locale: directory di build, voci degli artefatti e sorgenti dei programmi installati, a partire da quelli usati meno di recente.
- Infine, ciò che ha bisogno della rete per tornare: crate e checkout git nella Cargo home di QuickRust. Questi li rimuove Cargo stesso (
cargo -Zgc clean gc), perché sa quando ciascuno è stato usato l’ultima volta e attende le build che li stanno leggendo. QuickRust gli lascia applicare le sue soglie di età abituali a ogni pulizia e, solo finché i limiti sono ancora superati, ne chiede di progressivamente più brevi. Lo fa solo mentre non è in esecuzione alcun Cargo avviato da QuickRust. La pulizia di Cargo cancella anche i suoi record dei registri che non trova nella Cargo home, come quello temporaneo su cui compilacargo package, e un Cargo ancora in esecuzione con uno di quei record si ferma con un errore interno. Ogni processo di QuickRust che può eseguire un Cargo si registra prima, e la pulizia verifica che nessuno di quelli registrati sia in esecuzione. Altrimenti lascia i download alla pulizia successiva.
Una pulizia rimuove solo ciò che serve ai limiti: quanto manca, più un margine di un quarto di cache.min-free, che evita che la pulizia successiva segua subito dopo. Si basa sul proprio conto di ciò che ha liberato, non sullo spazio libero del disco, perché il disco potrebbe non mostrarlo. Uno snapshot conserva i blocchi di ogni file più vecchio di sé (Time Machine crea snapshot locali ogni ora e li conserva per un giorno; gli snapshot di btrfs e ZFS fanno lo stesso), e ciò che è stato usato meno di recente lo è sempre. Misurare il disco dopo ogni rimozione non mostrerebbe alcun progresso, e la pulizia andrebbe avanti finché non avesse rimosso tutto ciò che può. Invece, ciò che ha rimosso e che il disco non mostra ancora viene contato come libero finché il disco non lo mostra, per un giorno al massimo.
Alcune cose non vengono mai rimosse: tutto ciò che è stato usato negli ultimi 15 minuti, una directory di build prenotata da un comando di QuickRust o da una build di Cargo, un sorgente prenotato da un’installazione, e una voce degli artefatti i cui file sono ancora collegati da una directory di build in uso. La rimozione rinomina una directory spostandola da parte prima di cancellarla, così nessuna build ne vede mai una cancellata a metà, e ogni rimozione viene registrata nel log. Le dimensioni sono contate come blocchi allocati, con un file collegato tramite hard link contato una sola volta, così i numeri corrispondono a ciò che il disco perde e guadagna.
La stessa regola vale ovunque qui: QuickRust cancella solo dentro la propria cache, il cui contenuto ha creato lui. Non cancella mai in un progetto, in una directory target che hai scelto tu, o tra i file che possiedi nella sua Cargo home (sicurezza). La guida pratica sullo spazio su disco spiega come regolare i limiti e fare pulizia a mano.
Il motore, per ora
Possedere l’ambiente è una tappa, non la destinazione. Cargo resta il motore perché il suo resolver, il suo scheduler e i suoi fingerprint sono esattamente ciò che serve per la compatibilità, e non è lì che va la maggior parte del tempo di build. Con toolchain, posizioni degli output, cache e output sotto il controllo di QuickRust, un pezzo del motore può essere sostituito quando un benchmark mostra che ne vale la pena, senza che cambi nulla attorno.