]>
git.proxmox.com Git - cargo.git/blob - src/cargo/core/compiler/rustdoc.rs
1 //! Utilities for building with rustdoc.
3 use crate::core
::compiler
::context
::Context
;
4 use crate::core
::compiler
::unit
::Unit
;
5 use crate::core
::compiler
::CompileKind
;
6 use crate::sources
::CRATES_IO_REGISTRY
;
7 use crate::util
::errors
::{internal, CargoResult}
;
8 use crate::util
::ProcessBuilder
;
9 use std
::collections
::HashMap
;
14 /// Mode used for `std`.
15 #[derive(Debug, Hash)]
16 pub enum RustdocExternMode
{
17 /// Use a local `file://` URL.
19 /// Use a remote URL to https://doc.rust-lang.org/ (default).
25 impl From
<String
> for RustdocExternMode
{
26 fn from(s
: String
) -> RustdocExternMode
{
28 "local" => RustdocExternMode
::Local
,
29 "remote" => RustdocExternMode
::Remote
,
30 _
=> RustdocExternMode
::Url(s
),
35 impl fmt
::Display
for RustdocExternMode
{
36 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
38 RustdocExternMode
::Local
=> "local".fmt(f
),
39 RustdocExternMode
::Remote
=> "remote".fmt(f
),
40 RustdocExternMode
::Url(s
) => s
.fmt(f
),
45 impl<'de
> serde
::de
::Deserialize
<'de
> for RustdocExternMode
{
46 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
48 D
: serde
::de
::Deserializer
<'de
>,
50 let s
= String
::deserialize(deserializer
)?
;
55 #[derive(serde::Deserialize, Debug)]
56 pub struct RustdocExternMap
{
57 registries
: HashMap
<String
, String
>,
58 std
: Option
<RustdocExternMode
>,
61 impl hash
::Hash
for RustdocExternMap
{
62 fn hash
<H
: hash
::Hasher
>(&self, into
: &mut H
) {
64 for (key
, value
) in &self.registries
{
74 rustdoc
: &mut ProcessBuilder
,
75 ) -> CargoResult
<()> {
76 let config
= cx
.bcx
.config
;
77 if !config
.cli_unstable().rustdoc_map
{
78 log
::debug
!("`doc.extern-map` ignored, requires -Zrustdoc-map flag");
81 let map
= config
.doc_extern_map()?
;
82 if map
.registries
.is_empty() && map
.std
.is_none() {
83 // Skip doing unnecessary work.
86 let mut unstable_opts
= false;
87 // Collect mapping of registry name -> index url.
88 let name2url
: HashMap
<&String
, Url
> = map
92 if let Ok(index_url
) = config
.get_registry_index(name
) {
93 Some((name
, index_url
))
96 "`doc.extern-map.{}` specifies a registry that is not defined",
103 for dep
in cx
.unit_deps(unit
) {
104 if dep
.unit
.target
.is_linkable() && !dep
.unit
.mode
.is_doc() {
105 for (registry
, location
) in &map
.registries
{
106 let sid
= dep
.unit
.pkg
.package_id().source_id();
107 let matches_registry
= || -> bool
{
108 if !sid
.is_registry() {
111 if sid
.is_default_registry() {
112 return registry
== CRATES_IO_REGISTRY
;
114 if let Some(index_url
) = name2url
.get(registry
) {
115 return index_url
== sid
.url();
119 if matches_registry() {
120 let mut url
= location
.clone();
121 if !url
.contains("{pkg_name}") && !url
.contains("{version}") {
122 if !url
.ends_with('
/'
) {
125 url
.push_str("{pkg_name}/{version}/");
128 .replace("{pkg_name}", &dep
.unit
.pkg
.name())
129 .replace("{version}", &dep
.unit
.pkg
.version().to_string());
130 rustdoc
.arg("--extern-html-root-url");
131 rustdoc
.arg(format
!("{}={}", dep
.unit
.target
.crate_name(), url
));
132 unstable_opts
= true;
137 let std_url
= match &map
.std
{
138 None
| Some(RustdocExternMode
::Remote
) => None
,
139 Some(RustdocExternMode
::Local
) => {
140 let sysroot
= &cx
.bcx
.target_data
.info(CompileKind
::Host
).sysroot
;
141 let html_root
= sysroot
.join("share").join("doc").join("rust").join("html");
142 if html_root
.exists() {
143 let url
= Url
::from_file_path(&html_root
).map_err(|()| {
145 "`{}` failed to convert to URL",
149 Some(url
.to_string())
152 "`doc.extern-map.std` is \"local\", but local docs don't appear to exist at {}",
158 Some(RustdocExternMode
::Url(s
)) => Some(s
.to_string()),
160 if let Some(url
) = std_url
{
161 for name
in &["std", "core", "alloc", "proc_macro"] {
162 rustdoc
.arg("--extern-html-root-url");
163 rustdoc
.arg(format
!("{}={}", name
, url
));
164 unstable_opts
= true;
169 rustdoc
.arg("-Zunstable-options");