Witaj, Cargo!
Cargo to system budowania i menedżer pakietów Rusta. Większość Rustaceanów używa tego narzędzia do zarządzania swoimi projektami w Ruście, ponieważ Cargo obsługuje wiele zadań za Ciebie, takich jak budowanie kodu, pobieranie bibliotek, od których zależy Twój kod, i budowanie tych bibliotek. (Biblioteki, których potrzebuje Twój kod, nazywamy zależnościami.)
Najprostsze programy w Ruście, takie jak ten, który do tej pory napisaliśmy, nie mają żadnych zależności. Gdybyśmy zbudowali projekt „Witaj, świecie!” za pomocą Cargo, używałby on tylko części Cargo, która obsługuje budowanie kodu. W miarę pisania bardziej złożonych programów w Ruście, będziesz dodawać zależności, a jeśli rozpoczniesz projekt za pomocą Cargo, dodawanie zależności będzie znacznie łatwiejsze.
Ponieważ zdecydowana większość projektów w Ruście używa Cargo, reszta tej książki zakłada, że Ty również używasz Cargo. Cargo jest instalowane wraz z Rustem, jeśli użyłeś oficjalnych instalatorów omówionych w sekcji „Instalacja”. Jeśli zainstalowałeś Rusta innymi sposobami, sprawdź, czy Cargo jest zainstalowane, wpisując w terminalu:
$ cargo --version
Jeśli widzisz numer wersji, masz go! Jeśli widzisz błąd, taki jak command not found, poszukaj w dokumentacji swojej metody instalacji, aby ustalić, jak
zainstalować Cargo oddzielnie.
Tworzenie projektu za pomocą Cargo
Utwórzmy nowy projekt za pomocą Cargo i przyjrzyjmy się, jak różni się od naszego oryginalnego projektu „Witaj, świecie!”. Wróć do katalogu projects (lub gdziekolwiek zdecydowałeś się przechowywać swój kod). Następnie, na każdym systemie operacyjnym, uruchom:
$ cargo new hello_cargo
$ cd hello_cargo
Pierwsze polecenie tworzy nowy katalog i projekt o nazwie hello_cargo. Nazwaliśmy nasz projekt hello_cargo, a Cargo tworzy swoje pliki w katalogu o tej samej nazwie.
Przejdź do katalogu hello_cargo i wypisz pliki. Zobaczysz, że Cargo wygenerowało dla nas dwa pliki i jeden katalog: plik Cargo.toml i katalog src z plikiem main.rs w środku.
Zainicjowało również nowe repozytorium Git wraz z plikiem .gitignore.
Pliki Git nie zostaną wygenerowane, jeśli uruchomisz cargo new w istniejącym
repozytorium Git; możesz nadpisać to zachowanie, używając cargo new --vcs=git.
Uwaga: Git to popularny system kontroli wersji. Możesz zmienić
cargo new, aby używać innego systemu kontroli wersji lub żadnego, używając flagi--vcs. Uruchomcargo new --help, aby zobaczyć dostępne opcje.
Otwórz Cargo.toml w swoim ulubionym edytorze tekstu. Powinien wyglądać podobnie do kodu z Listingu 1-2.
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"
[dependencies]
Ten plik jest w formacie TOML (Tom’s Obvious, Minimal Language), który jest formatem konfiguracyjnym Cargo.
Pierwszy wiersz, [package], to nagłówek sekcji wskazujący, że następne
instrukcje konfigurują pakiet. W miarę dodawania kolejnych informacji do tego
pliku, będziemy dodawać inne sekcje.
Trzy następne wiersze ustawiają informacje konfiguracyjne, których Cargo
potrzebuje do skompilowania programu: nazwę, wersję i wydanie Rusta do
użycia. Omówimy klucz edition w Dodatku E.
Ostatni wiersz, [dependencies], to początek sekcji, w której możesz wymienić
wszystkie zależności swojego projektu. W Ruście pakiety kodu są nazywane
skrzynkami. Nie będziemy potrzebować żadnych innych skrzynek do tego projektu,
ale będziemy potrzebować ich w pierwszym projekcie w Rozdziale 2, więc
skorzystamy z tej sekcji zależności wtedy.
Teraz otwórz src/main.rs i przyjrzyj się:
Nazwa pliku: src/main.rs
fn main() {
println!("Hello, world!");
}
Cargo wygenerowało dla Ciebie program „Witaj, świecie!”, dokładnie taki jak ten, który napisaliśmy w Listingu 1-1! Do tej pory różnice między naszym projektem a projektem wygenerowanym przez Cargo polegały na tym, że Cargo umieściło kod w katalogu src, a my mamy plik konfiguracyjny Cargo.toml w najwyższym katalogu.
Cargo oczekuje, że Twoje pliki źródłowe będą znajdować się w katalogu src. Katalog projektu najwyższego poziomu jest przeznaczony tylko na pliki README, informacje licencyjne, pliki konfiguracyjne i wszystko inne, co nie jest związane z Twoim kodem. Korzystanie z Cargo pomaga w organizacji projektów. Wszystko ma swoje miejsce i wszystko jest na swoim miejscu.
Jeśli rozpocząłeś projekt, który nie używa Cargo, tak jak to zrobiliśmy z
projektem „Witaj, świecie!”, możesz przekonwertować go na projekt, który używa
Cargo. Przenieś kod projektu do katalogu src i utwórz odpowiedni plik
Cargo.toml. Łatwym sposobem na uzyskanie pliku Cargo.toml jest uruchomienie
cargo init, które utworzy go dla Ciebie automatycznie.
Budowanie i uruchamianie projektu Cargo
Teraz przyjrzyjmy się, co się zmieni, gdy zbudujemy i uruchomimy program „Witaj, świecie!” za pomocą Cargo! Z katalogu hello_cargo zbuduj swój projekt, wypisując następujące polecenie:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
To polecenie tworzy plik wykonywalny w target/debug/hello_cargo (lub target\debug\hello_cargo.exe na Windows), a nie w bieżącym katalogu. Ponieważ domyślna kompilacja jest kompilacją debugową, Cargo umieszcza plik binarny w katalogu o nazwie debug. Możesz uruchomić plik wykonywalny za pomocą tego polecenia:
$ ./target/debug/hello_cargo # lub .\target\debug\hello_cargo.exe na Windows
Hello, world!
Jeśli wszystko pójdzie dobrze, w terminalu powinno zostać wyświetlone
Witaj, świecie!. Uruchomienie cargo build po raz pierwszy powoduje również,
że Cargo tworzy nowy plik na najwyższym poziomie: Cargo.lock. Ten plik śledzi
dokładne wersje zależności w Twoim projekcie. Ten projekt nie ma zależności,
więc plik jest nieco skąpy. Nigdy nie będziesz musiał ręcznie zmieniać tego
pliku; Cargo zarządza jego zawartością za Ciebie.
Właśnie zbudowaliśmy projekt za pomocą cargo build i uruchomiliśmy go za
pomocą ./target/debug/hello_cargo, ale możemy również użyć cargo run,
aby skompilować kod, a następnie uruchomić wynikowy plik wykonywalny za
jednym poleceniem:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
Używanie cargo run jest wygodniejsze niż konieczność pamiętania o
uruchamianiu cargo build, a następnie używaniu pełnej ścieżki do pliku
binearnego, więc większość deweloperów używa cargo run.
Zauważ, że tym razem nie widzieliśmy wyjścia wskazującego, że Cargo kompiluje
hello_cargo. Cargo ustaliło, że pliki nie uległy zmianie, więc nie
przebudowywało, a jedynie uruchomiło plik binarny. Gdybyś zmodyfikował swój kod
źródłowy, Cargo przebudowałoby projekt przed jego uruchomieniem, a Ty
zobaczyłbyś takie wyjście:
$ cargo run
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
Running `target/debug/hello_cargo`
Hello, world!
Cargo udostępnia również polecenie cargo check. To polecenie szybko
sprawdza Twój kod, aby upewnić się, że kompiluje się, ale nie tworzy pliku
wykonywalnego:
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
Dlaczego nie chciałbyś pliku wykonywalnego? Często cargo check jest
zauważalnie szybsze niż cargo build, ponieważ pomija krok tworzenia pliku
wykonywalnego. Jeśli stale sprawdzasz swoją pracę podczas pisania kodu,
użycie cargo check przyspieszy proces informowania Cię, czy Twój projekt
nadal się kompiluje! W związku z tym wielu Rustaceanów uruchamia cargo check
periodycznie podczas pisania programu, aby upewnić się, że się kompiluje.
Następnie uruchamiają cargo build, gdy są gotowi do użycia pliku
wykonywalnego.
Podsumujmy, czego do tej pory nauczyliśmy się o Cargo:
- Możemy utworzyć projekt za pomocą
cargo new. - Możemy zbudować projekt za pomocą
cargo build. - Możemy zbudować i uruchomić projekt w jednym kroku za pomocą
cargo run. - Możemy zbudować projekt bez tworzenia pliku binarnego, aby sprawdzić błędy,
za pomocą
cargo check. - Zamiast zapisywać wynik kompilacji w tym samym katalogu co nasz kod, Cargo przechowuje go w katalogu target/debug.
Dodatkową zaletą używania Cargo jest to, że polecenia są takie same, niezależnie od systemu operacyjnego, na którym pracujesz. Tak więc, w tym momencie nie będziemy już podawać konkretnych instrukcji dla Linuksa i macOS w stosunku do Windows.
Budowanie do wersji produkcyjnej
Kiedy Twój projekt jest wreszcie gotowy do wydania, możesz użyć cargo build --release, aby skompilować go z optymalizacjami. To polecenie utworzy plik
wykonywalny w target/release zamiast target/debug. Optymalizacje sprawiają,
że kod Rusta działa szybciej, ale ich włączenie wydłuża czas kompilacji
programu. Dlatego istnieją dwa różne profile: jeden do rozwoju, gdy chcesz
szybko i często przebudowywać, a drugi do budowania ostatecznego programu,
który przekażesz użytkownikowi, który nie będzie wielokrotnie przebudowywany i
który będzie działał tak szybko, jak to możliwe. Jeśli mierzysz czas
uruchamiania kodu, upewnij się, że uruchamiasz cargo build --release i
mierzysz wydajność z plikiem wykonywalnym w target/release.
Wykorzystanie konwencji Cargo
W przypadku prostych projektów Cargo nie zapewnia dużej wartości w porównaniu
z samym używaniem rustc, ale udowodni swoją wartość, gdy Twoje programy
staną się bardziej złożone. Gdy programy rozrosną się do wielu plików lub
będą wymagały zależności, znacznie łatwiej jest pozwolić Cargo
koordynować budowanie.
Mimo że projekt hello_cargo jest prosty, wykorzystuje teraz wiele
rzeczywistych narzędzi, których będziesz używać w pozostałej części swojej
kariery z Rustem. W rzeczywistości, aby pracować nad istniejącymi projektami,
możesz użyć następujących poleceń, aby pobrać kod za pomocą Git, przejść do
katalogu tego projektu i zbudować:
$ git clone example.org/someproject
$ cd someproject
$ cargo build
Więcej informacji na temat Cargo znajdziesz w jego dokumentacji.
Podsumowanie
Już świetnie zacząłeś swoją podróż z Rustem! W tym rozdziale nauczyłeś się:
- Jak zainstalować najnowszą stabilną wersję Rusta za pomocą
rustup. - Jak zaktualizować Rusta do nowszej wersji.
- Jak otworzyć lokalnie zainstalowaną dokumentację.
- Jak napisać i uruchomić program „Witaj, świecie!” bezpośrednio za pomocą
rustc. - Jak utworzyć i uruchomić nowy projekt, korzystając z konwencji Cargo.
To świetny moment, aby zbudować bardziej rozbudowany program, aby przyzwyczaić się do czytania i pisania kodu w Ruście. Tak więc, w Rozdziale 2 zbudujemy program do zgadywania liczb. Jeśli wolisz zacząć od nauki, jak działają powszechne koncepcje programistyczne w Ruście, zobacz Rozdział 3, a następnie wróć do Rozdziału 2.