diff --git a/src/bin/cargo/commands/doc.rs b/src/bin/cargo/commands/doc.rs index 8405015dfbb..61e36a10fed 100644 --- a/src/bin/cargo/commands/doc.rs +++ b/src/bin/cargo/commands/doc.rs @@ -27,6 +27,12 @@ pub fn cli() -> App { .arg_features() .arg_target_triple("Build for the target triple") .arg_target_dir() + .arg( + Arg::with_name("use-local-sysroot-docs") + .long("use-local-sysroot-docs") + .help("Attempt to use local sysroot file:// links if available") + .hidden(true), + ) .arg_manifest_path() .arg_message_format() .after_help( @@ -48,19 +54,34 @@ the `cargo help pkgid` command. pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let ws = args.workspace(config)?; + let mode = CompileMode::Doc { deps: !args.is_present("no-deps"), }; + let mut compile_opts = args.compile_options(config, mode, Some(&ws))?; compile_opts.local_rustdoc_args = if args.is_present("document-private-items") { Some(vec!["--document-private-items".to_string()]) } else { None }; + + let use_local_sysroot_docs = args.is_present("use-local-sysroot-docs"); + if use_local_sysroot_docs && !config.cli_unstable().unstable_options { + return Err(failure::format_err!( + "`cargo doc --use-local-sysroot-docs` is unstable, pass `-Z unstable-options` to enable it" + ) + .into()); + } + + compile_opts.build_config.use_local_sysroot_docs = use_local_sysroot_docs; + let doc_opts = DocOptions { open_result: args.is_present("open"), compile_opts, }; + ops::doc(&ws, &doc_opts)?; + Ok(()) } diff --git a/src/bin/cargo/commands/rustdoc.rs b/src/bin/cargo/commands/rustdoc.rs index 6616dc70e18..71d6acbad7b 100644 --- a/src/bin/cargo/commands/rustdoc.rs +++ b/src/bin/cargo/commands/rustdoc.rs @@ -30,6 +30,12 @@ pub fn cli() -> App { .arg_features() .arg_target_triple("Build for the target triple") .arg_target_dir() + .arg( + Arg::with_name("use-local-sysroot-docs") + .long("use-local-sysroot-docs") + .help("Attempt to use local sysroot file:// links if available") + .hidden(true), + ) .arg_manifest_path() .arg_message_format() .after_help( @@ -51,21 +57,36 @@ the `cargo help pkgid` command. pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let ws = args.workspace(config)?; + let mut compile_opts = args.compile_options_for_single_package( config, CompileMode::Doc { deps: false }, Some(&ws), )?; + let target_args = values(args, "args"); compile_opts.target_rustdoc_args = if target_args.is_empty() { None } else { Some(target_args) }; + + let use_local_sysroot_docs = args.is_present("use-local-sysroot-docs"); + if use_local_sysroot_docs && !config.cli_unstable().unstable_options { + return Err(failure::format_err!( + "`cargo doc --use-local-sysroot-docs` is unstable, pass `-Z unstable-options` to enable it" + ) + .into()); + } + + compile_opts.build_config.use_local_sysroot_docs = use_local_sysroot_docs; + let doc_opts = DocOptions { open_result: args.is_present("open"), compile_opts, }; + ops::doc(&ws, &doc_opts)?; + Ok(()) } diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index f5fbe119354..9600ace342b 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -29,6 +29,8 @@ pub struct BuildConfig { pub rustfix_diagnostic_server: RefCell>, /// Whether or not Cargo should cache compiler output on disk. cache_messages: bool, + /// Whether rustdoc should attempt to get local std docs + pub use_local_sysroot_docs: bool, } impl BuildConfig { @@ -101,6 +103,7 @@ impl BuildConfig { rustc_wrapper: None, rustfix_diagnostic_server: RefCell::new(None), cache_messages: config.cli_unstable().cache_messages, + use_local_sysroot_docs: false, }) } diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 8abc579e713..5b694718eaf 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -15,6 +15,7 @@ pub struct TargetInfo { crate_types: RefCell>>, cfg: Option>, pub sysroot_libdir: Option, + pub sysroot_dir: Option, pub rustflags: Vec, pub rustdocflags: Vec, } @@ -113,6 +114,7 @@ impl TargetInfo { } let mut sysroot_libdir = None; + let mut sysroot_dir = None; if has_cfg_and_sysroot { let line = match lines.next() { Some(line) => line, @@ -122,6 +124,7 @@ impl TargetInfo { ), }; let mut rustlib = PathBuf::from(line); + sysroot_dir = Some(rustlib.clone()); if kind == Kind::Host { if cfg!(windows) { rustlib.push("bin"); @@ -148,6 +151,7 @@ impl TargetInfo { crate_type_process: Some(crate_type_process), crate_types: RefCell::new(map), sysroot_libdir, + sysroot_dir, // recalculate `rustflags` from above now that we have `cfg` // information rustflags: env_args( diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 628ac8bbff8..260456fed19 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -600,9 +600,35 @@ fn prepare_rustc<'a, 'cfg>( Ok(base) } +fn add_sysroot_doc_args(bcx: &BuildContext<'_, '_>, cmd: &mut ProcessBuilder) { + let sysroot_dir = bcx.target_info.sysroot_dir.as_ref(); + + if sysroot_dir.is_none() { + return; + } + + let sysroot_docdir = sysroot_dir.unwrap().join("share/doc/rust/html"); + + if !sysroot_docdir.is_dir() || !sysroot_docdir.join("index.html").is_file() { + return; + } + + let sysroot_docdir = sysroot_docdir.to_string_lossy(); + cmd.arg("-Zunstable-options"); + for crate_name in ["std", "core", "proc_macro", "alloc", "test"].iter() { + cmd.arg("--extern-html-root-url") + .arg(format!("{}={}", crate_name, sysroot_docdir)); + } +} + fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult { let bcx = cx.bcx; let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg, unit.target)?; + + if bcx.build_config.use_local_sysroot_docs { + add_sysroot_doc_args(bcx, &mut rustdoc); + } + rustdoc.inherit_jobserver(&cx.jobserver); rustdoc.arg("--crate-name").arg(&unit.target.crate_name()); add_path_args(bcx, unit, &mut rustdoc);