Rust 中的 bin, lib, rlib, a, so 概念介紹


 

寫了這么久的 Rust 代碼了,可能很多人還對 Rust 的編譯后的文件格式不是很清晰。本篇我們就來理一下,Rust 中的 bin, lib, rlib, a, so 是什么,如何生成,以及其它一些細節。

從 cargo new 說起

我們創建一個新工程,通常從下面兩句入手:

cargo new foobar 

cargo new --lib foobar 

前者創建一個可執行工程,而后者創建一個庫工程。

實際上,你去探索上述命令行生成的文件,發現它們的 Cargo.toml 完全一樣,區別僅在於 src 目錄下,可執行工程是一個 main.rs,而庫工程是一個 lib.rs。

這是因為 main.rs 和 lib.rs 對於一個 crate 來講,是兩個特殊的文件名。rustc 內置了對這兩個特殊文件名的處理(當然也可以通過 Cargo.toml 進行配置,不詳談),我們可以認為它們就是一個 crate 的入口。

可執行 crate 和庫 crate 是兩種不同的 crate。下面我們就來一並說一下它們的兄弟姐妹及其之間的異同。

crate type

執行

rustc --help|grep crate-type 

可得到如下輸出

       --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] 

才發現,原來有這么多種 crate type。下面挨個看一下。

bin

二進制可執行 crate,編譯出的文件為二進制可執行文件。必須要有 main 函數作為入口。這種 crate 不需要在 Cargo.toml 中或 --crate-type 命令行參數中指定,會自動識別。

lib

庫 crate。它其實並不是一種具體的庫,它指代后面各種庫 crate 中的一種,可以認為是一個代理名稱(alias)。

通常來講,如果什么都不配置,默認指的是 rlib, 會生成 .rlib 的文件。

rlib

rlib 是 Rust Library 特定靜態中間庫格式。如果只是純 Rust 代碼項目之間的依賴和調用,那么,用 rlib 就能完全滿足使用需求。

rlib 實現為一個 ar 歸檔文件。

> file target/debug/libfoobar.rlib target/debug/libfoobar.rlib: current ar archive 

rlib 中包含很多 metadata 信息(比如可能的上游依賴信息),用來做后面的 linkage。

在 Cargo.toml 中配置:

[lib] name = "foobar" crate-type = ["rlib"] 

可以指定生成 rlib,但是一般沒必要設置,因為默認 lib 就是 rlib。

rlib 是平台(Linux, MacOS, Windows ...)無關的。

dylib

動態庫。

在 Cargo.toml 中配置:

[lib] name = "foobar" crate-type = ["dylib"] 

會在編譯的時候,生成動態庫(Linux 上為 .so, MacOS 上為 .dylib, Windows 上為 .dll)。

動態庫是平台相關的庫。動態庫在被依賴並鏈接時,不會被鏈接到目標文件中。這種動態庫只能被 Rust 寫的程序(或遵循 Rust 內部不穩定的規范的程序)調用。這個動態庫可能依賴於其它動態庫(比如,Linux 下用 C 語言寫的 PostgreSQL 的 libpq.so,或者另一個編譯成 "dylib" 的 Rust 動態庫)。

cdylib

C規范動態庫。

在 Cargo.toml 中配置:

[lib] name = "foobar" crate-type = ["cdylib"] 

與 dylib 類似,也會生成 .so, .dylib 或 .dll 文件。但是這種動態庫可以被其它語言調用(因為幾乎所有語言都有遵循 C 規范的 FFI 實現),也就是跨語言 FFI 使用。這個動態庫可能依賴於其它動態庫(比如,Linux 下用 C 語言寫的 PostgreSQL 的 libpq.so)。

staticlib

靜態庫。

在 Cargo.toml 中配置:

[lib] name = "foobar" crate-type = ["staticlib"] 

編譯會生成 .a 文件(在 Linux 和 MacOS 上),或 .lib 文件(在 Windows 上)。

編譯器會把所有實現的 Rust 庫代碼以及依賴的庫代碼全部編譯到一個靜態庫文件中,也就是對外界不產生任何依賴了。這特別適合將 Rust 實現的功能封裝好給第三方應用使用。

proc-macro

過程宏 crate.

在 Cargo.toml 中配置:

[lib] name = "foobar" crate-type = ["proc-macro"] 

這種 crate 里面只能導出過程宏,被導出的過程宏可以被其它 crate 引用。


Crate type 以及它們之間的區別就介紹到這里了,有些細節還是需要仔細理解的。本篇意在闡述一些基礎知識,而不打算成為一篇完整的參考文件,如要查看 Rust Linkage 的詳細內容,直接訪問 Rust Reference。

https://doc.rust-lang.org/reference/linkage.html

這一篇帖子非常有用:

https://users.rust-lang.org/t/what-is-the-difference-between-dylib-and-cdylib/28847

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM