Skip to content

Commit

Permalink
Merge #721
Browse files Browse the repository at this point in the history
721: Add preliminary support for running doctests. r=Emilgardis a=Alexhuszagh

This partially addresses #225.

This only works on nightly, due to the use of the unstable feature [doctest-xcompile](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile)

The relevant tracking issues are:
- rust-lang/cargo#7040
- rust-lang/rust#64245

If the subcommand is `test` and the compiler is nightly, we provide the `-Zdoctest-xcompile` flag if `CROSS_UNSTABLE_ENABLE_DOCTESTS=true`.

Co-authored-by: Alex Huszagh <[email protected]>
  • Loading branch information
bors[bot] and Alexhuszagh committed May 26, 2022
2 parents 10da657 e4f896c commit 459e03e
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]

- #722 - boolean environment variables are evaluated as truthy or falsey.
- #721 - add support for running doctests on nightly if `CROSS_UNSTABLE_ENABLE_DOCTESTS=true`.
- #718 - remove deb subcommand.
- #714 - use host target directory when falling back to host cargo.
- #713 - convert relative target directories to absolute paths.
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 207,15 @@ passthrough = [
]
```

### Unstable Features

Certain unstable features can enable additional functionality useful to
cross-compiling. Note that these are unstable, and may be removed at any
time (particularly if the feature is stabilized or removed), and will
only be used on a nightly channel.

- `CROSS_UNSTABLE_ENABLE_DOCTESTS=true`: also run doctests.

### Mounting volumes into the build environment

In addition to passing environment variables, you can also specify environment
Expand Down
5 changes: 5 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 14,7 @@ pub struct Args {
pub target: Option<Target>,
pub target_dir: Option<PathBuf>,
pub docker_in_docker: bool,
pub enable_doctests: bool,
}

// Fix for issue #581. target_dir must be absolute.
Expand Down Expand Up @@ -85,6 86,9 @@ pub fn parse(target_list: &TargetList) -> Result<Args> {
let docker_in_docker = env::var("CROSS_DOCKER_IN_DOCKER")
.map(|s| bool_from_envvar(&s))
.unwrap_or_default();
let enable_doctests = env::var("CROSS_UNSTABLE_ENABLE_DOCTESTS")
.map(|s| bool_from_envvar(&s))
.unwrap_or_default();

Ok(Args {
all,
Expand All @@ -93,5 97,6 @@ pub fn parse(target_list: &TargetList) -> Result<Args> {
target,
target_dir,
docker_in_docker,
enable_doctests,
})
}
15 changes: 13 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 21,7 @@ use std::path::PathBuf;
use std::process::ExitStatus;

use config::Config;
use rustc_version::Channel;
use serde::Deserialize;

use self::cargo::{Root, Subcommand};
Expand Down Expand Up @@ -314,20 315,22 @@ fn run() -> Result<ExitStatus> {
default_toolchain.to_string()
};
sysroot.set_file_name(&toolchain);
let mut is_nightly = toolchain.contains("nightly");

let installed_toolchains = rustup::installed_toolchains(verbose)?;

if !installed_toolchains.into_iter().any(|t| t == toolchain) {
rustup::install_toolchain(&toolchain, verbose)?;
}
// TODO: Provide a way to pick/match the toolchain version as a consumer of `cross`.
if let Some((rustc_version, rustc_commit)) = rustup::rustc_version(&sysroot)? {
if let Some((rustc_version, channel, rustc_commit)) = rustup::rustc_version(&sysroot)? {
warn_host_version_mismatch(
&host_version_meta,
&toolchain,
&rustc_version,
&rustc_commit,
)?;
is_nightly = channel == Channel::Nightly;
}

let available_targets = rustup::available_targets(&toolchain, verbose)?;
Expand Down Expand Up @@ -358,7 361,7 @@ fn run() -> Result<ExitStatus> {
.map(|sc| sc.needs_interpreter())
.unwrap_or(false);

let filtered_args = if args
let mut filtered_args = if args
.subcommand
.map_or(false, |s| !s.needs_target_in_command())
{
Expand All @@ -384,6 387,14 @@ fn run() -> Result<ExitStatus> {
args.all.clone()
};

let is_test = args
.subcommand
.map(|sc| sc == Subcommand::Test)
.unwrap_or(false);
if is_test && args.enable_doctests && is_nightly {
filtered_args.push("-Zdoctest-xcompile".to_string());
}

if target.needs_docker() && args.subcommand.map(|sc| sc.needs_docker()).unwrap_or(false)
{
if host_version_meta.needs_interpreter()
Expand Down
25 changes: 17 additions & 8 deletions src/rustup.rs
Original file line number Diff line number Diff line change
@@ -1,7 1,7 @@
use std::path::Path;
use std::process::Command;

use rustc_version::Version;
use rustc_version::{Channel, Version};

use crate::errors::*;
use crate::extensions::CommandExt;
Expand Down Expand Up @@ -101,7 101,17 @@ pub fn component_is_installed(component: &str, toolchain: &str, verbose: bool) -
.any(|l| l.starts_with(component) && l.contains("installed")))
}

pub fn rustc_version(toolchain_path: &Path) -> Result<Option<(Version, String)>> {
fn rustc_channel(version: &Version) -> Result<Channel> {
match version.pre.split('.').next().unwrap() {
"" => Ok(Channel::Stable),
"dev" => Ok(Channel::Dev),
"beta" => Ok(Channel::Beta),
"nightly" => Ok(Channel::Nightly),
x => eyre::bail!("unknown prerelease tag {x}"),
}
}

pub fn rustc_version(toolchain_path: &Path) -> Result<Option<(Version, Channel, String)>> {
let path = toolchain_path.join("lib/rustlib/multirust-channel-manifest.toml");
if path.exists() {
let contents = std::fs::read(&path)
Expand All @@ -115,12 125,11 @@ pub fn rustc_version(toolchain_path: &Path) -> Result<Option<(Version, String)>>
{
// Field is `"{version} ({commit} {date})"`
if let Some((version, meta)) = rust_version.split_once(' ') {
return Ok(Some((
Version::parse(version).wrap_err_with(|| {
format!("invalid rust version found in {}", path.display())
})?,
meta.to_owned(),
)));
let version = Version::parse(version).wrap_err_with(|| {
format!("invalid rust version found in {}", path.display())
})?;
let channel = rustc_channel(&version)?;
return Ok(Some((version, channel, meta.to_owned())));
}
}
}
Expand Down

0 comments on commit 459e03e

Please sign in to comment.