]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/advanced-linking.md
libcxxabi is no longer necessary for libunwind
[rust.git] / src / doc / trpl / advanced-linking.md
1 % Advanced Linking
2
3 The common cases of linking with Rust have been covered earlier in this book,
4 but supporting the range of linking possibilities made available by other
5 languages is important for Rust to achieve seamless interaction with native
6 libraries.
7
8 # Link args
9
10 There is one other way to tell `rustc` how to customize linking, and that is via
11 the `link_args` attribute. This attribute is applied to `extern` blocks and
12 specifies raw flags which need to get passed to the linker when producing an
13 artifact. An example usage would be:
14
15 ``` no_run
16 #![feature(link_args)]
17
18 #[link_args = "-foo -bar -baz"]
19 extern {}
20 # fn main() {}
21 ```
22
23 Note that this feature is currently hidden behind the `feature(link_args)` gate
24 because this is not a sanctioned way of performing linking. Right now `rustc`
25 shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
26 so it makes sense to provide extra command line
27 arguments, but this will not always be the case. In the future `rustc` may use
28 LLVM directly to link native libraries, in which case `link_args` will have no
29 meaning. You can achieve the same effect as the `link-args` attribute with the
30 `-C link-args` argument to `rustc`.
31
32 It is highly recommended to *not* use this attribute, and rather use the more
33 formal `#[link(...)]` attribute on `extern` blocks instead.
34
35 # Static linking
36
37 Static linking refers to the process of creating output that contains all
38 required libraries and so doesn't need libraries installed on every system where
39 you want to use your compiled project. Pure-Rust dependencies are statically
40 linked by default so you can use created binaries and libraries without
41 installing Rust everywhere. By contrast, native libraries
42 (e.g. `libc` and `libm`) are usually dynamically linked, but it is possible to
43 change this and statically link them as well.
44
45 Linking is a very platform-dependent topic, and static linking may not even be
46 possible on some platforms! This section assumes some basic familiarity with
47 linking on your platform of choice.
48
49 ## Linux
50
51 By default, all Rust programs on Linux will link to the system `libc` along with
52 a number of other libraries. Let's look at an example on a 64-bit Linux machine
53 with GCC and `glibc` (by far the most common `libc` on Linux):
54
55 ``` text
56 $ cat example.rs
57 fn main() {}
58 $ rustc example.rs
59 $ ldd example
60         linux-vdso.so.1 =>  (0x00007ffd565fd000)
61         libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000)
62         libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000)
63         librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000)
64         libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000)
65         libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000)
66         /lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000)
67         libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000)
68 ```
69
70 Dynamic linking on Linux can be undesirable if you wish to use new library
71 features on old systems or target systems which do not have the required
72 dependencies for your program to run.
73
74 Static linking is supported via an alternative `libc`, `musl`. You can compile
75 your own version of Rust with `musl` enabled and install it into a custom
76 directory with the instructions below:
77
78 ```text
79 $ mkdir musldist
80 $ PREFIX=$(pwd)/musldist
81 $
82 $ # Build musl
83 $ curl -O http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
84 $ tar xf musl-1.1.10.tar.gz
85 $ cd musl-1.1.10/
86 musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
87 musl-1.1.10 $ make
88 musl-1.1.10 $ make install
89 musl-1.1.10 $ cd ..
90 $ du -h musldist/lib/libc.a
91 2.2M    musldist/lib/libc.a
92 $
93 $ # Build libunwind.a
94 $ curl -O http://llvm.org/releases/3.7.0/llvm-3.7.0.src.tar.xz
95 $ tar xf llvm-3.7.0.src.tar.xz
96 $ cd llvm-3.7.0.src/projects/
97 llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libunwind-3.7.0.src.tar.xz | tar xJf -
98 llvm-3.7.0.src/projects $ mv libunwind-3.7.0.src libunwind
99 llvm-3.7.0.src/projects $ mkdir libunwind/build
100 llvm-3.7.0.src/projects $ cd libunwind/build
101 llvm-3.7.0.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
102 llvm-3.7.0.src/projects/libunwind/build $ make
103 llvm-3.7.0.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
104 llvm-3.7.0.src/projects/libunwind/build $ cd ../../../../
105 $ du -h musldist/lib/libunwind.a
106 164K    musldist/lib/libunwind.a
107 $
108 $ # Build musl-enabled rust
109 $ git clone https://github.com/rust-lang/rust.git muslrust
110 $ cd muslrust
111 muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
112 muslrust $ make
113 muslrust $ make install
114 muslrust $ cd ..
115 $ du -h musldist/bin/rustc
116 12K     musldist/bin/rustc
117 ```
118
119 You now have a build of a `musl`-enabled Rust! Because we've installed it to a
120 custom prefix we need to make sure our system can find the binaries and appropriate
121 libraries when we try and run it:
122
123 ```text
124 $ export PATH=$PREFIX/bin:$PATH
125 $ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
126 ```
127
128 Let's try it out!
129
130 ```text
131 $ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
132 $ rustc --target=x86_64-unknown-linux-musl example.rs
133 $ ldd example
134         not a dynamic executable
135 $ ./example
136 hi!
137 thread '<main>' panicked at 'failed', example.rs:1
138 ```
139
140 Success! This binary can be copied to almost any Linux machine with the same
141 machine architecture and run without issues.
142
143 `cargo build` also permits the `--target` option so you should be able to build
144 your crates as normal. However, you may need to recompile your native libraries
145 against `musl` before they can be linked against.