計(jì)語(yǔ)言——認(rèn)識(shí)Cargo和Crates.io)
目錄1. 采用發(fā)布配置自定義構(gòu)建2. 將crate發(fā)布到Crates.io2.1 編寫有用的文檔注釋2.1.1 常用章節(jié)2.1.2 文檔注釋作為測(cè)試2.1.3 注釋包含項(xiàng)的結(jié)構(gòu)2.2 導(dǎo)出實(shí)用的公有API2.3 創(chuàng)建crates.io賬號(hào)2.4 向新crate添加元數(shù)據(jù)2.5 發(fā)布到crates.io2.6 發(fā)布現(xiàn)有crate的新版本2.7 使用cargo yank從Crates.io撤回版本3. Cargo工作空間3.1 創(chuàng)建工作空間3.2 在工作空間中創(chuàng)建第二個(gè)包3.2.1 依賴外部包3.2.2 為工作空間增加測(cè)試4. 使用cargo install安裝二進(jìn)制文件5. Cargo自定義擴(kuò)展命令參考1. 采用發(fā)布配置自定義構(gòu)建在Rust中發(fā)布配置release profiles是預(yù)定義且可定制的配置文件集它們包含不同的配置允許程序員靈活地控制代碼編譯的多種選項(xiàng)。每一種配置都獨(dú)立于其他配置。Cargo有兩個(gè)主要的配置運(yùn)行cargo build時(shí)采用的dev配置和運(yùn)行cargo build --release的release配置。dev配置為開(kāi)發(fā)定義了良好的默認(rèn)配置release配置則為發(fā)布構(gòu)建定義了良好的默認(rèn)配置。當(dāng)項(xiàng)目的Cargo.toml文件沒(méi)有顯式增加任何[profile.*]部分的時(shí)候Cargo會(huì)對(duì)每一個(gè)配置都采用默認(rèn)設(shè)置。通過(guò)增加任何希望定制的配置對(duì)應(yīng)的[profile.*]部分我們可以選擇覆蓋任意默認(rèn)設(shè)置的子集。如下是dev和release配置的opt-level設(shè)置的默認(rèn)值[profile.dev] opt-level 0 [profile.release] opt-level 3opt-level設(shè)置控制Rust會(huì)對(duì)代碼進(jìn)行何種程度的優(yōu)化。這個(gè)配置的值從0到3.越高的優(yōu)化級(jí)別需要更多的時(shí)間編譯如果你在進(jìn)行開(kāi)發(fā)并經(jīng)常編譯可能會(huì)希望在犧牲一些代碼性能的情況下減少優(yōu)化以便編譯得快一點(diǎn)。因此dev的opt-level默認(rèn)為0.當(dāng)你準(zhǔn)備發(fā)布時(shí)花費(fèi)更多時(shí)間在編譯上則更好。只需要在發(fā)布模式編譯一次而編譯出來(lái)的程序則會(huì)運(yùn)行很多次所以發(fā)布模式用更長(zhǎng)的編譯時(shí)間換取運(yùn)行更快的代碼因此release配置的默認(rèn)opt-level為32. 將crate發(fā)布到Crates.io我們?cè)陧?xiàng)目中使用過(guò)crates.io上的包作為依賴也可以通過(guò)發(fā)布自己的包來(lái)向他人分享代碼。crates.io上的crate注冊(cè)表會(huì)分發(fā)你包的源代碼因此它主要托管開(kāi)源代碼。2.1 編寫有用的文檔注釋準(zhǔn)確的包文檔有助于其他用戶理解如何以及何時(shí)使用它們所以花一些時(shí)間編寫文檔時(shí)值得。//可以注釋代碼但Rust也有特定的用于文檔的注釋類型通常被稱為文檔注釋它們會(huì)生成HTML文檔。這些HTML文檔展示公有API文檔注釋的內(nèi)容它們意在讓對(duì)庫(kù)感興趣的程序員理解如何使用這個(gè)crate而不是它是如何被實(shí)現(xiàn)的。文檔注釋使用三條斜杠///而不是兩條斜杠并且支持使用Markdown標(biāo)記來(lái)格式化文本。將文檔注釋放在它所說(shuō)明的項(xiàng)之前。/// Adds one to the number given.////// # Examples////// /// let arg 5;/// let answer my_crate::add_one(arg);////// assert_eq!(6, answer);/// pubfnadd_one(x:i32)-i32{x1}我描述了add_one函數(shù)的功能接著以Examples為標(biāo)題開(kāi)始了一小節(jié)并給出了展示如何使用add_one函數(shù)的代碼??梢赃\(yùn)行cargo doc來(lái)根據(jù)這些文檔注釋生成HTML文檔。這個(gè)命令會(huì)運(yùn)行Rust自帶的rustdoc工具并將生成的HTML文檔放到target/doc目錄中。運(yùn)行cargo doc --open會(huì)為當(dāng)前crate的文檔構(gòu)建HTML并在瀏覽器中打開(kāi)結(jié)果。定位到add_one函數(shù)時(shí)你會(huì)看到文檔注釋中的文本是如何被渲染的2.1.1 常用章節(jié)上面的文檔展示了使用# Examples Markdown標(biāo)題在HTML中創(chuàng)建了一個(gè)以Examples為標(biāo)題的部分。其他一些crate作者經(jīng)常在文檔注釋中使用的部分有Panics函數(shù)在什么情況下可能會(huì)panic!。不希望程序panic的調(diào)用者應(yīng)確保不會(huì)在這些情況下調(diào)用該函數(shù)。Errors如果函數(shù)返回Result說(shuō)明可能出現(xiàn)哪些錯(cuò)誤以及什么條件會(huì)導(dǎo)致返回這些錯(cuò)誤會(huì)有助于調(diào)用者編寫代碼以不同方式處理不同種類的錯(cuò)誤。Safety如果調(diào)用該函數(shù)時(shí)unsafe的(后面會(huì)將不安全代碼)這里應(yīng)該解釋為什么它是不安全的并說(shuō)明函數(shù)要求調(diào)用者維持哪些不變式。大多數(shù)文檔注釋不需要包含所有這些章節(jié)但這是一份很好的檢查清單可以提醒你關(guān)注用戶會(huì)想了解的內(nèi)容。2.1.2 文檔注釋作為測(cè)試在文檔注釋中添加示例代碼塊有助于展示如何使用你的庫(kù)而且還有一個(gè)額外的好處運(yùn)行cargo test時(shí)文檔中的示例代碼也會(huì)作為測(cè)試運(yùn)行沒(méi)有什么比帶示例的文檔更好了但也沒(méi)有什么比示例失敗的文檔更糟糕了。運(yùn)行cargo test如果我們修改函數(shù)或示例中的任意一方使示例里的assert_eq!觸發(fā)panic然后再次運(yùn)行cargo test就會(huì)看到文檔測(cè)試捕獲了示例與代碼不同步的問(wèn)題。2.1.3 注釋包含項(xiàng)的結(jié)構(gòu)//!這種文檔注釋風(fēng)格為“包含這些注釋的項(xiàng)”添加文檔而不是為“位于這些注釋之后的項(xiàng)”添加文檔。我們通常在crate根文件src/lib.rs或模塊內(nèi)部使用這種文檔注釋為整個(gè)crate或整個(gè)模塊編寫說(shuō)明。為了添加描述包含add_one函數(shù)的my crate crate用于的文檔可以在src/lib.rs文件開(kāi)頭加入以//!開(kāi)頭的文檔注釋//! # My Crate//!//! my_crate is a collection of utilities to make performing certain//! calculations more convenient./// Adds one to the number given.// 省略最后一行以//!開(kāi)頭的注釋后面沒(méi)有代碼。因?yàn)槲覀兪褂玫氖?/!而不是///所以這里記錄的是“包含這條注釋的項(xiàng)”的文檔而不是“緊隨這條注釋之后的項(xiàng)”的文檔。在這里這個(gè)項(xiàng)就是src/lib.rs文件也就是crate根。這些注釋描述的是真?zhèn)€crate。運(yùn)行cargo doc --open項(xiàng)內(nèi)部的文檔注釋特別適合用來(lái)描述crate和模塊。使用它們來(lái)解釋這個(gè)容器整體的目的可以幫助用戶理解crate的組織方式。2.2 導(dǎo)出實(shí)用的公有API公有API的結(jié)構(gòu)是你發(fā)布crate時(shí)主要需要考慮的。crate用戶沒(méi)有你那么熟悉其結(jié)構(gòu)并且如果模塊層級(jí)過(guò)大他們可能會(huì)難以找到所需的部分。第七章介紹了如何使用pub關(guān)鍵字使項(xiàng)公開(kāi)以及如何使用use關(guān)鍵字將項(xiàng)引入作用域。不過(guò)在你開(kāi)發(fā)crate時(shí)對(duì)你來(lái)說(shuō)合理的結(jié)果對(duì)用戶而言可能并不方便。你可能想把結(jié)構(gòu)體組織成一個(gè)包含多層的層級(jí)結(jié)構(gòu)但想使用你定義在深層級(jí)中的某個(gè)類型的人可能很難發(fā)現(xiàn)它的存在。他們也可能會(huì)厭煩不得不寫use my_crate::some_module::another_module::UsefulType;而不是簡(jiǎn)單的use my_crate::UsefulType;。好消息是如果這種結(jié)構(gòu)對(duì)外部用戶來(lái)說(shuō)并不方便你也不必重新安排內(nèi)部組織。你可以使用pub use來(lái)重導(dǎo)出項(xiàng)從而建立一個(gè)與私有結(jié)構(gòu)不同的公有結(jié)構(gòu)。重導(dǎo)出會(huì)把某個(gè)位置的公有項(xiàng)在另一個(gè)位置再次公開(kāi)就好像它原本就定義在哪里一樣。假設(shè)我們創(chuàng)建了一個(gè)名為art的庫(kù)用來(lái)建模藝術(shù)概念。在這個(gè)庫(kù)里有兩個(gè)模塊kinds模塊包含兩個(gè)枚舉PrimaryColor和SecondaryColorutils模塊包含一個(gè)名為mix的函數(shù)//! # Art//!//! A library for modeling artistic concepts.pubmodkinds{/// The primary colors according to the RYB color model.pubenumPrimaryColor{Red,Yellow,Blue,}/// The secondary colors according to the RYB color model.pubenumSecondaryColor{Orange,Green,Purple,}}pubmodutils{usecrate::kinds::*;/// Combines two primary colors in equal amounts to create/// a secondary color.pubfnmix(c1:PrimaryColor,c2:PrimaryColor)-SecondaryColor{// 省略}}下面是這個(gè)crate生成的文檔首頁(yè)。注意PrimaryColor和SecondaryColor類型、以及mix函數(shù)都沒(méi)有在首頁(yè)中列出。我們必須點(diǎn)擊kinds或utils才能看到它們。依賴這個(gè)庫(kù)的另一個(gè)crate需要使用use語(yǔ)句把a(bǔ)rt中的項(xiàng)引入作用域同時(shí)必須指定當(dāng)前定義的模塊結(jié)構(gòu)。如下所示useart::kinds::PrimaryColor;useart::utils::mix;fnmain(){letredPrimaryColor::Red;letyellowPrimaryColor::Yellow;mix(red,yellow);}寫出上面代碼的作者必須先弄清楚PrimaryColor在kinds模塊中而mix在utils模塊中。art crate的模塊結(jié)構(gòu)對(duì)開(kāi)發(fā)art crate的人來(lái)說(shuō)比對(duì)使用它的人更有意義。這種內(nèi)部結(jié)構(gòu)并沒(méi)有給想理解如何使用art crate的人提供有價(jià)值的信息反而會(huì)帶來(lái)困惑因?yàn)橛脩舯仨毾雀闱宄撊ツ睦镎倚枰膬?nèi)容還要在use語(yǔ)句中寫出模塊名。為了從公有API中去掉內(nèi)部組織細(xì)節(jié)在art crate中加入pub use語(yǔ)句在頂層導(dǎo)出這些項(xiàng)。//! # Art//!//! A library for modeling artistic concepts.pubuseself::kinds::PrimaryColor;pubuseself::kinds::SecondaryColor;pubuseself::utils::mix;pubmodkinds{// 省略}pubmodutils{// 省略}運(yùn)行cargo doc --open之后可以在首頁(yè)看到重導(dǎo)出項(xiàng)這使PrimaryColor、SecondaryColor和mix更容易被找到。art crate的用戶仍然可以像網(wǎng)頁(yè)文檔看的一樣使用art中的內(nèi)部結(jié)構(gòu)useart::PrimaryColor;useart::mix;fnmain(){// 省略}在存在很多嵌套模塊的情況下使用pub use將類型重導(dǎo)出到頂層會(huì)顯著改善使用這個(gè)crate的體驗(yàn)。pub use的另一個(gè)用法是把當(dāng)前crate的某個(gè)依賴中的定義重新導(dǎo)出讓那個(gè)crate的定義稱為你這個(gè)crate公有API的一部分。創(chuàng)建有用的公有API結(jié)構(gòu)更像一門藝術(shù)而不是科學(xué)你可以不斷迭代找到最適合用戶的API。選擇pub use能讓你在crate內(nèi)部結(jié)構(gòu)的組織方式上保持靈活并將其與你呈現(xiàn)給用戶的結(jié)構(gòu)解耦。2.3 創(chuàng)建crates.io賬號(hào)在發(fā)布任何crate之前你需要在crates.io上創(chuàng)建賬號(hào)并獲取一個(gè)API token。為此請(qǐng)?jiān)L問(wèn)crates.io首頁(yè)并通過(guò)Github賬號(hào)登陸。登錄之后前往https://crates.io/me的賬戶設(shè)置頁(yè)面獲取API key。然后運(yùn)行cargo login命令并在提示時(shí)粘貼你的API key。這個(gè)命令會(huì)把你的API token告訴cargo并將其保存在本地的~/.cargo/credentials文件中。所有token都是秘密不應(yīng)該與任何人分享。如果泄露了立即前往crates.io撤銷并重新生成一個(gè)token。2.4 向新crate添加元數(shù)據(jù)比如說(shuō)你已經(jīng)有一個(gè)希望發(fā)布的crate。在發(fā)布之前你需要在crate的Cargo.toml文件的[package]部分增加一些本crate的元數(shù)據(jù)。首先crate需要一個(gè)唯一的名稱。雖然在本地開(kāi)發(fā)crate時(shí)可以隨意命名但crates.io上的crate名稱遵循先到先得的原則。一但某個(gè)crate名稱已經(jīng)被占據(jù)就沒(méi)有其他人能再用這個(gè)名稱發(fā)布crate。請(qǐng)搜索你想使用的名稱確認(rèn)它是否已被占用。如果沒(méi)有就把Cargo.toml中[package]里的name字段改成你想發(fā)布時(shí)使用的名稱如下所示[package] name guessing_game即使你選擇了一個(gè)唯一的名稱如果此時(shí)嘗試運(yùn)行cargo publish發(fā)布該crate的話會(huì)得到一個(gè)警告缺少一些關(guān)鍵信息——關(guān)于該crate用途的描述以及用戶可以在什么許可條款下使用它。在Cargo.toml中添加一兩句簡(jiǎn)短描述即可因?yàn)樗鼤?huì)在搜索結(jié)果中和你的crate一起顯示。對(duì)于license字段你需要填寫一個(gè)許可證標(biāo)識(shí)符值。Linux基金會(huì)的Software Package Data Exchange(SPDX)列出了可用的標(biāo)識(shí)符。如果使用MIT License如下所示[package] name guessing_name license MIT如果你想使用SPDX中不存在的許可證就需要把許可證文本放入一個(gè)文件中將該文件包含到項(xiàng)目里然后使用license-file指定該文件名而不是使用license字段。很多Rust社區(qū)成員選擇與Rust本身相同的許可證也就是雙許可證MIT OR Apache-2.0??梢允褂肙R分隔多個(gè)許可證標(biāo)識(shí)符來(lái)為項(xiàng)目指定多個(gè)許可證。有了唯一的名稱、版本號(hào)、由cargo new新建項(xiàng)目時(shí)增加的作者信息、描述和所選擇的license已經(jīng)準(zhǔn)備好發(fā)布的項(xiàng)目的Cargo.toml文件看起來(lái)如下[package] name guessing_game version 0.1.0 edition 2024 description A fun game where you guess what number the computer has chosen. license MIT OR Apache-2.0 [dependencies]2.5 發(fā)布到crates.io在創(chuàng)建了賬號(hào)、保存了API token、為crate準(zhǔn)備好名字以及元數(shù)據(jù)之后可以發(fā)布了。發(fā)布crate會(huì)將該crate的某個(gè)特定版本上傳到crates.io供他人使用。發(fā)布crate時(shí)務(wù)必小心發(fā)布是永久性的。對(duì)應(yīng)版本無(wú)法被覆蓋其代碼也無(wú)法被刪除。crates.io的一個(gè)主要目標(biāo)是充當(dāng)代碼的永久歸檔服務(wù)器這樣所有依賴crates.io上crate的項(xiàng)目可以一直正常工作。而如果允許刪除版本就無(wú)法實(shí)現(xiàn)這一目標(biāo)。不過(guò)可發(fā)布的版本號(hào)數(shù)量并沒(méi)有限制。運(yùn)行cargo publish發(fā)布。2.6 發(fā)布現(xiàn)有crate的新版本當(dāng)你修改了crate并準(zhǔn)備發(fā)布新版本時(shí)修改Cargo.toml中version的值。請(qǐng)使用語(yǔ)義化版本控制規(guī)則根據(jù)修改的類型決定下一個(gè)版本號(hào)。然后再次運(yùn)行cargo publish來(lái)上傳新版本。2.7 使用cargo yank從Crates.io撤回版本雖然你不能刪除crate的歷史版本但可以阻止未來(lái)的新項(xiàng)目把它加入依賴。這在某個(gè)版本因?yàn)槟撤N原因損壞時(shí)會(huì)很用。為此Cargo支持對(duì)某個(gè)版本執(zhí)行撤回yank。撤回某個(gè)版本會(huì)阻止新項(xiàng)目依賴這個(gè)版本不過(guò)所有已經(jīng)依賴它的項(xiàng)目仍然可以下載并繼續(xù)依賴它。從本質(zhì)上說(shuō)撤回意味著所有已有Cargo.lock的項(xiàng)目都不會(huì)因此損壞而任何新生成的Cargo.lock都不會(huì)再使用被撤回的版本。要撤回crate的某個(gè)版本請(qǐng)?jiān)谥鞍l(fā)布該crate的目錄中運(yùn)行cargo yank并指定要撤回的版本。比如如果我們發(fā)布了名為guessing_game的crate的1.0.1版本并想撤回它就在guessing_game項(xiàng)目目錄中運(yùn)行cargoyank--vers1.0.1也可以撤銷這次撤回讓項(xiàng)目重新可以依賴該版本只需在命令中加上–undocargoyank--vers1.0.1--undo撤回不會(huì)刪除任何代碼。例如撤回功能并不能刪除你不小心上傳的秘密信息。如果發(fā)生了這種情況請(qǐng)立刻輪換這些秘密信息。3. Cargo工作空間Cargo提供了一項(xiàng)叫做工作空間workspace的功能可以幫助管理多個(gè)彼此相關(guān)、并行開(kāi)發(fā)的包。3.1 創(chuàng)建工作空間工作空間是一組共享同一個(gè)Cargo.lock和輸出目錄的包。下面創(chuàng)建一個(gè)工作空間包含一個(gè)二進(jìn)制crate和兩個(gè)庫(kù)。二進(jìn)crate提供主要功能并依賴這兩個(gè)庫(kù)。一個(gè)庫(kù)提供add_one函數(shù)另一個(gè)庫(kù)提供add_two函數(shù)。三個(gè)crate屬于同一個(gè)工作空間。創(chuàng)建工作空間的目錄mkdiraddcdadd在add目錄中新建Cargo.toml文件用來(lái)配置整個(gè)工作空間。這個(gè)文件不會(huì)有[package]部分而是會(huì)以[workspace]部分開(kāi)頭這樣我們就能向工作空間添加成員。我們還會(huì)把resolver的值設(shè)為3以便在工作空間中使用Cargo最新的依賴解析算法。[workspace] resolver 3接下來(lái)在add目錄運(yùn)行cargo new新建adder二進(jìn)制cratecargonew adder在工作空間中運(yùn)行cargo new時(shí)新創(chuàng)建的包也會(huì)被自動(dòng)加入工作空間Cargo.toml中[workspace]定義的members鍵[workspace] resolver 3 members [adder]可以運(yùn)行cargo build來(lái)構(gòu)建工作空間。工作空間在頂層只有一個(gè)target目錄用來(lái)存放編譯產(chǎn)物adder包不會(huì)有自己的target目錄。即使我們?cè)赼dder目錄中運(yùn)行cargo build編譯產(chǎn)物也仍會(huì)放到add/target而不是add/adder/target。Cargo之所以這樣組織工作空間中的target目錄是因?yàn)楣ぷ骺臻g中的crate本來(lái)就是要彼此依賴的。如果每個(gè)crate都有各自的target目錄那么每個(gè)crate都不得不重新編譯工作空間中的其他crate才能把產(chǎn)物放進(jìn)自己的target目錄。共享一個(gè)target目錄可以避免不必要的重復(fù)構(gòu)建。3.2 在工作空間中創(chuàng)建第二個(gè)包在工作空間中創(chuàng)建另一個(gè)成員包并將其命名為add_one。cargonew add_one--lib現(xiàn)在add目錄包含如下目錄和文件在add_one/src/lib.rs中增加一個(gè)add_one函數(shù)pubfnadd_one(x:i32)-i32{x1}現(xiàn)在可以讓二進(jìn)制包adder依賴包含庫(kù)的add_one包。首先需要在adder/Cargo.toml中把a(bǔ)dd_one添加為一個(gè)路徑依賴[dependencies] add_one { path ../add_one }Cargo并不會(huì)假定工作空間中的crate會(huì)彼此依賴因?yàn)槲覀冃枰@式聲明這些依賴關(guān)系。在adder crate中使用add_one crate里的add_one函數(shù)。在adder/src/main.rs中調(diào)用add_onefnmain(){letnum10;println!(Hello, World! {num} plus one is {}!,add_one::add_one(num));}在頂層add目錄中運(yùn)行cargo build來(lái)構(gòu)建工作空間。要從add目錄運(yùn)行這個(gè)二進(jìn)制crate可以在cargo run時(shí)通過(guò)-p參數(shù)加上包名指定要運(yùn)行工作空間中的哪個(gè)包c(diǎn)argorun-padder這會(huì)運(yùn)行adder/src/main.rs中的代碼其依賴add_one crate。3.2.1 依賴外部包注意工作空間只在頂層有一個(gè)Cargo.lock文件而不是讓每個(gè)crate目錄里都各自有一個(gè)Cargo.lock。這能確保所有crate使用的都是同一個(gè)版本的依賴。如果我們把rand包同時(shí)加到adder/Cargo.toml和add_one/Cargo.toml中Cargo會(huì)把它們都解析為同一個(gè)rand版本并把結(jié)果記錄到唯一的Cargo.lock中。讓工作空間中的所有crate使用相同依賴意味著這些crate會(huì)始終彼此兼容。將rand crate加到add_one/Cargo.toml的[dependencies]部分[dependencies] rand 0.10.2在add_one/src/lib.rs中加入use rand;然后在add目錄中運(yùn)行cargo build來(lái)構(gòu)建整個(gè)工作空間這會(huì)引入并編譯rand crate。頂層的Cargo.lock現(xiàn)在已經(jīng)包含了add_one依賴rand的信息。不過(guò)即使rand在工作空間的某處被使用我們也不能直接在工作空間里的其他crate中使用它除非把rand加到它們各自的Cargo.toml中。要修復(fù)這個(gè)錯(cuò)誤必須把rand也加到adder的Cargo.toml中。這樣在構(gòu)建adder包的時(shí)候才會(huì)將rand加到Cargo.lock中adder的依賴列表里。Cargo會(huì)確保工作空間中每個(gè)使用rand的crate都使用同一個(gè)版本只要它們聲明的是彼此兼容的rand版本這樣既節(jié)省空間也確保工作空間中的crate彼此兼容。如果工作空間中的crate為同一個(gè)依賴指定了彼此不兼容的版本Cargo仍然會(huì)分別解析它們但會(huì)盡量把版本數(shù)量控制得盡可能少。3.2.2 為工作空間增加測(cè)試為add_one::add_one函數(shù)增加一個(gè)測(cè)試pubfnadd_one(x:i32)-i32{x1}#[cfg(test)]modtests{usesuper::*;#[test]fnit_works(){assert_eq!(3,add_one(2));}}在根目錄下運(yùn)行cargo test會(huì)執(zhí)行工作空間中所有crate的測(cè)試可以在根目錄中通過(guò)-p參數(shù)并指定想要測(cè)試的crate名稱如果你打算把工作空間中的crate發(fā)布到crates.io上那么工作空間中的每個(gè)crate都需要單獨(dú)發(fā)布。和cargo test一樣可以通過(guò)-p參數(shù)并指定要發(fā)布的crate名稱來(lái)發(fā)布工作空間中的某個(gè)特定crate。4. 使用cargo install安裝二進(jìn)制文件cargo install命令允許你在本地安裝和使用二進(jìn)制crate。它并不是為了替代系統(tǒng)包管理器而是為Rust開(kāi)發(fā)者提供一種方便的方式用來(lái)安裝他人在crates.io上分享的工具。只有帶有二進(jìn)制目標(biāo)的包才能被安裝。二進(jìn)制目標(biāo)是指當(dāng)crate包含src/main.rs文件或?qū)⑵渌募付槎M(jìn)制目標(biāo)時(shí)所生成的可運(yùn)行文件這與庫(kù)目標(biāo)不同庫(kù)目標(biāo)本身不能單獨(dú)運(yùn)行但適合被其他程序接入。通常crate的README文件會(huì)說(shuō)明它是庫(kù)、帶有二進(jìn)制目標(biāo)還是兩者兼有。所有通過(guò)cargo install安裝的二進(jìn)制文件都會(huì)放在安裝根目錄下的bin文件夾中。請(qǐng)確保這個(gè)bin文件夾已經(jīng)在系統(tǒng)環(huán)境變量PATH中。5. Cargo自定義擴(kuò)展命令Cargo的設(shè)計(jì)允許你用新的子命令來(lái)擴(kuò)展它而不必修改Cargo本身。如果你的PATH中有一個(gè)名為cargo-something的二進(jìn)制文件那么你可以像Cargo子命令一樣通過(guò)cargo something來(lái)運(yùn)行它。這類自定義命令也會(huì)在你運(yùn)行cargo --list時(shí)顯示出來(lái)。Cargo這種設(shè)計(jì)帶來(lái)了一個(gè)非常方便的好處你可以引用cargo install安裝擴(kuò)展然后像使用Cargo內(nèi)建工具一樣運(yùn)行它們。參考1、進(jìn)一步認(rèn)識(shí)Cargo和Crates.io