鍍金池/ 教程/ Java/ 鏈接進階
哲學家就餐問題
鏈接進階
名詞中英文對照
測試
引用和借用
泛型
方法語法
函數(shù)
不安全代碼
并發(fā)
裝箱語法和模式
注釋
棧和堆
運算符與重載
語法索引
文檔
固有功能
所有權
循環(huán)
通用函數(shù)調用語法
不定長類型
<code>const</code> 和 <code>static</code>
迭代器
其他語言中的 Rust
枚舉
詞匯表
If語句
猜猜看
錯誤處理
生命周期
編譯器插件
發(fā)布途徑
閉包
trait 對象
不使用標準庫
關聯(lián)常量
外部函數(shù)接口(FFI)
類型轉換
原生類型
匹配
參考文獻
Rust 編程語言
內聯(lián)匯編
條件編譯
選擇你的保證
學習 Rust
`type`別名
自定義內存分配器
屬性
if let
高效 Rust
可變性
語法和語義
模式
基準測試
結構體
變量綁定
語言項
切片模式
<code>Deref</code> 強制多態(tài)
關聯(lián)類型
裸指針
<code>Borrow</code> 和 <code>AsRef</code>
準備
Rust 開發(fā)版
字符串

鏈接進階

advanced-linking.md
commit 024aa9a345e92aa1926517c4d9b16bd83e74c10d

Rust 的常用鏈接形式在本書的之前部分已經(jīng)介紹過了,不過支持多種其他語言可用的可能的鏈接對 Rust 獲取與原生庫的無縫交互是很重要的。

鏈接參數(shù)

這里還有一個方法來告訴 rustc 如何自定義鏈接,這就是通過link_args屬性。這個屬性作用于extern塊并指定當產(chǎn)生構件時需要傳遞給連接器的原始標記。一個用例將是:

#![feature(link_args)]

#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}

注意現(xiàn)在這個功能隱藏在feature(link_args)gate 之后因為它并不是一個被認可的執(zhí)行鏈接的方法。目前 rustc 從 shell 調用系統(tǒng)的連接器(大多數(shù)系統(tǒng)是gcc,MSVC 是link.exe),所以使用額外的命令行參數(shù)是可行的,不過這并一定永遠可行。將來 rustc 可能使用 LLVM 直接鏈接原生庫這樣一來link_args就毫無意義了。你可以向rustc傳遞-C link-args參數(shù)來獲得和link_args屬性同樣的效果。

強烈建議你不要使用這個屬性,而是使用一個更正式的[link(...)]屬性作用于extern塊。

靜態(tài)鏈接

靜態(tài)鏈接代表創(chuàng)建包含所有所需庫的輸出的過程,這樣你在任何系統(tǒng)上使用你編譯的項目時就不需要安裝相應的庫了。純 Rust 的依賴默認都是靜態(tài)鏈接的這樣你可以使用你創(chuàng)建的二進制和庫而不需要安裝 Rust。相反,原生庫(例如,libclibm)通常是動態(tài)鏈接的,不過也可以修改為靜態(tài)鏈接。

鏈接是一個非常依賴平臺的問題--在一些平臺上,靜態(tài)鏈接可能根本就是不可能的!這個部分假設你對你選擇的平臺的鏈接一些基礎的認識。

Linux

在 Linux 上 Rust 程默認會鏈接系統(tǒng)的libc以及一些其他的庫。讓我們看看一個使用 GCC 和glibc的 64 位 Linux(目前為止 Linux 上最常見的libc)的例子:

$ mkdir musldist
$ PREFIX=$(pwd)/musldist
$
$ # Build musl
$ curl -O http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
$ tar xf musl-1.1.10.tar.gz
$ cd musl-1.1.10/
musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
musl-1.1.10 $ make
musl-1.1.10 $ make install
musl-1.1.10 $ cd ..
$ du -h musldist/lib/libc.a
2.2M    musldist/lib/libc.a
$
$ # Build libunwind.a
$ curl -O http://llvm.org/releases/3.7.0/llvm-3.7.0.src.tar.xz
$ tar xf llvm-3.7.0.src.tar.xz
$ cd llvm-3.7.0.src/projects/
llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libunwind-3.7.0.src.tar.xz | tar xJf -
llvm-3.7.0.src/projects $ mv libunwind-3.7.0.src libunwind
llvm-3.7.0.src/projects $ mkdir libunwind/build
llvm-3.7.0.src/projects $ cd libunwind/build
llvm-3.7.0.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
llvm-3.7.0.src/projects/libunwind/build $ make
llvm-3.7.0.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
llvm-3.7.0.src/projects/libunwind/build $ cd ../../../../
$ du -h musldist/lib/libunwind.a
164K    musldist/lib/libunwind.a
$
$ # Build musl-enabled rust
$ git clone https://github.com/rust-lang/rust.git muslrust
$ cd muslrust
muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
muslrust $ make
muslrust $ make install
muslrust $ cd ..
$ du -h musldist/bin/rustc
12K     musldist/bin/rustc

現(xiàn)在你有了一個啟用了musl的Rust!因為我們用了一個自定義的目錄,當我們嘗試并運行它的時候我們需要確保我們的系統(tǒng)能夠找到二進制文件和正確的庫:

$ export PATH=$PREFIX/bin:$PATH
$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH

讓我們試一下!

$ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
$ rustc --target=x86_64-unknown-linux-musl example.rs
$ ldd example
        not a dynamic executable
$ ./example
hi!
thread '<main>' panicked at 'failed', example.rs:1

成功了!這個二進制文件可以被拷貝到幾乎所有擁有相同構架的 Linux 機器上無故障的運行。

cargo build也允許--target選項所以你也能用它來正常的構建你的 crate。然而,你可能需要先鏈接你的原生庫到musl,在你可以鏈接到它之前。

上一篇:選擇你的保證下一篇:模式