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
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:
16 #![feature(link_args)]
18 #[link_args = "-foo -bar -baz"]
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`.
32 It is highly recommended to *not* use this attribute, and rather use the more
33 formal `#[link(...)]` attribute on `extern` blocks instead.
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.
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.
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):
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)
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.
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:
80 $ PREFIX=$(pwd)/musldist
83 $ curl -O http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
84 $ tar xf musl-1.1.10.tar.gz
86 musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
88 musl-1.1.10 $ make install
90 $ du -h musldist/lib/libc.a
91 2.2M musldist/lib/libc.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
108 $ # Build musl-enabled rust
109 $ git clone https://github.com/rust-lang/rust.git muslrust
111 muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
113 muslrust $ make install
115 $ du -h musldist/bin/rustc
116 12K musldist/bin/rustc
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:
124 $ export PATH=$PREFIX/bin:$PATH
125 $ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
131 $ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
132 $ rustc --target=x86_64-unknown-linux-musl example.rs
134 not a dynamic executable
137 thread '<main>' panicked at 'failed', example.rs:1
140 Success! This binary can be copied to almost any Linux machine with the same
141 machine architecture and run without issues.
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.