<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          懂你,更懂Rust系列之不斷增長(zhǎng)的Rust項(xiàng)目管理

          共 7613字,需瀏覽 16分鐘

           ·

          2021-06-12 17:30



          簡(jiǎn)單愛,你心所愛

          世界也變得大了起來

          所有花都為你開

          所有景物也為了你安排

          我們是如此的不同

          肯定前世就已經(jīng)深愛過

          講好了這一輩子

          再度重相逢



          前面所分享到的所有的Rust相關(guān)的代碼,都是在一個(gè)文件中的,那么當(dāng)在實(shí)際的開發(fā)過程中,肯定是涉及到很多很復(fù)雜的代碼量的,這個(gè)時(shí)候,就涉及到公共函數(shù)的封裝,接口調(diào)用等等關(guān)聯(lián)的東西,那么今天就給大家?guī)黻P(guān)于Rust項(xiàng)目的實(shí)際工作中的,包、模塊管理。


          首先,看下新建一個(gè)名為first-large-project的Rust項(xiàng)目


          其結(jié)構(gòu)如下:


          eff2538742fc6e657eef90d1dc21d426.webp


          新建的一個(gè)Rust項(xiàng)目,包含一個(gè)src文件夾,下面有一個(gè)main.rs文件,此外還有Cargo.lock和Cargo.toml文件


          首先先來了解下Cargo.lock和Cargo.toml


          下面是2個(gè)文件內(nèi)容的對(duì)比:


          b941c71f35cc4d45b1339cfd0c5ed96a.webp


          Cargo.lock:注釋描述中說到,該文件是Cargo自動(dòng)生成的,同時(shí)不是手動(dòng)手動(dòng)編輯的,言下之意就是,我們不需要去手動(dòng)修改這個(gè)文件。那么這個(gè)文件究竟是干啥用的呢?


          • Cargo.lock?contains exact information about your dependencies. It is maintained by Cargo and should not be manually edited.


          這里是官方對(duì)該文件的解釋:包含項(xiàng)目有關(guān)依賴項(xiàng)的確切信息


          即我們可以這么理解,這個(gè)文件用于記載項(xiàng)目的所有依賴的詳細(xì)信息



          Cargo.toml:這里可以看到,描述了本項(xiàng)目的基本信息,同時(shí)下面有一個(gè)

          [dependencies],即這里可以給項(xiàng)目添加依賴。



          那么我們嘗試添加一個(gè)依賴:


          afe522988cb8e01a2f3949c8351de735.webp



          這里添加了一個(gè)rand庫,等待項(xiàng)目構(gòu)建完成,這時(shí)候可以看看Cargo.lock文件:


          db9a75b28cc379852ceee7be85bac523.webp



          上圖可以看見,Cargo.lock文件記錄了更多的依賴信息,而不是像Cargo.toml文件中記載的那一個(gè)依賴了。


          然后可以通過依賴的git地址,發(fā)現(xiàn)rand項(xiàng)目所有依賴的庫和rand包含的子項(xiàng)目也都在我們的Cargo.lock文件中有所記載。


          這里顯然,Cargo.lock就是對(duì)Cargo.toml依賴的一個(gè)詳細(xì)說明。



          接下來,先明確幾個(gè)概念:



          crate


          crate:a library or executable program is called a?crate?.



          上面是Rust官方給出的一個(gè)解釋,一個(gè)庫或者可執(zhí)行的程序,被稱為crate


          包<package>


          包:是提供一系列功能的一個(gè)或者多個(gè)crate,即包=crate+crate+...+crate

          一個(gè)包會(huì)包含一個(gè)Cargo.toml文件,描述如何構(gòu)建包所包含的所有crate


          那么其實(shí)上面例子中的這個(gè)first-large-project就是一個(gè)包



          然后回頭看下上面的例子,還剩下一個(gè)src/main.rs文件。Cargo遵循了一個(gè)約定:src/main.rs?就是一個(gè)與包同名的二進(jìn)制 crate 的 crate 根,那么這里的src/main.rs就是一個(gè)二進(jìn)制的crate


          下面有3點(diǎn)重要的約束:


          1、一個(gè)包中最多只能包含一個(gè)庫crate


          2、一個(gè)包中可以有多個(gè)二進(jìn)制crate


          3、一個(gè)包中至少包含一個(gè)crate


          以上三點(diǎn)約束是很重要很重要的,在之后構(gòu)建大型的Rust項(xiàng)目,這是一個(gè)必須掌握的,否則,我們連如果建Rust文件都搞不定,總不能把所有代碼都寫在一個(gè)文件吧!



          結(jié)合上面的例子,接著看這個(gè)first-large-project,可以看到目前這個(gè)項(xiàng)目只有一個(gè)src/main.rs文件,上面也講過了,這個(gè)main.rs文件其實(shí)就是和我們項(xiàng)目同名的二進(jìn)制crate根。


          那么這就滿足了3點(diǎn)約束中的第3條:一個(gè)包中至少包含一個(gè)crate,因?yàn)槿绻诎堰@個(gè)main.rs去掉,這也就不是一個(gè)程序了,Rust也無法編譯構(gòu)建了


          那么看3點(diǎn)約束中的第2條:一個(gè)包中可以有多個(gè)二進(jìn)制crate,那么這個(gè)怎么做呢?


          這時(shí)候,在src目錄下,新建一個(gè)main_other.rs


          8a4b48f417b6dd026a101340a400c658.webp


          然后定義main函數(shù),這時(shí)候,可以發(fā)現(xiàn),雖然這里也定義了main方法,但是可以看到,這個(gè)main函數(shù)是不可被Rust編譯后可以運(yùn)行的主函數(shù)mian,


          對(duì)比這2個(gè)main函數(shù):


          f0a2c73900e6f938acc79e510a9ae7a4.webp


          后者沒有run標(biāo)識(shí),這就說明,這個(gè)main_other.rs不是一個(gè)二進(jìn)制的crate,僅僅是一個(gè)普通的Rust文件,在此時(shí),先透露一下,這個(gè)main_other.rs被稱為module。


          我們?cè)谶@個(gè)main_other.rs的main函數(shù)前面加一個(gè)pub關(guān)鍵字,然后就可以在main.rs中調(diào)用了。


          0f4c2e234703f075268ab87b4eef606d.webp


          修改main.rs


          4157cd3499276b610cf35fcf2920ce73.webp


          編譯運(yùn)行:


          6e4b3cb21212b2eee4863d6cbcbaa225.webp


          這里使用mod關(guān)鍵字,將與main.rs同級(jí)目錄下的main_other模塊兒<module>引入進(jìn)來,然后調(diào)用main函數(shù)。


          main_other.rs的main函數(shù)為啥需要加一個(gè)pub呢?


          在Rust中,默認(rèn)的所有函數(shù)或者模塊或者結(jié)構(gòu)體、枚舉等,都是private的,即只能自己或者同級(jí)調(diào)用,不可被其他地方使用,如果需要被其他地方調(diào)用,需要將其設(shè)置為公開的,即:pub


          比如,假設(shè)去掉pub


          編譯報(bào)錯(cuò)


          12a2a654e9635c06130161fd410483d0.webp


          那么有人可能會(huì)問,在main.rs中,是如何使用mod,將main_other引入到main.rs中的呢?


          這里,是因?yàn)?,在Rust中,src/main.rs為與包同名的二進(jìn)制crate根,這里的src/main_other.rs,為名為main_other<注,模塊名與文件同名>的crate根模塊,即兩者是平級(jí)的:


          a587559a18b2e4c9877034aae5ce38a5.webp


          所以,在main.rs中,可以直接使用mod,引入,但是由于main_other.rs中的main函數(shù)是私有的,所以在main.rs中,不可使用,所以報(bào)錯(cuò)。


          所以必須要改為pub



          此外,這里有一個(gè)比較重要的,容易出錯(cuò)的地方,那就是二進(jìn)制的crate庫,只能在當(dāng)前目錄下,通過mod方式引入module。至少當(dāng)前版本是這樣子的。


          這個(gè)地方跑得有些遠(yuǎn)了,這里需要實(shí)現(xiàn)擁有多個(gè)二進(jìn)制crate庫,


          那么現(xiàn)在一個(gè)目的就是如何將這個(gè)main_other.rs編程二進(jìn)制crate庫,因?yàn)楝F(xiàn)在它是個(gè)module


          在src下新建一個(gè)bin目錄,然后將這個(gè)main_other.rs移動(dòng)進(jìn)去看看會(huì)發(fā)生什么?


          4541ca2a65887e84991e9c6e18ed0ad5.webp


          這時(shí)候,可以看見這個(gè)main_other.rs也變成了一個(gè)二進(jìn)制的crate庫


          即:一個(gè)包中可以有多個(gè)二進(jìn)制crate


          接下來分析第一個(gè):一個(gè)包中最多只能包含一個(gè)庫crate


          回到項(xiàng)目的初始狀態(tài):


          5026e975984143d49d34f001e65794f9.webp


          這時(shí)候,在src下新建一個(gè)lib.rs


          d255a55919d29ad186d538d9d3576144.webp


          Rust約定:這個(gè)lib.rs就是一個(gè)和項(xiàng)目同名的crate庫


          在lib.rs中,定義兩個(gè)模塊兒:


          1530b1541d7b70c4807229136a23e3bb.webp



          這里描述下,在Rust中,模塊兒定義方式:


          mod 關(guān)鍵字然后一對(duì)大括號(hào),將模塊兒內(nèi)容寫入其中,模塊兒中,可以定義方法、結(jié)構(gòu)體、枚舉等。因?yàn)橄旅嫖覀冃枰{(diào)用這個(gè)lib.rs中的內(nèi)容,所以全部定義為pub的。



          然后在二進(jìn)制文件中調(diào)用這個(gè)lib.rs


          bb507742d6a230e2a4f81a7947997030.webp


          這里可以看見,在二進(jìn)制的Rust文件中,調(diào)用crate庫,需要用use + crate庫名,但是我這里用的是:use first_large_project;


          但是我們前面說到,Rust約定crate應(yīng)該是與包同名,這里的crate雖然不是二進(jìn)制的,難道就不是與包同名了么?


          顯然不是這樣的,不管是不是二進(jìn)制的crate,都是與包同名,但是因?yàn)檫@里寫上use first-large-project;Rust解析會(huì)報(bào)錯(cuò):


          81afcb345dcfd8e845f09d0f0b719004.webp



          因?yàn)楹完P(guān)鍵字沖突了,所以不能用-,這時(shí)候就提了一個(gè)醒,Rust包命名的時(shí)候,盡量不要用-,但是如果已經(jīng)用了怎么辦?比如上面我們這個(gè)項(xiàng)目??梢酝ㄟ^修改Cargo.toml文件的項(xiàng)目構(gòu)建信息來改變:


          比如這里:


          1d7af980dbcb81348ffe5d6662e45b12.webp


          然后包的crate庫就變成了,first_large_project


          所以就有了前面使用use first_large_project;將crate庫引入crate二進(jìn)制文件中。


          在lib.rs文件中,再定義一個(gè)函數(shù),函數(shù)調(diào)用

          lib_module_one.print_one和lib_module_two.print_two

          函數(shù)


          cc90522a5f8e9236aa61d4d99baa48ec.webp


          這里,可以看到直接通過

          lib_module_one::print_one()

          或者lib_module_two::print_two()

          完成了函數(shù)調(diào)用


          這是Rust語言中,通過相對(duì)路徑對(duì)模塊的引入,因?yàn)檫@里lib_module_one和print_one_and_two函數(shù)同屬一個(gè)層級(jí),即兩者是兄弟關(guān)系,所以可以直接通過相對(duì)路徑調(diào)用,當(dāng)然也可以通過絕對(duì)路徑來調(diào)用:


          比如:


          ca3c1d2b8cdf1c62885fce7595add159.webp



          絕對(duì)路徑,即通過關(guān)鍵字crate : : +module路徑來表示


          ?在二進(jìn)制crate庫中調(diào)用下:


          d78e85c4da3e0ea69080dd594a48bdfe.webp


          下面嘗試在lib_module_two中定義一個(gè)結(jié)構(gòu)體,同時(shí)定義結(jié)構(gòu)體函數(shù),修改函數(shù)print_two(),調(diào)用結(jié)構(gòu)體函數(shù):


          af8efd0778baecb6d52b19e8cc148572.webp


          這里沒有什么問題,在本模塊兒,初始化結(jié)構(gòu)體,同時(shí)調(diào)用函數(shù)。


          下面,修改lib_module_one::print_one()函數(shù),同時(shí)也想初始化這個(gè)結(jié)構(gòu)體,調(diào)用結(jié)構(gòu)體的函數(shù)。


          怎么做?


          這里在lib_module_one::print_one()函數(shù)中直接初始化這個(gè)結(jié)構(gòu)體肯定是不行的,因?yàn)檫@個(gè)結(jié)構(gòu)體并不在自己的作用域內(nèi),肯定是要引入的,當(dāng)然可通過絕對(duì)路徑引入,如:


          use crate::lib_module_two::LibModuleTwoStruct



          這里想要通過使用相對(duì)路徑,lib_module_two和lib_module_one是兄弟關(guān)系,所以只要引入到lib_module_two了,即很方便了。


          看下樹結(jié)構(gòu):


          174da82fae4e1977cb9118884b642b29.webp

          從上圖可以看出,在lib_module_one中,需要引入LibModuleTwoStruct,即通過父級(jí)達(dá)到crate根,然后可以找到lib_module_two,那么下面就簡(jiǎn)單了:


          79747da60fe451400ee8aac36c953fb0.webp

          ,然后lib_module_one,那么

          li看回放b_module_one

          這里使用了super關(guān)鍵字,找到父級(jí),然后找到需要的模塊,引入


          綜合上述代碼,看下lib.rs


          pub mod lib_module_one{    // use crate::lib_module_two::LibModuleTwoStruct;    use super::lib_module_two::LibModuleTwoStruct;    pub fn print_one(){        println!("print_one");        let lib_module_two_struct =  LibModuleTwoStruct{            name : String::from("lgli"),            age : 20        };        lib_module_two_struct.print_name();    }}
          pub mod lib_module_two{ pub fn print_two(){ println!("print_two"); let lib_module_two_struct = LibModuleTwoStruct{ name : String::from("lgli"), age : 18 }; lib_module_two_struct.print_name(); } pub struct LibModuleTwoStruct { pub name:String, pub age : i8 } impl LibModuleTwoStruct{ pub fn print_name(&self){ println!("姓名:{},年齡:{}",self.name,self.age); } }}
          pub fn print_one_and_two(){ lib_module_one::print_one(); lib_module_two::print_two();}
          pub mod lib_module_one{ // use crate::lib_module_two::LibModuleTwoStruct; use super::lib_module_two::LibModuleTwoStruct; pub fn print_one(){ println!("print_one"); let lib_module_two_struct = LibModuleTwoStruct{ name : String::from("lgli"), age : 20 }; lib_module_two_struct.print_name(); }}
          pub mod lib_module_two{ pub fn print_two(){ println!("print_two"); let lib_module_two_struct = LibModuleTwoStruct{ name : String::from("lgli"), age : 18 }; lib_module_two_struct.print_name(); } pub struct LibModuleTwoStruct { pub name:String, pub age : i8 } impl LibModuleTwoStruct{ pub fn print_name(&self){ println!("姓名:{},年齡:{}",self.name,self.age); } }}
          pub fn print_one_and_two(){ lib_module_one::print_one(); lib_module_two::print_two();}



          然后在二進(jìn)制的crate中調(diào)用運(yùn)行:


          27d2f4330969f29f2b6e31f51fd8965e.webp


          程序編譯運(yùn)行正常。


          下面,在src目錄下,新建一個(gè)out_module.rs文件,定義一個(gè)模塊兒,包含一個(gè)say_hello函數(shù):


          2884136ed88f60923b5e76fa94272433.webp


          這時(shí)候,在lib.rs中調(diào)用這個(gè)函數(shù):


          388cdaa6584fdc9fecf935ec3392e840.webp


          編譯運(yùn)行:


          fbd13e2442d3023f6f87a1dcc3871f22.webp


          調(diào)用成功,即這個(gè)地方的out_module就只能是一個(gè)模塊兒,而不能是一個(gè)crate庫,即:一個(gè)包中最多只能包含一個(gè)庫crate


          假設(shè)某種情況下,out_module是一個(gè)比較大,同時(shí)又是一個(gè)獨(dú)立的功能模塊兒,需要建文件夾將其封裝起來,這時(shí)候怎么弄?



          Rust提供了一種類似橋接方式,首先,在src下新建文件夾:module_dir


          1fcb02c4ec9481a644d075dacb87385e.webp


          在module_dir中新建Rust文件:mod.rs、a.rs


          b04d7aa72075ef421ab61e024d4645ff.webp


          其中src/module_dir/mod.rs文件可以視為模塊橋接,mod定義一個(gè)函數(shù),調(diào)用a.rs的函數(shù):


          9e62fc13a0378805baf34b940821084c.webp


          a.rs


          6caf7f59139d004a2aa0df9343d294f4.webp



          這時(shí)候,在根crate庫中,調(diào)用這個(gè)module_dir模塊


          lib.rs修改:


          c9260e2222123abe5f316da44e93b31e.webp


          編譯運(yùn)行:


          12ab8d9f6d39cd9123514956026e0c03.webp


          橋接成功??!


          一般來說,一個(gè)成熟的大型的項(xiàng)目,都會(huì)存在類似父項(xiàng)目中有子項(xiàng)目,在Rust中,也是可以的:


          將上述Rust項(xiàng)目作為一個(gè)父項(xiàng)目,新建一個(gè)子項(xiàng)目:



          56c84ac5fb0d5d67cc2e935d5ec20ad8.webp



          3d91b07911ec8d6ab3f1b614623a163d.webp


          這里選擇新建二進(jìn)制的Rust Crate,當(dāng)然也是可以選擇直接crate 庫。


          bbc601e73ddb363fc35422cfb939529b.webp



          這時(shí)候,可以看到,這個(gè)新的inner_one是一個(gè)可以獨(dú)立構(gòu)建的Rust包項(xiàng)目

          因?yàn)樗歇?dú)立的Cargo.toml文件


          上述步奏,如果新建一個(gè)crate庫,則就是包含一個(gè)lib.rs文件,看下兩者的區(qū)別:



          5b7bc7addbf567f62d7faf83b4126b6a.webp


          這里的inner_two是直接新建的一個(gè)crate庫,這里也就直接的說明了,二進(jìn)制的crate就是指main.rs,crate庫就是lib.rs


          然后下面要做的是在inner_two中引入父級(jí)包,然后調(diào)用父級(jí)包中的模塊函數(shù)



          首先在inner_two項(xiàng)目Cargo.toml文件中,添加父依賴:


          first_large_project = { path = "../../../first-large-project" }


          即:


          c20becc18190242074cdaf68c4d46544.webp


          first_large_project是父級(jí)項(xiàng)目構(gòu)建名字,前面已經(jīng)說了,在cargo.toml中修改了name,所以這里是first_large_project,這里的路徑和前面的名字,是一定要對(duì)應(yīng)上的



          這時(shí)候就可以在inner_two中使用first_large_project中的crate庫及其模塊了



          在inner_two的lib.rs文件中,引用模塊,調(diào)用函數(shù):


          9fa0e4b13b67359fb8cfd2dfb44ada27.webp


          下面在inner_one中,添加inner_two的依賴:


          614f5ddc2b7df8111a31c3169833b5ae.webp


          然后在main.rs中,引入inner_two,調(diào)用函數(shù):



          979c8296084a06eb1bb1925c0e6fba5f.webp


          編譯運(yùn)行inner_one的main函數(shù):


          db862425023b8565e9b810605271b850.webp


          因?yàn)閕nner_two實(shí)際調(diào)用的是

          lib_module_two::print_two()函數(shù),所以打印成功


          這里這么弱智的繞來繞去操作,僅僅是為了了解引用依賴,及其二進(jìn)制庫和crate庫的區(qū)別。


          這里添加依賴的方式,是通過路徑來添加的。當(dāng)然也可以通過其他方式,如前面舉例說到的git:


          fb230088c0f693c94b603286cd206778.webp


          這里需要記住的就是,前面的名字一定要和依賴Rust的構(gòu)建名字一樣!


          這里有一個(gè)小問題,如果有2個(gè)依賴的項(xiàng)目名字一樣了怎么辦?


          a944fcfbdedb50e65c30cd35ae129cbe.webp


          如上圖所示,這里添加了2個(gè)依賴,其都叫"rand",這個(gè)時(shí)候如何處理呢?



          Cargo?提供了依賴重命名,即前面的這個(gè)名字,默認(rèn)是依賴項(xiàng)目的構(gòu)建名,可以重新命名,但是需要指定package


          即:


          f9e2ae5be870d1ec6771ca1ef69a80aa.webp


          這個(gè)rand是在和inner_one同級(jí)目錄下新建的一個(gè)crate庫,僅僅包含了一個(gè)函數(shù)。:


          90b05f2a21f0a9e77ce044634e9327a1.webp



          這時(shí)候,在inner_one的二進(jìn)制庫中引入這個(gè)my_rand,同時(shí)調(diào)用其say_rand函數(shù):


          9c6fb2930d8f64512bdf8e895102e9ad.webp



          總結(jié)一下前面說的內(nèi)容


          cargo.toml和cargo.lock


          Rust3個(gè)重要約束?


          二進(jìn)制crate和crate庫的區(qū)別?


          module引入到二進(jìn)制crate


          module引入到crate庫


          use、mod、pub等關(guān)鍵字的使用


          絕對(duì)路徑和相對(duì)路徑


          cargo-dependencies重命名引包


          上面這些問題,在本文中均是涵蓋了的,如果沒有什么印象了,可以回頭看看!



          點(diǎn)擊下面公眾號(hào)獲取更多


          歡迎點(diǎn)贊轉(zhuǎn)發(fā),謝謝

          瀏覽 96
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91爱在线 | 欧美精品99久久导航 | 日韩无码一区二 | 青青草原视频精品在线免费观看 | 性爱少妇高手无码 |