Hello, Cargo!
Cargo là hệ thống build và quản lý gói của Rust. Hầu hết các Rustacean sử dụng công cụ này để quản lý project Rust của họ vì Cargo xử lý rất nhiều tác vụ cho bạn, như build code, tải thư viện mà code của bạn phụ thuộc vào và build những thư viện đó. (Chúng ta gọi những thư viện mà code của bạn cần là những dependency.)
Những chương trình Rust đơn giản nhất, như ví dụ bạn vừa viết chẳng hạn, không có dependency nào. Nên nếu chúng ta build project “Hello, world!” với Cargo, nó sẽ chỉ dùng một phần của Cargo để xử lý việc build code của bạn. Khi bạn viết những chương trình phức tạp hơn, bạn sẽ cần thêm các dependency, và nếu bạn bắt đầu một project với Cargo, việc thêm dependency sẽ dễ hơn rất nhiều.
Bởi vì một phần rất lớn các project Rust sử dụng Cargo, phần còn lại của cuốn sách này sẽ coi như bạn cũng đang sử dụng Cargo. Cargo được cài đặt cùng với Rust nếu bạn sử dụng bộ cài chính thức đã được nêu ở phần "Cài đặt". Nếu bạn đã cài Rust theo những cách khác, hãy kiểm tra xem Cargo đã được cài đặt hay chưa bằng cách nhập câu lệnh sau trong terminal:
$ cargo --version
Nếu bạn nhìn thấy số phiên bản, tức là bạn đã cài nó! Nếu bạn nhìn thấy lỗi như
command not found
, đọc trong tài liệu của phương thức cài đặt bạn đã dùng để
xác định cách cài đặt Cargo riêng rẽ như thế nào.
Tạo một Project với Cargo
Chúng ta hãy tạo một project mới bằng Cargo và xem nó khác như thế nào so với project “Hello, world!” trước. Vào thư mục projects của bạn (hoặc bất cứ thư mục nào bạn muốn mà bạn quyết định sẽ lưu trữ code của bạn). Sau đó chạy những lệnh sau:
$ cargo new hello_cargo
$ cd hello_cargo
Câu lệnh đầu tiên tạo một thư mục mới là hello_cargo. Chúng ta đã đặt tên project của chúng ta là hello_cargo, và Cargo tạo những file của nó trong một thư mục cùng tên.
Đi tới thư mục hello_cargo và hiện danh sách các file. Bạn sẽ thấy Cargo đã tạo hai file và một thư mục cho chúng ta: một file Cargo.toml và một thư mục src với một file main.rs bên trong.
Nó cũng khởi tạo một repository Git mới đi kèm với một file .gitignore. Git
file sẽ không được sinh ra nếu bạn chạy cargo new
trong một repository Git đã
tồn tại; bạn có thể ghi đè hành vi này bằng cách sử dụng cargo new --vcs=git
.
Lưu ý: Git là một hệ thống quản lý phiên bản phổ biến (version control system - VCS). Bạn có thể thay đổi
cargo new
để sử dụng một VCS khác hoặc không sử dụng VCS với cờ--vcs
. Chạycargo new --help
để xem những tùy chọn khả dụng.
Mở Cargo.toml trong phần mềm soạn thảo của bạn. Nó sẽ giống với code ở Listing 1-2.
Filename: Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2018"
[dependencies]
Listing 1-2: Nội dung của Cargo.toml tạo bởi cargo new
File này được viết dưới định dạng TOML (Tom’s Obvious, Minimal Language), định dạng cấu hình của Cargo.
Dòng đầu tiên, [package]
, là tiêu đề của một section thể hiện rằng những khai báo
sau đó đang cấu hình một package. Khi chúng ta thêm nhiều thông tin nữa vào file này,
chúng ta sẽ cần thêm những section khác nữa.
Ba dòng tiếp theo đặt thông tin cấu hình Cargo cần để biên dịch chương trình
của bạn: tên, phiên bản của chương trình, và phiên bản (edition) của Rust mà bạn
dùng. Chúng ta sẽ nói về khóa edition
trong Phụ lục E.
Dòng cuối, [dependencies]
, là bắt đầu của một đoạn liệt kê các dependency của
project. Trong Rust, các package được coi như các crate. Chúng ta không cần
bất kỳ crate nào khác cho project này, nhưng chúng ta sẽ cần trong project đầu
tiên ở Chương 2, nên chúng ta sẽ sử dụng đoạn khai báo dependencies này sau.
Giờ mở src/main.rs lên và xem thử:
Filename: src/main.rs
fn main() { println!("Hello, world!"); }
Cargo đã tạo ra một chương trình “Hello, world!” cho bạn, giống như cái chúng ta đã viết trong Listing 1-1! Cho đến giờ, điểm khác biệt giữa project trước và project Cargo tạo ra là Cargo đặt code bên trong thư mục src, và chúng ta có một file cấu hình Cargo.toml ở thư mục ngoài cùng.
Cargo yêu cầu những file mã nguồn của bạn nằm trong thư mục src. Thư mục ngoài cùng của project chỉ để file README, thông tin bản quyền, các file cấu hình, và những thứ không liên quan tới code. Việc sử dụng Cargo giúp bạn tổ chức project khoa học hơn.
Nếu bạn đã tạp một project mà không sử dụng Cargo, như project “Hello, world!”, bạn có thể chuyển nó thành một project sử dụng Cargo. Chuyển code vào trong thư mục src và tạo một file Cargo.toml phù hợp.
Build và Chạy một Project Cargo
Giờ hãy nhìn vào sự khác biệt khi bạn build và chạy chương trình “Hello, world!” vơi Cargo! Từ thư mục hello_cargo của bạn, build project bằng lệnh sau:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
Câu lệnh trên tạo một file thực thi trong target/debug/hello_cargo (hoặc target\debug\hello_cargo.exe trên Windows) thay vì thư mục hiện tại của bạn. Bạn có thể chạy file thực thi với lệnh sau:
$ ./target/debug/hello_cargo # hoặc .\target\debug\hello_cargo.exe trên Windows
Hello, world!
Nếu mọi việc thực hiện đúng, Hello, world!
sẽ được in ra terminal. Việc chạy
cargo build
lần đầu tiên cũng làm Cargo tạo ra một file mới ở thư mục ngoài:
Cargo.lock. File này chứa thông tin phiên bản của các dependency trong project
của bạn. Project này không có dependency nên file này hầu như không có thông tin
gì cả. Bạn không cần phải sửa đổi gì ở file này; Cargo sẽ quản lý nội dung của
nó cho bạn.
Chúng ta vừa mới build một project với cargo build
và chạy nó với
./target/debug/hello_cargo
, nhưng chúng ta cũng có thể sử dụng cargo run
để
biên dịch và chạy trong một lệnh.
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
Lưu ý rằng lần này chúng ta không nhìn thấy output chỉ ra rằng Cargo đang biên
dịc hello_cargo
. Cargo thấy rằng các file không thay đổi nên nó chỉ thực thi
file nhị phân. Nếu bạn đã sửa source code, Cargo sẽ build lại project trước khi
chạy nó và bạn sẽ nhìn thấy output này:
$ 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 cung cấp một câu lệnh gọi là cargo check
. Câu lệnh này nhanh chóng kiểm
tra code của bạn để chắc chắn rằng nó biên dịch được nhưng không tạo ra file
thực thi:
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
Sao bạn lại không muốn file thực thi chứ? Thông thường, cargo check
nhanh hơn
rất nhiều so với cargo build
, bởi vì nó bỏ qua bước tạo file thực thi. Nếu bạn
liên tục kiểm tra code của bạn trong khi viết, sử dụng cargo check
sẽ tăng tốc
quá trình làm việc lên! Như vậy, nhiều Rustacean chạy cargo check
thường xuyên
khi họ viết chương trình để đảm bảo nó biên dịch được. Sau đó họ chạy cargo build
khi họ sẵn sàng sử dụng file thực thi.
Hãy cùng điểm lại những gì chúng ta đã học được về Cargo cho đến lúc này:
- Chúng ta có thể build một project với
cargo build
hoặccargo check
. - Chúng ta có thể build và chạy một project trong một bước bằng
cargo run
. - Thay vì lưu kết quả build trong cùng thư mục với code, Cargo lưu nó trong thư mục target/debug.
Một ưu điểm nữa của Cargo là các câu lệnh của nó không thay đổi theo hệ điều hành. Nên cho đến giờ chúng ta sẽ không đưa ra những chỉ dẫn riêng cho Linux và macOS với Windows nữa.
Build bản Release
Khi project của bạn sẵn sàng để release, bạn có thể sử dụng cargo build --release
để biên dịch nó một các tối ưu. Câu lệnh này sẽ tạo một file thực thi
trong target/release thay vì target/debug. Những biện pháp tối ưu hóa làm
code của bạn chạy nhanh hơn, nhưng bật chúng lên sẽ làm biên dịch mất thời gian
hơn. Đây là lý do vì sao có hai cấu hình khác nhau: một cho việc phát triển, khi
mà bạn muốn build lại nhanh chóng và thường xuyên, và một cái khác cho việc
build ra chương trình cuối cùng, thứ mà bạn sẽ đưa cho người dùng, thứ sẽ không
cần build lại nhiều lần và thứ sẽ chạy nhanh nhất có thể. Nếu bạn đang benchmark
thời gian chạy của code, hãy chắc chắn rằng chạy cargo build --release
và
benchmark với file thực thi trong target/release.
Cargo as Convention
Với những project đơn giản, Cargo không có giá trị nhiều so với sử dụng
rustc
, nhưng nó sẽ chứng minh giá chị của nó khi chương trình của bạn phức tạp
hơn. Với những project phức tạp bao gồm nhiều crate, dùng Cargo sẽ thuận tiện hơn
nhiều.
Mặc dù project hello_cargo
rất đơn giản, bây giờ nó đã sử dụng những công cụ
thực tế mà bạn sẽ sử dụng sau này trong công việc của bạn. Trên thực tế, để làm
việc với bất kì các project đã có nào, bạn có thể sử dụng những câu lệnh sau đây
để lấy code với Git, đi tới thư mục project và build:
$ git clone someurl.com/someproject
$ cd someproject
$ cargo build
Xem thêm tài liệu về Cargo để biết nhiều thông tin hơn.
Tổng kết
Bạn đã có một khởi đầu rất tuyệt trong hành trình đến với Rust! Trong chương này, bạn đã học được cách:
- Cài đặt phiên bản stable mới nhất của Rust bằng cách sử dụng
rustup
- Cập nhật tới một phiên bản Rust mới hơn
- Mở tài liệu có sẵn trong máy
- Viết và chạy một chương trình “Hello, world!” với
rustc
- Tạo và chạy một project mới bằng Cargo
Đây là thời điểm tốt để build một chương trình lớn hơn để làm quen với việc đọc và viết code Rust. Vì thế, trong chương 2, chúng ta sẽ build một chương trình trò chơi đoán số. Nếu bạn muốn bắt đầu học về các khái niệm lập trình phổ thông trong Rust, bạn có thể đọc Chương 3 và quay lại Chương 2 sau.