about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/reference.md4
-rw-r--r--src/doc/trpl/SUMMARY.md2
-rw-r--r--src/doc/trpl/advanced-linking.md151
-rw-r--r--src/doc/trpl/link-args.md25
4 files changed, 156 insertions, 26 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index a37e1c14668..26fd2fd8d20 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -1636,6 +1636,10 @@ The type of a function declared in an extern block is `extern "abi" fn(A1, ...,
 An) -> R`, where `A1...An` are the declared types of its arguments and `R` is
 the declared return type.
 
+It is valid to add the `link` attribute on an empty extern block. You can use
+this to satisfy the linking requirements of extern blocks elsewhere in your code
+(including upstream crates) instead of adding the attribute to each extern block.
+
 ## Visibility and Privacy
 
 These two terms are often used interchangeably, and what they are attempting to
diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md
index ca3381ffba4..f1e51591aea 100644
--- a/src/doc/trpl/SUMMARY.md
+++ b/src/doc/trpl/SUMMARY.md
@@ -63,7 +63,7 @@
     * [No stdlib](no-stdlib.md)
     * [Intrinsics](intrinsics.md)
     * [Lang items](lang-items.md)
-    * [Link args](link-args.md)
+    * [Advanced linking](advanced-linking.md)
     * [Benchmark Tests](benchmark-tests.md)
     * [Box Syntax and Patterns](box-syntax-and-patterns.md)
     * [Slice Patterns](slice-patterns.md)
diff --git a/src/doc/trpl/advanced-linking.md b/src/doc/trpl/advanced-linking.md
new file mode 100644
index 00000000000..6d370433542
--- /dev/null
+++ b/src/doc/trpl/advanced-linking.md
@@ -0,0 +1,151 @@
+% Advanced Linking
+
+The common cases of linking with Rust have been covered earlier in this book,
+but supporting the range of linking possibilities made available by other
+languages is important for Rust to achieve seamless interaction with native
+libraries.
+
+# Link args
+
+There is one other way to tell `rustc` how to customize linking, and that is via
+the `link_args` attribute. This attribute is applied to `extern` blocks and
+specifies raw flags which need to get passed to the linker when producing an
+artifact. An example usage would be:
+
+``` no_run
+#![feature(link_args)]
+
+#[link_args = "-foo -bar -baz"]
+extern {}
+# fn main() {}
+```
+
+Note that this feature is currently hidden behind the `feature(link_args)` gate
+because this is not a sanctioned way of performing linking. Right now `rustc`
+shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
+so it makes sense to provide extra command line
+arguments, but this will not always be the case. In the future `rustc` may use
+LLVM directly to link native libraries, in which case `link_args` will have no
+meaning. You can achieve the same effect as the `link-args` attribute with the
+`-C link-args` argument to `rustc`.
+
+It is highly recommended to *not* use this attribute, and rather use the more
+formal `#[link(...)]` attribute on `extern` blocks instead.
+
+# Static linking
+
+Static linking refers to the process of creating output that contain all
+required libraries and so don't need libraries installed on every system where
+you want to use your compiled project. Pure-Rust dependencies are statically
+linked by default so you can use created binaries and libraries without
+installing the Rust everywhere. By contrast, native libraries
+(e.g. `libc` and `libm`) usually dynamically linked, but it is possible to
+change this and statically link them as well.
+
+Linking is a very platform dependent topic — on some platforms, static linking
+may not be possible at all! This section assumes some basic familiarity with
+linking on your platform of choice.
+
+## Linux
+
+By default, all Rust programs on Linux will link to the system `libc` along with
+a number of other libraries. Let's look at an example on a 64-bit Linux machine
+with GCC and `glibc` (by far the most common `libc` on Linux):
+
+``` text
+$ cat example.rs
+fn main() {}
+$ rustc example.rs
+$ ldd example
+        linux-vdso.so.1 =>  (0x00007ffd565fd000)
+        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000)
+        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000)
+        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000)
+        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000)
+        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000)
+        /lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000)
+        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000)
+```
+
+Dynamic linking on Linux can be undesirable if you wish to use new library
+features on old systems or target systems which do not have the required
+dependencies for your program to run.
+
+Static linking is supported via an alternative `libc`, `musl` - this must be
+enabled at Rust compile-time with some prerequisites available. You can compile
+your own version of Rust with `musl` enabled and install it into a custom
+directory with the instructions below:
+
+```text
+$ mkdir musldist
+$ PREFIX=$(pwd)/musldist
+$
+$ # Build musl
+$ wget 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
+$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz
+$ tar xf llvm-3.6.1.src.tar.xz
+$ cd llvm-3.6.1.src/projects/
+llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi
+llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind
+llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt
+llvm-3.6.1.src/projects $ mkdir libunwind/build
+llvm-3.6.1.src/projects $ cd libunwind/build
+llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
+llvm-3.6.1.src/projects/libunwind/build $ make
+llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
+llvm-3.6.1.src/projects/libunwind/build $ cd 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
+```
+
+You now have a build of a `musl`-enabled Rust! Because we've installed it to a
+custom prefix we need to make sure our system can the binaries and appropriate
+libraries when we try and run it:
+
+```text
+$ export PATH=$PREFIX/bin:$PATH
+$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
+```
+
+Let's try it out!
+
+```text
+$ 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
+```
+
+Success! This binary can be copied to almost any Linux machine with the same
+machine architecture and run without issues.
+
+`cargo build` also permits the `--target` option so you should be able to build
+your crates as normal. However, you may need to recompile your native libraries
+against `musl` before they can be linked against.
diff --git a/src/doc/trpl/link-args.md b/src/doc/trpl/link-args.md
deleted file mode 100644
index cdaef6cd9b5..00000000000
--- a/src/doc/trpl/link-args.md
+++ /dev/null
@@ -1,25 +0,0 @@
-% Link args
-
-There is one other way to tell rustc how to customize linking, and that is via
-the `link_args` attribute. This attribute is applied to `extern` blocks and
-specifies raw flags which need to get passed to the linker when producing an
-artifact. An example usage would be:
-
-``` no_run
-#![feature(link_args)]
-
-#[link_args = "-foo -bar -baz"]
-extern {}
-# fn main() {}
-```
-
-Note that this feature is currently hidden behind the `feature(link_args)` gate
-because this is not a sanctioned way of performing linking. Right now rustc
-shells out to the system linker, so it makes sense to provide extra command line
-arguments, but this will not always be the case. In the future rustc may use
-LLVM directly to link native libraries, in which case `link_args` will have no
-meaning.
-
-It is highly recommended to *not* use this attribute, and rather use the more
-formal `#[link(...)]` attribute on `extern` blocks instead.
-