# 鏈接進階
> [advanced-linking.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/advanced-linking.md)
commit 024aa9a345e92aa1926517c4d9b16bd83e74c10d
Rust 的常用鏈接形式在本書的之前部分已經介紹過了,不過支持多種其他語言可用的可能的鏈接對 Rust 獲取與原生庫的無縫交互是很重要的。
### 鏈接參數
這里還有一個方法來告訴 rustc 如何自定義鏈接,這就是通過`link_args`屬性。這個屬性作用于`extern`塊并指定當產生構件時需要傳遞給連接器的原始標記。一個用例將是:
~~~
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
~~~
注意現在這個功能隱藏在`feature(link_args)`gate 之后因為它并不是一個被認可的執行鏈接的方法。目前 rustc 從 shell 調用系統的連接器(大多數系統是`gcc`,MSVC 是`link.exe`),所以使用額外的命令行參數是可行的,不過這并一定永遠可行。將來 rustc 可能使用 LLVM 直接鏈接原生庫這樣一來`link_args`就毫無意義了。你可以向`rustc`傳遞`-C link-args`參數來獲得和`link_args`屬性同樣的效果。
強烈建議你*不要*使用這個屬性,而是使用一個更正式的`[link(...)]`屬性作用于`extern`塊。
### 靜態鏈接
靜態鏈接代表創建包含所有所需庫的輸出的過程,這樣你在任何系統上使用你編譯的項目時就不需要安裝相應的庫了。純 Rust 的依賴默認都是靜態鏈接的這樣你可以使用你創建的二進制和庫而不需要安裝 Rust。相反,原生庫(例如,`libc`和`libm`)通常是動態鏈接的,不過也可以修改為靜態鏈接。
鏈接是一個非常依賴平臺的問題--在一些平臺上,靜態鏈接可能根本就是不可能的!這個部分假設你對你選擇的平臺的鏈接一些基礎的認識。
### Linux
在 Linux 上 Rust 程默認會鏈接系統的`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
~~~
現在你有了一個啟用了`musl`的Rust!因為我們用了一個自定義的目錄,當我們嘗試并運行它的時候我們需要確保我們的系統能夠找到二進制文件和正確的庫:
~~~
$ 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`,在你可以鏈接到它之前。
- 前言
- 貢獻者
- 1.介紹
- 2.準備
- 3.學習 Rust
- 3.1.猜猜看
- 3.2.哲學家就餐問題
- 3.3.其它語言中的 Rust
- 4.語法和語義
- 4.1.變量綁定
- 4.2.函數
- 4.3.原生類型
- 4.4.注釋
- 4.5.If語句
- 4.6.循環
- 4.7.所有權
- 4.8.引用和借用
- 4.9.生命周期
- 4.10.可變性
- 4.11.結構體
- 4.12.枚舉
- 4.13.匹配
- 4.14.模式
- 4.15.方法語法
- 4.16.Vectors
- 4.17.字符串
- 4.18.泛型
- 4.19.Traits
- 4.20.Drop
- 4.21.if let
- 4.22.trait 對象
- 4.23.閉包
- 4.24.通用函數調用語法
- 4.25.crate 和模塊
- 4.26.const和static
- 4.27.屬性
- 4.28.type別名
- 4.29.類型轉換
- 4.30.關聯類型
- 4.31.不定長類型
- 4.32.運算符和重載
- 4.33.Deref強制多態
- 4.34.宏
- 4.35.裸指針
- 4.36.不安全代碼
- 5.高效 Rust
- 5.1.棧和堆
- 5.2.測試
- 5.3.條件編譯
- 5.4.文檔
- 5.5.迭代器
- 5.6.并發
- 5.7.錯誤處理
- 5.8.選擇你的保證
- 5.9.外部函數接口
- 5.10.Borrow 和 AsRef
- 5.11.發布途徑
- 5.12.不使用標準庫
- 6.Rust 開發版
- 6.1.編譯器插件
- 6.2.內聯匯編
- 6.4.固有功能
- 6.5.語言項
- 6.6.鏈接進階
- 6.7.基準測試
- 6.8.裝箱語法和模式
- 6.9.切片模式
- 6.10.關聯常量
- 6.11.自定義內存分配器
- 7.詞匯表
- 8.語法索引
- 9.參考文獻
- 附錄:名詞中英文對照