Skip to content

Commit 84f60dd

Browse files
committed
---
yaml --- r: 235783 b: refs/heads/stable c: a75c21f h: refs/heads/master i: 235781: 0187606 235779: 3e7b5fa 235775: 072bc97 v: v3
1 parent 18c1707 commit 84f60dd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1707
-354
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ refs/heads/tmp: afae2ff723393b3ab4ccffef6ac7c6d1809e2da0
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f
3030
refs/tags/homu-tmp: f859507de8c410b648d934d8f5ec1c52daac971d
3131
refs/tags/1.0.0-beta: 8cbb92b53468ee2b0c2d3eeb8567005953d40828
32-
refs/heads/stable: e66817512a414d1665e37e6016a6fc06522fb2e0
32+
refs/heads/stable: a75c21fc9cf970c0a4372c2e4c5f3b770050f26f
3333
refs/tags/1.0.0: 55bd4f8ff2b323f317ae89e254ce87162d52a375
3434
refs/tags/1.1.0: bc3c16f09287e5545c1d3f76b7abd54f2eca868b
3535
refs/tags/1.2.0: f557861f822c34f07270347b94b5280de20a597e

branches/stable/src/doc/reference.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,10 @@ The type of a function declared in an extern block is `extern "abi" fn(A1, ...,
16361636
An) -> R`, where `A1...An` are the declared types of its arguments and `R` is
16371637
the declared return type.
16381638

1639+
It is valid to add the `link` attribute on an empty extern block. You can use
1640+
this to satisfy the linking requirements of extern blocks elsewhere in your code
1641+
(including upstream crates) instead of adding the attribute to each extern block.
1642+
16391643
## Visibility and Privacy
16401644

16411645
These two terms are often used interchangeably, and what they are attempting to

branches/stable/src/doc/trpl/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
* [No stdlib](no-stdlib.md)
6464
* [Intrinsics](intrinsics.md)
6565
* [Lang items](lang-items.md)
66-
* [Link args](link-args.md)
66+
* [Advanced linking](advanced-linking.md)
6767
* [Benchmark Tests](benchmark-tests.md)
6868
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
6969
* [Slice Patterns](slice-patterns.md)
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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 contain all
38+
required libraries and so don'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 the Rust everywhere. By contrast, native libraries
42+
(e.g. `libc` and `libm`) 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 — on some platforms, static linking
46+
may not be possible at all! 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` - this must be
75+
enabled at Rust compile-time with some prerequisites available. You can compile
76+
your own version of Rust with `musl` enabled and install it into a custom
77+
directory with the instructions below:
78+
79+
```text
80+
$ mkdir musldist
81+
$ PREFIX=$(pwd)/musldist
82+
$
83+
$ # Build musl
84+
$ wget http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
85+
[...]
86+
$ tar xf musl-1.1.10.tar.gz
87+
$ cd musl-1.1.10/
88+
musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
89+
[...]
90+
musl-1.1.10 $ make
91+
[...]
92+
musl-1.1.10 $ make install
93+
[...]
94+
musl-1.1.10 $ cd ..
95+
$ du -h musldist/lib/libc.a
96+
2.2M musldist/lib/libc.a
97+
$
98+
$ # Build libunwind.a
99+
$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz
100+
$ tar xf llvm-3.6.1.src.tar.xz
101+
$ cd llvm-3.6.1.src/projects/
102+
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi
103+
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind
104+
llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt
105+
llvm-3.6.1.src/projects $ mkdir libunwind/build
106+
llvm-3.6.1.src/projects $ cd libunwind/build
107+
llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
108+
llvm-3.6.1.src/projects/libunwind/build $ make
109+
llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
110+
llvm-3.6.1.src/projects/libunwind/build $ cd cd ../../../../
111+
$ du -h musldist/lib/libunwind.a
112+
164K musldist/lib/libunwind.a
113+
$
114+
$ # Build musl-enabled rust
115+
$ git clone https://github.com/rust-lang/rust.git muslrust
116+
$ cd muslrust
117+
muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
118+
muslrust $ make
119+
muslrust $ make install
120+
muslrust $ cd ..
121+
$ du -h musldist/bin/rustc
122+
12K musldist/bin/rustc
123+
```
124+
125+
You now have a build of a `musl`-enabled Rust! Because we've installed it to a
126+
custom prefix we need to make sure our system can the binaries and appropriate
127+
libraries when we try and run it:
128+
129+
```text
130+
$ export PATH=$PREFIX/bin:$PATH
131+
$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
132+
```
133+
134+
Let's try it out!
135+
136+
```text
137+
$ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
138+
$ rustc --target=x86_64-unknown-linux-musl example.rs
139+
$ ldd example
140+
not a dynamic executable
141+
$ ./example
142+
hi!
143+
thread '<main>' panicked at 'failed', example.rs:1
144+
```
145+
146+
Success! This binary can be copied to almost any Linux machine with the same
147+
machine architecture and run without issues.
148+
149+
`cargo build` also permits the `--target` option so you should be able to build
150+
your crates as normal. However, you may need to recompile your native libraries
151+
against `musl` before they can be linked against.

branches/stable/src/doc/trpl/link-args.md

Lines changed: 0 additions & 25 deletions
This file was deleted.

branches/stable/src/doc/trpl/while-loops.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,24 @@ for x in 0..10 {
8888
}
8989
```
9090

91+
You may also encounter situations where you have nested loops and need to
92+
specify which one your `break` or `continue` statement is for. Like most
93+
other languages, by default a `break` or `continue` will apply to innermost
94+
loop. In a sitation where you would like to a `break` or `continue` for one
95+
of the outer loops, you can use labels to specify which loop the `break` or
96+
`continue` statement applies to. This will only print when both `x` and `y` are
97+
odd:
98+
99+
```rust
100+
'outer: for x in 0..10 {
101+
'inner: for y in 0..10 {
102+
if x % 2 == 0 { continue 'outer; } // continues the loop over x
103+
if y % 2 == 0 { continue 'inner; } // continues the loop over y
104+
println!("x: {}, y: {}", x, y);
105+
}
106+
}
107+
```
108+
91109
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
92110

93111
[for]: for-loops.html

branches/stable/src/liballoc/boxed.rs

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,16 @@
5555

5656
use core::prelude::*;
5757

58+
use heap;
59+
5860
use core::any::Any;
5961
use core::cmp::Ordering;
6062
use core::fmt;
6163
use core::hash::{self, Hash};
62-
use core::marker::Unsize;
64+
use core::marker::{self, Unsize};
6365
use core::mem;
6466
use core::ops::{CoerceUnsized, Deref, DerefMut};
67+
use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
6568
use core::ptr::Unique;
6669
use core::raw::{TraitObject};
6770

@@ -72,7 +75,7 @@ use core::raw::{TraitObject};
7275
///
7376
/// ```
7477
/// # #![feature(box_heap)]
75-
/// #![feature(box_syntax)]
78+
/// #![feature(box_syntax, placement_in_syntax)]
7679
/// use std::boxed::HEAP;
7780
///
7881
/// fn main() {
@@ -83,15 +86,110 @@ use core::raw::{TraitObject};
8386
#[lang = "exchange_heap"]
8487
#[unstable(feature = "box_heap",
8588
reason = "may be renamed; uncertain about custom allocator design")]
86-
pub const HEAP: () = ();
89+
pub const HEAP: ExchangeHeapSingleton =
90+
ExchangeHeapSingleton { _force_singleton: () };
91+
92+
/// This the singleton type used solely for `boxed::HEAP`.
93+
#[derive(Copy, Clone)]
94+
pub struct ExchangeHeapSingleton { _force_singleton: () }
8795

8896
/// A pointer type for heap allocation.
8997
///
9098
/// See the [module-level documentation](../../std/boxed/index.html) for more.
9199
#[lang = "owned_box"]
92100
#[stable(feature = "rust1", since = "1.0.0")]
93101
#[fundamental]
94-
pub struct Box<T>(Unique<T>);
102+
pub struct Box<T: ?Sized>(Unique<T>);
103+
104+
/// `IntermediateBox` represents uninitialized backing storage for `Box`.
105+
///
106+
/// FIXME (pnkfelix): Ideally we would just reuse `Box<T>` instead of
107+
/// introducing a separate `IntermediateBox<T>`; but then you hit
108+
/// issues when you e.g. attempt to destructure an instance of `Box`,
109+
/// since it is a lang item and so it gets special handling by the
110+
/// compiler. Easier just to make this parallel type for now.
111+
///
112+
/// FIXME (pnkfelix): Currently the `box` protocol only supports
113+
/// creating instances of sized types. This IntermediateBox is
114+
/// designed to be forward-compatible with a future protocol that
115+
/// supports creating instances of unsized types; that is why the type
116+
/// parameter has the `?Sized` generalization marker, and is also why
117+
/// this carries an explicit size. However, it probably does not need
118+
/// to carry the explicit alignment; that is just a work-around for
119+
/// the fact that the `align_of` intrinsic currently requires the
120+
/// input type to be Sized (which I do not think is strictly
121+
/// necessary).
122+
#[unstable(feature = "placement_in", reason = "placement box design is still being worked out.")]
123+
pub struct IntermediateBox<T: ?Sized>{
124+
ptr: *mut u8,
125+
size: usize,
126+
align: usize,
127+
marker: marker::PhantomData<*mut T>,
128+
}
129+
130+
impl<T> Place<T> for IntermediateBox<T> {
131+
fn pointer(&mut self) -> *mut T {
132+
unsafe { ::core::mem::transmute(self.ptr) }
133+
}
134+
}
135+
136+
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
137+
let p = b.ptr as *mut T;
138+
mem::forget(b);
139+
mem::transmute(p)
140+
}
141+
142+
fn make_place<T>() -> IntermediateBox<T> {
143+
let size = mem::size_of::<T>();
144+
let align = mem::align_of::<T>();
145+
146+
let p = if size == 0 {
147+
heap::EMPTY as *mut u8
148+
} else {
149+
let p = unsafe {
150+
heap::allocate(size, align)
151+
};
152+
if p.is_null() {
153+
panic!("Box make_place allocation failure.");
154+
}
155+
p
156+
};
157+
158+
IntermediateBox { ptr: p, size: size, align: align, marker: marker::PhantomData }
159+
}
160+
161+
impl<T> BoxPlace<T> for IntermediateBox<T> {
162+
fn make_place() -> IntermediateBox<T> { make_place() }
163+
}
164+
165+
impl<T> InPlace<T> for IntermediateBox<T> {
166+
type Owner = Box<T>;
167+
unsafe fn finalize(self) -> Box<T> { finalize(self) }
168+
}
169+
170+
impl<T> Boxed for Box<T> {
171+
type Data = T;
172+
type Place = IntermediateBox<T>;
173+
unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> { finalize(b) }
174+
}
175+
176+
impl<T> Placer<T> for ExchangeHeapSingleton {
177+
type Place = IntermediateBox<T>;
178+
179+
fn make_place(self) -> IntermediateBox<T> {
180+
make_place()
181+
}
182+
}
183+
184+
impl<T: ?Sized> Drop for IntermediateBox<T> {
185+
fn drop(&mut self) {
186+
if self.size > 0 {
187+
unsafe {
188+
heap::deallocate(self.ptr, self.size, self.align)
189+
}
190+
}
191+
}
192+
}
95193

96194
impl<T> Box<T> {
97195
/// Allocates memory on the heap and then moves `x` into it.
@@ -199,8 +297,7 @@ impl<T: Clone> Clone for Box<T> {
199297
/// let y = x.clone();
200298
/// ```
201299
#[inline]
202-
fn clone(&self) -> Box<T> { box {(**self).clone()} }
203-
300+
fn clone(&self) -> Box<T> { box (HEAP) {(**self).clone()} }
204301
/// Copies `source`'s contents into `self` without creating a new allocation.
205302
///
206303
/// # Examples

branches/stable/src/liballoc/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
test(no_crate_inject))]
7171
#![no_std]
7272

73+
// SNAP d4432b3
74+
#![allow(unused_features)] // until feature(placement_in_syntax) is in snap
7375
#![feature(allocator)]
7476
#![feature(box_syntax)]
7577
#![feature(coerce_unsized)]
@@ -82,6 +84,8 @@
8284
#![feature(no_std)]
8385
#![feature(nonzero)]
8486
#![feature(optin_builtin_traits)]
87+
#![feature(placement_in_syntax)]
88+
#![feature(placement_new_protocol)]
8589
#![feature(raw)]
8690
#![feature(staged_api)]
8791
#![feature(unboxed_closures)]

0 commit comments

Comments
 (0)