mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-09 16:37:36 +00:00
doc: Split out task tutorail. Add links to sub-tutorials
This commit is contained in:
parent
6caafaa9ea
commit
fd0de8bfd7
1
configure
vendored
1
configure
vendored
@ -508,6 +508,7 @@ do
|
|||||||
make_dir $h/test/doc-tutorial-ffi
|
make_dir $h/test/doc-tutorial-ffi
|
||||||
make_dir $h/test/doc-tutorial-macros
|
make_dir $h/test/doc-tutorial-macros
|
||||||
make_dir $h/test/doc-tutorial-borrowed-ptr
|
make_dir $h/test/doc-tutorial-borrowed-ptr
|
||||||
|
make_dir $h/test/doc-tutorial-tasks
|
||||||
make_dir $h/test/doc-ref
|
make_dir $h/test/doc-ref
|
||||||
done
|
done
|
||||||
|
|
||||||
|
173
doc/tutorial-tasks.md
Normal file
173
doc/tutorial-tasks.md
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
% Tasks and communication in Rust
|
||||||
|
|
||||||
|
Rust supports a system of lightweight tasks, similar to what is found
|
||||||
|
in Erlang or other actor systems. Rust tasks communicate via messages
|
||||||
|
and do not share data. However, it is possible to send data without
|
||||||
|
copying it by making use of [the exchange heap](#unique-boxes), which
|
||||||
|
allow the sending task to release ownership of a value, so that the
|
||||||
|
receiving task can keep on using it.
|
||||||
|
|
||||||
|
> ***Note:*** As Rust evolves, we expect the task API to grow and
|
||||||
|
> change somewhat. The tutorial documents the API as it exists today.
|
||||||
|
|
||||||
|
# Spawning a task
|
||||||
|
|
||||||
|
Spawning a task is done using the various spawn functions in the
|
||||||
|
module `task`. Let's begin with the simplest one, `task::spawn()`:
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
use task::spawn;
|
||||||
|
use io::println;
|
||||||
|
|
||||||
|
let some_value = 22;
|
||||||
|
|
||||||
|
do spawn {
|
||||||
|
println(~"This executes in the child task.");
|
||||||
|
println(fmt!("%d", some_value));
|
||||||
|
}
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
The argument to `task::spawn()` is a [unique
|
||||||
|
closure](#unique-closures) of type `fn~()`, meaning that it takes no
|
||||||
|
arguments and generates no return value. The effect of `task::spawn()`
|
||||||
|
is to fire up a child task that will execute the closure in parallel
|
||||||
|
with the creator.
|
||||||
|
|
||||||
|
# Communication
|
||||||
|
|
||||||
|
Now that we have spawned a child task, it would be nice if we could
|
||||||
|
communicate with it. This is done using *pipes*. Pipes are simply a
|
||||||
|
pair of endpoints, with one for sending messages and another for
|
||||||
|
receiving messages. The easiest way to create a pipe is to use
|
||||||
|
`pipes::stream`. Imagine we wish to perform two expensive
|
||||||
|
computations in parallel. We might write something like:
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
use task::spawn;
|
||||||
|
use pipes::{stream, Port, Chan};
|
||||||
|
|
||||||
|
let (chan, port) = stream();
|
||||||
|
|
||||||
|
do spawn {
|
||||||
|
let result = some_expensive_computation();
|
||||||
|
chan.send(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
some_other_expensive_computation();
|
||||||
|
let result = port.recv();
|
||||||
|
|
||||||
|
# fn some_expensive_computation() -> int { 42 }
|
||||||
|
# fn some_other_expensive_computation() {}
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
Let's walk through this code line-by-line. The first line creates a
|
||||||
|
stream for sending and receiving integers:
|
||||||
|
|
||||||
|
~~~~ {.ignore}
|
||||||
|
# use pipes::stream;
|
||||||
|
let (chan, port) = stream();
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
This port is where we will receive the message from the child task
|
||||||
|
once it is complete. The channel will be used by the child to send a
|
||||||
|
message to the port. The next statement actually spawns the child:
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
# use task::{spawn};
|
||||||
|
# use comm::{Port, Chan};
|
||||||
|
# fn some_expensive_computation() -> int { 42 }
|
||||||
|
# let port = Port();
|
||||||
|
# let chan = port.chan();
|
||||||
|
do spawn {
|
||||||
|
let result = some_expensive_computation();
|
||||||
|
chan.send(result);
|
||||||
|
}
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
This child will perform the expensive computation send the result
|
||||||
|
over the channel. (Under the hood, `chan` was captured by the
|
||||||
|
closure that forms the body of the child task. This capture is
|
||||||
|
allowed because channels are sendable.)
|
||||||
|
|
||||||
|
Finally, the parent continues by performing
|
||||||
|
some other expensive computation and then waiting for the child's result
|
||||||
|
to arrive on the port:
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
# use pipes::{stream, Port, Chan};
|
||||||
|
# fn some_other_expensive_computation() {}
|
||||||
|
# let (chan, port) = stream::<int>();
|
||||||
|
# chan.send(0);
|
||||||
|
some_other_expensive_computation();
|
||||||
|
let result = port.recv();
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
# Creating a task with a bi-directional communication path
|
||||||
|
|
||||||
|
A very common thing to do is to spawn a child task where the parent
|
||||||
|
and child both need to exchange messages with each other. The
|
||||||
|
function `std::comm::DuplexStream()` supports this pattern. We'll
|
||||||
|
look briefly at how it is used.
|
||||||
|
|
||||||
|
To see how `spawn_conversation()` works, we will create a child task
|
||||||
|
that receives `uint` messages, converts them to a string, and sends
|
||||||
|
the string in response. The child terminates when `0` is received.
|
||||||
|
Here is the function that implements the child task:
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
# use std::comm::DuplexStream;
|
||||||
|
# use pipes::{Port, Chan};
|
||||||
|
fn stringifier(channel: &DuplexStream<~str, uint>) {
|
||||||
|
let mut value: uint;
|
||||||
|
loop {
|
||||||
|
value = channel.recv();
|
||||||
|
channel.send(uint::to_str(value, 10u));
|
||||||
|
if value == 0u { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
The implementation of `DuplexStream` supports both sending and
|
||||||
|
receiving. The `stringifier` function takes a `DuplexStream` that can
|
||||||
|
send strings (the first type parameter) and receive `uint` messages
|
||||||
|
(the second type parameter). The body itself simply loops, reading
|
||||||
|
from the channel and then sending its response back. The actual
|
||||||
|
response itself is simply the strified version of the received value,
|
||||||
|
`uint::to_str(value)`.
|
||||||
|
|
||||||
|
Here is the code for the parent task:
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
# use std::comm::DuplexStream;
|
||||||
|
# use pipes::{Port, Chan};
|
||||||
|
# use task::spawn;
|
||||||
|
# fn stringifier(channel: &DuplexStream<~str, uint>) {
|
||||||
|
# let mut value: uint;
|
||||||
|
# loop {
|
||||||
|
# value = channel.recv();
|
||||||
|
# channel.send(uint::to_str(value, 10u));
|
||||||
|
# if value == 0u { break; }
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# fn main() {
|
||||||
|
|
||||||
|
let (from_child, to_child) = DuplexStream();
|
||||||
|
|
||||||
|
do spawn || {
|
||||||
|
stringifier(&to_child);
|
||||||
|
};
|
||||||
|
|
||||||
|
from_child.send(22u);
|
||||||
|
assert from_child.recv() == ~"22";
|
||||||
|
|
||||||
|
from_child.send(23u);
|
||||||
|
from_child.send(0u);
|
||||||
|
|
||||||
|
assert from_child.recv() == ~"23";
|
||||||
|
assert from_child.recv() == ~"0";
|
||||||
|
|
||||||
|
# }
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
The parent task first calls `DuplexStream` to create a pair of bidirectional endpoints. It then uses `task::spawn` to create the child task, which captures one end of the communication channel. As a result, both parent
|
||||||
|
and child can send and receive data to and from the other.
|
277
doc/tutorial.md
277
doc/tutorial.md
@ -7,9 +7,11 @@
|
|||||||
This is a tutorial for the Rust programming language. It assumes the
|
This is a tutorial for the Rust programming language. It assumes the
|
||||||
reader is familiar with the basic concepts of programming, and has
|
reader is familiar with the basic concepts of programming, and has
|
||||||
programmed in one or more other languages before. It will often make
|
programmed in one or more other languages before. It will often make
|
||||||
comparisons to other languages in the C family. The tutorial covers
|
comparisons to other languages in the C family. This tutorial covers
|
||||||
the whole language, though not with the depth and precision of the
|
the fundamentals of the language, including the syntax, the type
|
||||||
[language reference](rust.html).
|
system and memory model, and generics.
|
||||||
|
[Additional tutorials](#what-next) cover specific language features in
|
||||||
|
greater depth.
|
||||||
|
|
||||||
## Language overview
|
## Language overview
|
||||||
|
|
||||||
@ -2078,257 +2080,30 @@ This makes it possible to rebind a variable without actually mutating
|
|||||||
it, which is mostly useful for destructuring (which can rebind, but
|
it, which is mostly useful for destructuring (which can rebind, but
|
||||||
not assign).
|
not assign).
|
||||||
|
|
||||||
# Tasks
|
# What next?
|
||||||
|
|
||||||
Rust supports a system of lightweight tasks, similar to what is found
|
Now that you know the essentials, check out any of the additional
|
||||||
in Erlang or other actor systems. Rust tasks communicate via messages
|
tutorials on individual topics.
|
||||||
and do not share data. However, it is possible to send data without
|
|
||||||
copying it by making use of [the exchange heap](#unique-boxes), which
|
|
||||||
allow the sending task to release ownership of a value, so that the
|
|
||||||
receiving task can keep on using it.
|
|
||||||
|
|
||||||
> ***Note:*** As Rust evolves, we expect the task API to grow and
|
* [Borrowed pointers][borrow]
|
||||||
> change somewhat. The tutorial documents the API as it exists today.
|
* [Tasks and communication][tasks]
|
||||||
|
* [Macros][macros]
|
||||||
|
* [The foreign function interface][ffi]
|
||||||
|
|
||||||
## Spawning a task
|
There is further documentation on the [wiki], including articles about
|
||||||
|
[unit testing] in Rust, [documenting][rustdoc] and [packaging][cargo]
|
||||||
|
Rust code, and a discussion of the [attributes] used to apply metada
|
||||||
|
to code.
|
||||||
|
|
||||||
Spawning a task is done using the various spawn functions in the
|
[borrow]: tutorial-borrowed-ptr.html
|
||||||
module `task`. Let's begin with the simplest one, `task::spawn()`:
|
[tasks]: tutorial-tasks.html
|
||||||
|
[macros]: tutorial-macros.html
|
||||||
|
[ffi]: tutorial-ffi.html
|
||||||
|
|
||||||
~~~~
|
[wiki]: https://github.com/mozilla/rust/wiki/Docs
|
||||||
use task::spawn;
|
[unit testing]: https://github.com/mozilla/rust/wiki/Doc-unit-testing
|
||||||
use io::println;
|
[rustdoc]: https://github.com/mozilla/rust/wiki/Doc-using-rustdoc
|
||||||
|
[cargo]: https://github.com/mozilla/rust/wiki/Doc-using-cargo-to-manage-packages
|
||||||
|
[attributes]: https://github.com/mozilla/rust/wiki/Doc-attributes
|
||||||
|
|
||||||
let some_value = 22;
|
[pound-rust]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
|
||||||
|
|
||||||
do spawn {
|
|
||||||
println(~"This executes in the child task.");
|
|
||||||
println(fmt!("%d", some_value));
|
|
||||||
}
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
The argument to `task::spawn()` is a [unique
|
|
||||||
closure](#unique-closures) of type `fn~()`, meaning that it takes no
|
|
||||||
arguments and generates no return value. The effect of `task::spawn()`
|
|
||||||
is to fire up a child task that will execute the closure in parallel
|
|
||||||
with the creator.
|
|
||||||
|
|
||||||
## Communication
|
|
||||||
|
|
||||||
Now that we have spawned a child task, it would be nice if we could
|
|
||||||
communicate with it. This is done using *pipes*. Pipes are simply a
|
|
||||||
pair of endpoints, with one for sending messages and another for
|
|
||||||
receiving messages. The easiest way to create a pipe is to use
|
|
||||||
`pipes::stream`. Imagine we wish to perform two expensive
|
|
||||||
computations in parallel. We might write something like:
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
use task::spawn;
|
|
||||||
use pipes::{stream, Port, Chan};
|
|
||||||
|
|
||||||
let (chan, port) = stream();
|
|
||||||
|
|
||||||
do spawn {
|
|
||||||
let result = some_expensive_computation();
|
|
||||||
chan.send(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
some_other_expensive_computation();
|
|
||||||
let result = port.recv();
|
|
||||||
|
|
||||||
# fn some_expensive_computation() -> int { 42 }
|
|
||||||
# fn some_other_expensive_computation() {}
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
Let's walk through this code line-by-line. The first line creates a
|
|
||||||
stream for sending and receiving integers:
|
|
||||||
|
|
||||||
~~~~ {.ignore}
|
|
||||||
# use pipes::stream;
|
|
||||||
let (chan, port) = stream();
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
This port is where we will receive the message from the child task
|
|
||||||
once it is complete. The channel will be used by the child to send a
|
|
||||||
message to the port. The next statement actually spawns the child:
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
# use task::{spawn};
|
|
||||||
# use comm::{Port, Chan};
|
|
||||||
# fn some_expensive_computation() -> int { 42 }
|
|
||||||
# let port = Port();
|
|
||||||
# let chan = port.chan();
|
|
||||||
do spawn {
|
|
||||||
let result = some_expensive_computation();
|
|
||||||
chan.send(result);
|
|
||||||
}
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
This child will perform the expensive computation send the result
|
|
||||||
over the channel. (Under the hood, `chan` was captured by the
|
|
||||||
closure that forms the body of the child task. This capture is
|
|
||||||
allowed because channels are sendable.)
|
|
||||||
|
|
||||||
Finally, the parent continues by performing
|
|
||||||
some other expensive computation and then waiting for the child's result
|
|
||||||
to arrive on the port:
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
# use pipes::{stream, Port, Chan};
|
|
||||||
# fn some_other_expensive_computation() {}
|
|
||||||
# let (chan, port) = stream::<int>();
|
|
||||||
# chan.send(0);
|
|
||||||
some_other_expensive_computation();
|
|
||||||
let result = port.recv();
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
## Creating a task with a bi-directional communication path
|
|
||||||
|
|
||||||
A very common thing to do is to spawn a child task where the parent
|
|
||||||
and child both need to exchange messages with each other. The
|
|
||||||
function `std::comm::DuplexStream()` supports this pattern. We'll
|
|
||||||
look briefly at how it is used.
|
|
||||||
|
|
||||||
To see how `spawn_conversation()` works, we will create a child task
|
|
||||||
that receives `uint` messages, converts them to a string, and sends
|
|
||||||
the string in response. The child terminates when `0` is received.
|
|
||||||
Here is the function that implements the child task:
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
# use std::comm::DuplexStream;
|
|
||||||
# use pipes::{Port, Chan};
|
|
||||||
fn stringifier(channel: &DuplexStream<~str, uint>) {
|
|
||||||
let mut value: uint;
|
|
||||||
loop {
|
|
||||||
value = channel.recv();
|
|
||||||
channel.send(uint::to_str(value, 10u));
|
|
||||||
if value == 0u { break; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
The implementation of `DuplexStream` supports both sending and
|
|
||||||
receiving. The `stringifier` function takes a `DuplexStream` that can
|
|
||||||
send strings (the first type parameter) and receive `uint` messages
|
|
||||||
(the second type parameter). The body itself simply loops, reading
|
|
||||||
from the channel and then sending its response back. The actual
|
|
||||||
response itself is simply the strified version of the received value,
|
|
||||||
`uint::to_str(value)`.
|
|
||||||
|
|
||||||
Here is the code for the parent task:
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
# use std::comm::DuplexStream;
|
|
||||||
# use pipes::{Port, Chan};
|
|
||||||
# use task::spawn;
|
|
||||||
# fn stringifier(channel: &DuplexStream<~str, uint>) {
|
|
||||||
# let mut value: uint;
|
|
||||||
# loop {
|
|
||||||
# value = channel.recv();
|
|
||||||
# channel.send(uint::to_str(value, 10u));
|
|
||||||
# if value == 0u { break; }
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# fn main() {
|
|
||||||
|
|
||||||
let (from_child, to_child) = DuplexStream();
|
|
||||||
|
|
||||||
do spawn || {
|
|
||||||
stringifier(&to_child);
|
|
||||||
};
|
|
||||||
|
|
||||||
from_child.send(22u);
|
|
||||||
assert from_child.recv() == ~"22";
|
|
||||||
|
|
||||||
from_child.send(23u);
|
|
||||||
from_child.send(0u);
|
|
||||||
|
|
||||||
assert from_child.recv() == ~"23";
|
|
||||||
assert from_child.recv() == ~"0";
|
|
||||||
|
|
||||||
# }
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
The parent task first calls `DuplexStream` to create a pair of bidirectional endpoints. It then uses `task::spawn` to create the child task, which captures one end of the communication channel. As a result, both parent
|
|
||||||
and child can send and receive data to and from the other.
|
|
||||||
|
|
||||||
# Testing
|
|
||||||
|
|
||||||
The Rust language has a facility for testing built into the language.
|
|
||||||
Tests can be interspersed with other code, and annotated with the
|
|
||||||
`#[test]` attribute.
|
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
|
||||||
# // FIXME: xfailed because test_twice is a #[test] function it's not
|
|
||||||
# // getting compiled
|
|
||||||
extern mod std;
|
|
||||||
|
|
||||||
fn twice(x: int) -> int { x + x }
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_twice() {
|
|
||||||
let mut i = -100;
|
|
||||||
while i < 100 {
|
|
||||||
assert twice(i) == 2 * i;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
When you compile the program normally, the `test_twice` function will
|
|
||||||
not be included. To compile and run such tests, compile with the
|
|
||||||
`--test` flag, and then run the result:
|
|
||||||
|
|
||||||
~~~~ {.notrust}
|
|
||||||
> rustc --test twice.rs
|
|
||||||
> ./twice
|
|
||||||
running 1 tests
|
|
||||||
test test_twice ... ok
|
|
||||||
result: ok. 1 passed; 0 failed; 0 ignored
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
Or, if we change the file to fail, for example by replacing `x + x`
|
|
||||||
with `x + 1`:
|
|
||||||
|
|
||||||
~~~~ {.notrust}
|
|
||||||
running 1 tests
|
|
||||||
test test_twice ... FAILED
|
|
||||||
failures:
|
|
||||||
test_twice
|
|
||||||
result: FAILED. 0 passed; 1 failed; 0 ignored
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
You can pass a command-line argument to a program compiled with
|
|
||||||
`--test` to run only the tests whose name matches the given string. If
|
|
||||||
we had, for example, test functions `test_twice`, `test_once_1`, and
|
|
||||||
`test_once_2`, running our program with `./twice test_once` would run
|
|
||||||
the latter two, and running it with `./twice test_once_2` would run
|
|
||||||
only the last.
|
|
||||||
|
|
||||||
To indicate that a test is supposed to fail instead of pass, you can
|
|
||||||
give it a `#[should_fail]` attribute.
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
extern mod std;
|
|
||||||
|
|
||||||
fn divide(a: float, b: float) -> float {
|
|
||||||
if b == 0f { fail; }
|
|
||||||
a / b
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn divide_by_zero() { divide(1f, 0f); }
|
|
||||||
|
|
||||||
# fn main() { }
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
To disable a test completely, add an `#[ignore]` attribute. Running a
|
|
||||||
test runner (the program compiled with `--test`) with an `--ignored`
|
|
||||||
command-line flag will cause it to also run the tests labelled as
|
|
||||||
ignored.
|
|
||||||
|
|
||||||
A program compiled as a test runner will have the configuration flag
|
|
||||||
`test` defined, so that you can add code that won't be included in a
|
|
||||||
normal compile with the `#[cfg(test)]` attribute (for a full explanation
|
|
||||||
of attributes, see the [language reference](rust.html)).
|
|
||||||
|
10
mk/docs.mk
10
mk/docs.mk
@ -113,6 +113,16 @@ doc/tutorial-borrowed-ptr.html: tutorial-borrowed-ptr.md doc/version_info.html d
|
|||||||
--include-before-body=doc/version_info.html \
|
--include-before-body=doc/version_info.html \
|
||||||
--output=$@
|
--output=$@
|
||||||
|
|
||||||
|
DOCS += doc/tutorial-tasks.html
|
||||||
|
doc/tutorial-tasks.html: tutorial-tasks.md doc/version_info.html doc/rust.css
|
||||||
|
@$(call E, pandoc: $@)
|
||||||
|
$(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
|
||||||
|
$(CFG_PANDOC) --standalone --toc \
|
||||||
|
--section-divs --number-sections \
|
||||||
|
--from=markdown --to=html --css=rust.css \
|
||||||
|
--include-before-body=doc/version_info.html \
|
||||||
|
--output=$@
|
||||||
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
27
mk/tests.mk
27
mk/tests.mk
@ -179,6 +179,11 @@ doc-tutorial-borrowed-ptr-extract$(1):
|
|||||||
$$(Q)rm -f $(1)/test/doc-tutorial-borrowed-ptr/*.rs
|
$$(Q)rm -f $(1)/test/doc-tutorial-borrowed-ptr/*.rs
|
||||||
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-borrowed-ptr.md $(1)/test/doc-tutorial-borrowed-ptr
|
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-borrowed-ptr.md $(1)/test/doc-tutorial-borrowed-ptr
|
||||||
|
|
||||||
|
doc-tutorial-tasks-extract$(1):
|
||||||
|
@$$(call E, extract: tutorial-tasks tests)
|
||||||
|
$$(Q)rm -f $(1)/test/doc-tutorial-tasks/*.rs
|
||||||
|
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-tasks.md $(1)/test/doc-tutorial-tasks
|
||||||
|
|
||||||
doc-ref-extract$(1):
|
doc-ref-extract$(1):
|
||||||
@$$(call E, extract: ref tests)
|
@$$(call E, extract: ref tests)
|
||||||
$$(Q)rm -f $(1)/test/doc-ref/*.rs
|
$$(Q)rm -f $(1)/test/doc-ref/*.rs
|
||||||
@ -229,6 +234,7 @@ check-stage$(1)-T-$(2)-H-$(3): \
|
|||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr \
|
||||||
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-tasks \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-ref
|
check-stage$(1)-T-$(2)-H-$(3)-doc-ref
|
||||||
|
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-core: \
|
check-stage$(1)-T-$(2)-H-$(3)-core: \
|
||||||
@ -298,6 +304,9 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros: \
|
|||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr: \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr: \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy
|
||||||
|
|
||||||
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-tasks: \
|
||||||
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-tasks-dummy
|
||||||
|
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-ref: \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-ref: \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy
|
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy
|
||||||
|
|
||||||
@ -485,6 +494,12 @@ DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3) := \
|
|||||||
--build-base $(3)/test/doc-tutorial-borrowed-ptr/ \
|
--build-base $(3)/test/doc-tutorial-borrowed-ptr/ \
|
||||||
--mode run-pass
|
--mode run-pass
|
||||||
|
|
||||||
|
DOC_TUTORIAL_TASKS_ARGS$(1)-T-$(2)-H-$(3) := \
|
||||||
|
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
|
||||||
|
--src-base $(3)/test/doc-tutorial-tasks/ \
|
||||||
|
--build-base $(3)/test/doc-tutorial-tasks/ \
|
||||||
|
--mode run-pass
|
||||||
|
|
||||||
DOC_REF_ARGS$(1)-T-$(2)-H-$(3) := \
|
DOC_REF_ARGS$(1)-T-$(2)-H-$(3) := \
|
||||||
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
|
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
|
||||||
--src-base $(3)/test/doc-ref/ \
|
--src-base $(3)/test/doc-ref/ \
|
||||||
@ -611,6 +626,14 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy: \
|
|||||||
$$(DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3)) \
|
$$(DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3)) \
|
||||||
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr.log
|
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr.log
|
||||||
|
|
||||||
|
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-tasks-dummy: \
|
||||||
|
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
|
||||||
|
doc-tutorial-tasks-extract$(3)
|
||||||
|
@$$(call E, run doc-tutorial-tasks: $$<)
|
||||||
|
$$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
|
||||||
|
$$(DOC_TUTORIAL_TASKS_ARGS$(1)-T-$(2)-H-$(3)) \
|
||||||
|
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-tasks.log
|
||||||
|
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy: \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy: \
|
||||||
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
|
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
|
||||||
doc-ref-extract$(3)
|
doc-ref-extract$(3)
|
||||||
@ -748,6 +771,9 @@ check-stage$(1)-H-$(2)-doc-tutorial-macros: \
|
|||||||
check-stage$(1)-H-$(2)-doc-tutorial-borrowed-ptr: \
|
check-stage$(1)-H-$(2)-doc-tutorial-borrowed-ptr: \
|
||||||
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
|
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
|
||||||
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-borrowed-ptr)
|
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-borrowed-ptr)
|
||||||
|
check-stage$(1)-H-$(2)-doc-tutorial-tasks: \
|
||||||
|
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
|
||||||
|
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-tasks)
|
||||||
check-stage$(1)-H-$(2)-doc-ref: \
|
check-stage$(1)-H-$(2)-doc-ref: \
|
||||||
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
|
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
|
||||||
check-stage$(1)-T-$$(target)-H-$(2)-doc-ref)
|
check-stage$(1)-T-$$(target)-H-$(2)-doc-ref)
|
||||||
@ -859,6 +885,7 @@ check-stage$(1)-doc-tutorial: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial
|
|||||||
check-stage$(1)-doc-tutorial-ffi: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-ffi
|
check-stage$(1)-doc-tutorial-ffi: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-ffi
|
||||||
check-stage$(1)-doc-tutorial-macros: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-macros
|
check-stage$(1)-doc-tutorial-macros: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-macros
|
||||||
check-stage$(1)-doc-tutorial-borrowed-ptr: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-borrowed-ptr
|
check-stage$(1)-doc-tutorial-borrowed-ptr: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-borrowed-ptr
|
||||||
|
check-stage$(1)-doc-tutorial-tasks: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-tasks
|
||||||
check-stage$(1)-doc-ref: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-ref
|
check-stage$(1)-doc-ref: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-ref
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
Loading…
Reference in New Issue
Block a user