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

鏈接進(jìn)階

advanced-linking.md
commit 024aa9a345e92aa1926517c4d9b16bd83e74c10d

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

鏈接參數(shù)

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

#![feature(link_args)]

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

注意現(xiàn)在這個(gè)功能隱藏在feature(link_args)gate 之后因?yàn)樗⒉皇且粋€(gè)被認(rèn)可的執(zhí)行鏈接的方法。目前 rustc 從 shell 調(diào)用系統(tǒng)的連接器(大多數(shù)系統(tǒng)是gcc,MSVC 是link.exe),所以使用額外的命令行參數(shù)是可行的,不過(guò)這并一定永遠(yuǎn)可行。將來(lái) rustc 可能使用 LLVM 直接鏈接原生庫(kù)這樣一來(lái)link_args就毫無(wú)意義了。你可以向rustc傳遞-C link-args參數(shù)來(lái)獲得和link_args屬性同樣的效果。

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

靜態(tài)鏈接

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

鏈接是一個(gè)非常依賴(lài)平臺(tái)的問(wèn)題--在一些平臺(tái)上,靜態(tài)鏈接可能根本就是不可能的!這個(gè)部分假設(shè)你對(duì)你選擇的平臺(tái)的鏈接一些基礎(chǔ)的認(rèn)識(shí)。

Linux

在 Linux 上 Rust 程默認(rèn)會(huì)鏈接系統(tǒng)的libc以及一些其他的庫(kù)。讓我們看看一個(gè)使用 GCC 和glibc的 64 位 Linux(目前為止 Linux 上最常見(jiàn)的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)在你有了一個(gè)啟用了musl的Rust!因?yàn)槲覀冇昧艘粋€(gè)自定義的目錄,當(dāng)我們嘗試并運(yùn)行它的時(shí)候我們需要確保我們的系統(tǒng)能夠找到二進(jìn)制文件和正確的庫(kù):

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

讓我們?cè)囈幌拢?/p>

$ 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

成功了!這個(gè)二進(jìn)制文件可以被拷貝到幾乎所有擁有相同構(gòu)架的 Linux 機(jī)器上無(wú)故障的運(yùn)行。

cargo build也允許--target選項(xiàng)所以你也能用它來(lái)正常的構(gòu)建你的 crate。然而,你可能需要先鏈接你的原生庫(kù)到musl,在你可以鏈接到它之前。

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