2015年5月13日 星期三

Rust Cargo

佈署是現代程式設計遇到的一個問題,雖然網路的出現讓大家可以快速的流通成品,同時也帶來各種版本混亂。
這個問題在C/C++ 上不嚴重,主因C/C++的跟底層黏著度高,演化速度也慢,都是透過作業系統的套件更新。相對的我們可以看到無論python 的pip、Ruby的RubyGems、Golang 支援從github 取得project、NodeJS的npm,都是要建立一個統一的套件佈署管道,方便設計師開發。

今天要提的,就是Rust 的解決方案: Cargo,用來管理rust project,當然如果不用cargo,就算像之前的嵌入式系統一樣,直接寫一個rust檔案並用Makefile + rustc 編譯也是沒有問題的。

安裝好cargo使用cargo new即可生成一個新的rust project資料;跟先前提到的一樣,Cargo new 時即會生成一個git repository和它的.gitignore,方便套件版本控制。
project的資料會使用Cargo.toml這個檔案來管理,toml 是一款極簡的設定格式,相關文件格式可見:
https://github.com/toml-lang/toml

Cargo.toml 裡面會定義這個package 的資料:
[package]
name = "package name"
version = "0.1.0"
authors = ["author <author@xxxxx.com>"]

Cargo 有一系列可用的指令,用cargo --help 就可以看到
build Compile the current project
clean Remove the target directory
doc Build this project's and its dependencies' documentation
new Create a new cargo project
run Build and execute src/main.rs
test Run the tests
bench Run the benchmarks
update Update dependencies listed in Cargo.lock

一般最常用的組合,大概就是new, build, run三個基本指令,用來初始、編譯、執行,預設會用src/main.rs當作預設的編譯目標,並建構在target資料夾內,下面是其他的功能:

相依套件:

如果要用到其他的套件,把相依的套件名字填入Cargo.toml裡面:
[dependencies]
package “package version”

[dependencies.package]
git = “url”

[dependencies.package]
path = “path”

並在原始碼用extern指定它即可:
//main.rs
extern package
use package::{};

Cargo build 的時候會自動去檢查相依性套件,從它的git repository裡面簽出最新的master版本放到家目錄的.cargo 中,並用它進行建構;簽出的版本會寫進Cargo.lock,如果把Cargo.lock 傳給別人,他們就只之後就能用這個版本建構,如果要更新Cargo.lock 的話,就要用cargo update 來更新相依的套件,或用cargo update -p package指定更新某套件。

使用本地套件:

如果需要修相依套件裡面的bug,cargo 可以指定用本地的套件,而非簽出在.cargo 裡面的套件,只要在project 往上到根目錄的任一個地方,產生一個.cargo 的目錄,並在裡面建立config 檔,標示local project 的Cargo.toml 所在:
paths = ['path to local project']

測試:

cargo test 會執行在src 跟tests 裡面的測試,也就是有#[test] attribute 的,算是一個不錯小工具。

如果拿servo 當例子:
https://github.com/servo/servo/blob/master/components/servo/Cargo.toml
一開始先定義package:
[package]
name = "servo"
version = "0.0.1"
authors = ["The Servo Project Developers"]

servo要編出的library
[lib]
name = "servo"
path = "lib.rs"
crate-type = ["rlib"]

下面有一大排dependency,都是servo project 內的子專案,所以都是用相對路徑的方式來定義,而這些子專案的Cargo.toml內又會定義相依套件,例如外部相依大部分定義在util 裡面,這就會用git 的方式來引用:
[dependencies.azure]
git = "https://github.com/servo/rust-azure"

有一次有寫到一個issue 就是要更動相依的rust-mozjs的套件,再更新servo 內Cargo.lock 檔,相關的更動可見:
https://github.com/servo/mozjs/pull/29
https://github.com/servo/servo/pull/4998

參考資料:

相關的cargo內容可見:
http://doc.crates.io/guide.html

可取用的rust 的套件庫以在這裡找到:
https://crates.io/
Related Posts Plugin for WordPress, Blogger...