about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-13 06:17:25 +0000
committerbors <bors@rust-lang.org>2020-08-13 06:17:25 +0000
commitd69b0997d7dcc99a188d5cb19137dedc4fc05d25 (patch)
tree5acdb2c21607c96661b0a34e5d7f8c173197101a /src
parent814bc4fe9364865bfaa94d7825b8eabc11245c7c (diff)
parentce717476ffc2d7ca1bc737942e778b8e0e813e05 (diff)
downloadrust-d69b0997d7dcc99a188d5cb19137dedc4fc05d25.tar.gz
rust-d69b0997d7dcc99a188d5cb19137dedc4fc05d25.zip
Auto merge of #75431 - ehuss:platform-support, r=Mark-Simulacrum
Move platform support to the rustc book.

This moves the [Platform Support](https://forge.rust-lang.org/release/platform-support.html) page from the forge to the rustc book. There are several reasons for doing this:

* The forge is not really oriented towards end-users (it mostly contains infrastructure, governance and policy, internal team pages, etc.). This platform support page is useful to user to know which targets are supported.
* This page can now be updated in-sync with any PRs that add or remove a target, or change its status.
* This is now automatically checked on CI to verify the list does not get out of sync. Currently it only checks the presence/absence of an entry, but more sophisticated checks could be added in the future.

I'm not 100% certain this is the best location, but I think it fits. I'd like to see the rustc guide continue to grow, including things like linking information and more platform-specific details.
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/test.rs44
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md223
-rw-r--r--src/doc/rustc/src/targets/built-in.md15
-rw-r--r--src/tools/tier-check/Cargo.toml8
-rw-r--r--src/tools/tier-check/src/main.rs52
7 files changed, 339 insertions, 5 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e13a5f24653..4b0905bd6c1 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -404,6 +404,7 @@ impl<'a> Builder<'a> {
                 test::CrateLibrustc,
                 test::CrateRustdoc,
                 test::Linkcheck,
+                test::TierCheck,
                 test::Cargotest,
                 test::Cargo,
                 test::Rls,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index bb5b9296c0a..11e2564305f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -2043,3 +2043,47 @@ impl Step for Bootstrap {
         run.builder.ensure(Bootstrap);
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct TierCheck {
+    pub compiler: Compiler,
+    target: TargetSelection,
+}
+
+impl Step for TierCheck {
+    type Output = ();
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/tier-check")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        let compiler = run.builder.compiler_for(run.builder.top_stage, run.host, run.host);
+        run.builder.ensure(TierCheck { compiler, target: run.host });
+    }
+
+    /// Tests the Platform Support page in the rustc book.
+    fn run(self, builder: &Builder<'_>) {
+        builder.ensure(compile::Std { compiler: self.compiler, target: self.target });
+        let mut cargo = tool::prepare_tool_cargo(
+            builder,
+            self.compiler,
+            Mode::ToolRustc,
+            self.target,
+            "run",
+            "src/tools/tier-check",
+            SourceType::InTree,
+            &[],
+        );
+        cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
+        cargo.arg(&builder.rustc(self.compiler));
+        if builder.is_verbose() {
+            cargo.arg("--verbose");
+        }
+
+        builder.info("platform support check");
+        try_run(builder, &mut cargo.into());
+    }
+}
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b603c7b231e..57013e9194b 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -11,6 +11,7 @@
         - [Deny-by-default lints](lints/listing/deny-by-default.md)
 - [Codegen options](codegen-options/index.md)
 - [JSON Output](json.md)
+- [Platform Support](platform-support.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
new file mode 100644
index 00000000000..b8d3c985cb5
--- /dev/null
+++ b/src/doc/rustc/src/platform-support.md
@@ -0,0 +1,223 @@
+# Platform Support
+
+<style type="text/css">
+    td code {
+        white-space: nowrap;
+    }
+</style>
+
+Support for different platforms are organized into three tiers, each with a
+different set of guarantees.
+
+Platforms are identified by their "target triple" which is the string to
+inform the compiler what kind of output should be produced. The columns in the
+tables below have the following meanings:
+
+* std:
+    * ✓ indicates the full standard library is available.
+    * \* indicates the target only supports [`no_std`] development.
+    * ? indicates the standard library support is unknown or a work-in-progress.
+* host: A ✓ indicates that `rustc` and `cargo` can run on the host platform.
+
+[`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html
+
+## Tier 1
+
+Tier 1 platforms can be thought of as "guaranteed to work".
+Specifically they will each satisfy the following requirements:
+
+* Official binary releases are provided for the platform.
+* Automated testing is set up to run tests for the platform.
+* Landing changes to the `rust-lang/rust` repository's master branch is gated
+  on tests passing.
+* Documentation for how to use and how to build the platform is available.
+
+target | std | host | notes
+-------|-----|------|-------
+`i686-pc-windows-gnu` | ✓ | ✓ | 32-bit MinGW (Windows 7+)
+`i686-pc-windows-msvc` | ✓ | ✓ | 32-bit MSVC (Windows 7+)
+`i686-unknown-linux-gnu` | ✓ | ✓ | 32-bit Linux (kernel 2.6.32+, glibc 2.11+)
+`x86_64-apple-darwin` | ✓ | ✓ | 64-bit OSX (10.7+, Lion+)
+`x86_64-pc-windows-gnu` | ✓ | ✓ | 64-bit MinGW (Windows 7+)
+`x86_64-pc-windows-msvc` | ✓ | ✓ | 64-bit MSVC (Windows 7+)
+`x86_64-unknown-linux-gnu` | ✓ | ✓ | 64-bit Linux (kernel 2.6.32+, glibc 2.11+)
+
+## Tier 2
+
+Tier 2 platforms can be thought of as "guaranteed to build". Automated tests
+are not run so it's not guaranteed to produce a working build, but platforms
+often work to quite a good degree and patches are always welcome!
+Specifically, these platforms are required to have each of the following:
+
+* Official binary releases are provided for the platform.
+* Automated building is set up, but may not be running tests.
+* Landing changes to the `rust-lang/rust` repository's master branch is gated on
+    platforms **building**. For some platforms only the standard library is
+    compiled, but for others `rustc` and `cargo` are too.
+
+target | std | host | notes
+-------|-----|------|-------
+`aarch64-apple-ios` | ✓[^apple] |  | ARM64 iOS
+`aarch64-fuchsia` | ✓ |  | ARM64 Fuchsia
+`aarch64-linux-android` | ✓ |  | ARM64 Android
+`aarch64-pc-windows-msvc` | ✓ |  | ARM64 Windows MSVC
+`aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17)
+`aarch64-unknown-linux-musl` | ✓ |  | ARM64 Linux with MUSL
+`aarch64-unknown-none` | * |  | Bare ARM64, hardfloat
+`aarch64-unknown-none-softfloat` | * |  | Bare ARM64, softfloat
+`arm-linux-androideabi` | ✓ |  | ARMv7 Android
+`arm-unknown-linux-gnueabi` | ✓ | ✓ | ARMv6 Linux (kernel 3.2, glibc 2.17)
+`arm-unknown-linux-gnueabihf` | ✓ | ✓ | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
+`arm-unknown-linux-musleabi` | ✓ |  | ARMv6 Linux with MUSL
+`arm-unknown-linux-musleabihf` | ✓ |  | ARMv6 Linux with MUSL, hardfloat
+`armebv7r-none-eabi` | * |  | Bare ARMv7-R, Big Endian
+`armebv7r-none-eabihf` | * |  | Bare ARMv7-R, Big Endian, hardfloat
+`armv5te-unknown-linux-gnueabi` | ✓ |  | ARMv5TE Linux (kernel 4.4, glibc 2.23)
+`armv5te-unknown-linux-musleabi` | ✓ |  | ARMv5TE Linux with MUSL
+`armv7-linux-androideabi` | ✓ |  | ARMv7a Android
+`armv7a-none-eabi` | * |  | Bare ARMv7-A
+`armv7r-none-eabi` | * |  | Bare ARMv7-R
+`armv7r-none-eabihf` | * |  | Bare ARMv7-R, hardfloat
+`armv7-unknown-linux-gnueabi` | ✓ |   | ARMv7 Linux (kernel 4.15, glibc 2.27)
+`armv7-unknown-linux-gnueabihf` | ✓ | ✓ | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17)
+`armv7-unknown-linux-musleabi` | ✓ |   | ARMv7 Linux, MUSL
+`armv7-unknown-linux-musleabihf` | ✓ |  | ARMv7 Linux with MUSL
+`asmjs-unknown-emscripten` | ✓ |  | asm.js via Emscripten
+`i586-pc-windows-msvc` | ✓ |  | 32-bit Windows w/o SSE
+`i586-unknown-linux-gnu` | ✓ |  | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23)
+`i586-unknown-linux-musl` | ✓ |  | 32-bit Linux w/o SSE, MUSL
+`i686-linux-android` | ✓ |  | 32-bit x86 Android
+`i686-unknown-freebsd` | ✓ | ✓ | 32-bit FreeBSD
+`i686-unknown-linux-musl` | ✓ |  | 32-bit Linux with MUSL
+`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
+`mips-unknown-linux-musl` | ✓ |  | MIPS Linux with MUSL
+`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
+`mips64-unknown-linux-muslabi64` | ✓ |  | MIPS64 Linux, n64 ABI, MUSL
+`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
+`mips64el-unknown-linux-muslabi64` | ✓ |  | MIPS64 (LE) Linux, n64 ABI, MUSL
+`mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (LE) Linux (kernel 4.4, glibc 2.23)
+`mipsel-unknown-linux-musl` | ✓ |  | MIPS (LE) Linux with MUSL
+`nvptx64-nvidia-cuda` | ✓ |  | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
+`powerpc-unknown-linux-gnu` | ✓ | ✓ | PowerPC Linux (kernel 2.6.32, glibc 2.11)
+`powerpc64-unknown-linux-gnu` | ✓ | ✓ | PPC64 Linux (kernel 2.6.32, glibc 2.11)
+`powerpc64le-unknown-linux-gnu` | ✓ | ✓ | PPC64LE Linux (kernel 3.10, glibc 2.17)
+`riscv32i-unknown-none-elf` | * |  | Bare RISC-V (RV32I ISA)
+`riscv32imac-unknown-none-elf` | * |  | Bare RISC-V (RV32IMAC ISA)
+`riscv32imc-unknown-none-elf` | * |  | Bare RISC-V (RV32IMC ISA)
+`riscv64gc-unknown-linux-gnu` | ✓ | ✓ | RISC-V Linux (kernel 4.20, glibc 2.29)
+`riscv64gc-unknown-none-elf` | * |  | Bare RISC-V (RV64IMAFDC ISA)
+`riscv64imac-unknown-none-elf` | * |  | Bare RISC-V (RV64IMAC ISA)
+`s390x-unknown-linux-gnu` | ✓ | ✓ | S390x Linux (kernel 2.6.32, glibc 2.11)
+`sparc64-unknown-linux-gnu` | ✓ |  | SPARC Linux (kernel 4.4, glibc 2.23)
+`sparcv9-sun-solaris` | ✓ |  | SPARC Solaris 10/11, illumos
+`thumbv6m-none-eabi` | * |  | Bare Cortex-M0, M0+, M1
+`thumbv7em-none-eabi` | * |  | Bare Cortex-M4, M7
+`thumbv7em-none-eabihf` | * |  | Bare Cortex-M4F, M7F, FPU, hardfloat
+`thumbv7m-none-eabi` | * |  | Bare Cortex-M3
+`thumbv7neon-linux-androideabi` | ✓ |  | Thumb2-mode ARMv7a Android with NEON
+`thumbv7neon-unknown-linux-gnueabihf` | ✓ |  | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23)
+`thumbv8m.base-none-eabi` | * |  | ARMv8-M Baseline
+`thumbv8m.main-none-eabi` | * |  | ARMv8-M Mainline
+`thumbv8m.main-none-eabihf` | * |  | ARMv8-M Baseline, hardfloat
+`wasm32-unknown-emscripten` | ✓ |  | WebAssembly via Emscripten
+`wasm32-unknown-unknown` | ✓ |  | WebAssembly
+`wasm32-wasi` | ✓ |  | WebAssembly with WASI
+`x86_64-apple-ios` | ✓[^apple] |  | 64-bit x86 iOS
+`x86_64-fortanix-unknown-sgx` | ✓ |  | [Fortanix ABI] for 64-bit Intel SGX
+`x86_64-fuchsia` | ✓ |  | 64-bit Fuchsia
+`x86_64-linux-android` | ✓ |  | 64-bit x86 Android
+`x86_64-rumprun-netbsd` | ✓ |  | 64-bit NetBSD Rump Kernel
+`x86_64-sun-solaris` | ✓ |  | 64-bit Solaris 10/11, illumos
+`x86_64-unknown-cloudabi` | ✓ |  | 64-bit CloudABI
+`x86_64-unknown-freebsd` | ✓ | ✓ | 64-bit FreeBSD
+`x86_64-unknown-illumos` | ✓ | ✓ | illumos
+`x86_64-unknown-linux-gnux32` | ✓ |  | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
+`x86_64-unknown-linux-musl` | ✓ | ✓ | 64-bit Linux with MUSL
+`x86_64-unknown-netbsd` | ✓ | ✓ | NetBSD/amd64
+`x86_64-unknown-redox` | ✓ |  | Redox OS
+
+[Fortanix ABI]: https://edp.fortanix.com/
+
+## Tier 3
+
+Tier 3 platforms are those which the Rust codebase has support for, but which
+are not built or tested automatically, and may not work. Official builds are
+not available.
+
+target | std | host | notes
+-------|-----|------|-------
+`aarch64-apple-darwin` | ? |  | ARM64 macOS
+`aarch64-apple-tvos` | *[^apple] |  | ARM64 tvOS
+`aarch64-unknown-cloudabi` | ✓ |  | ARM64 CloudABI
+`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
+`aarch64-unknown-hermit` | ? |  |
+`aarch64-unknown-netbsd` | ? |  |
+`aarch64-unknown-openbsd` | ✓ | ✓ | ARM64 OpenBSD
+`aarch64-unknown-redox` | ? |  | ARM64 Redox OS
+`aarch64-uwp-windows-msvc` | ? |  |
+`aarch64-wrs-vxworks` | ? |  |
+`armv4t-unknown-linux-gnueabi` | ? |  |
+`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
+`armv6-unknown-netbsd-eabihf` | ? |  |
+`armv7-apple-ios` | ✓[^apple] |  | ARMv7 iOS, Cortex-a8
+`armv7-unknown-cloudabi-eabihf` | ✓ |  | ARMv7 CloudABI, hardfloat
+`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
+`armv7-unknown-netbsd-eabihf` | ? |  |
+`armv7-wrs-vxworks-eabihf` | ? |  |
+`armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat
+`armv7s-apple-ios` | ✓[^apple] |  |
+`avr-unknown-unknown` | ? |  | AVR
+`hexagon-unknown-linux-musl` | ? |  |
+`i386-apple-ios` | ✓[^apple] |  | 32-bit x86 iOS
+`i686-apple-darwin` | ✓ | ✓ | 32-bit OSX (10.7+, Lion+)
+`i686-pc-windows-msvc` | ✓ |  | 32-bit Windows XP support
+`i686-unknown-cloudabi` | ✓ |  | 32-bit CloudABI
+`i686-unknown-uefi` | ? |  | 32-bit UEFI
+`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
+`i686-unknown-netbsd` | ✓ |  | NetBSD/i386 with SSE2
+`i686-unknown-openbsd` | ✓ | ✓ | 32-bit OpenBSD
+`i686-uwp-windows-gnu` | ? |  |
+`i686-uwp-windows-msvc` | ? |  |
+`i686-wrs-vxworks` | ? |  |
+`mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
+`mipsel-unknown-linux-uclibc` | ✓ |  | MIPS (LE) Linux with uClibc
+`mipsel-sony-psp` | * |  | MIPS (LE) Sony PlayStation Portable (PSP)
+`mipsisa32r6-unknown-linux-gnu` | ? |  |
+`mipsisa32r6el-unknown-linux-gnu` | ? |  |
+`mipsisa64r6-unknown-linux-gnuabi64` | ? |  |
+`mipsisa64r6el-unknown-linux-gnuabi64` | ? |  |
+`msp430-none-elf` | * |  | 16-bit MSP430 microcontrollers
+`powerpc-unknown-linux-gnuspe` | ✓ |  | PowerPC SPE Linux
+`powerpc-unknown-linux-musl` | ? |  |
+`powerpc-unknown-netbsd` | ? |  |
+`powerpc-wrs-vxworks` | ? |  |
+`powerpc-wrs-vxworks-spe` | ? |  |
+`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
+`powerpc64-unknown-linux-musl` | ? |  |
+`powerpc64-wrs-vxworks` | ? |  |
+`powerpc64le-unknown-linux-musl` | ? |  |
+`sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
+`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64
+`sparc64-unknown-openbsd` | ? |  |
+`thumbv7a-pc-windows-msvc` | ? |  |
+`thumbv7a-uwp-windows-msvc` | ✓ |  |
+`thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7a Linux with NEON, MUSL
+`thumbv4t-none-eabi` | * |  | ARMv4T T32
+`x86_64-apple-ios-macabi` | ✓[^apple] |  | Apple Catalyst
+`x86_64-apple-tvos` | *[^apple] | | x86 64-bit tvOS
+`x86_64-linux-kernel` | ? |  | Linux kernel modules
+`x86_64-pc-solaris` | ? |  |
+`x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support
+`x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
+`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
+`x86_64-unknown-hermit` | ? |  |
+`x86_64-unknown-hermit-kernel` | ? |  | HermitCore kernel
+`x86_64-unknown-l4re-uclibc` | ? |  |
+`x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD
+`x86_64-unknown-uefi` | ? |  |
+`x86_64-uwp-windows-gnu` | ✓ |  |
+`x86_64-uwp-windows-msvc` | ✓ |  |
+`x86_64-wrs-vxworks` | ? |  |
+
+[runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
+[^apple]: These targets are only available on macOS.
diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
index 2e94ebe345a..c33b506cdae 100644
--- a/src/doc/rustc/src/targets/built-in.md
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -2,9 +2,14 @@
 
 `rustc` ships with the ability to compile to many targets automatically, we
 call these "built-in" targets, and they generally correspond to targets that
-the team is supporting directly.
+the team is supporting directly. To see the list of built-in targets, you can
+run `rustc --print target-list`.
 
-To see the list of built-in targets, you can run `rustc --print target-list`,
-or look at [the API
-docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/index.html#modules).
-Each module there defines a builder for a particular target.
\ No newline at end of file
+Typically, a target needs a compiled copy of the Rust standard library to
+work. If using [rustup], then check out the documentation on
+[Cross-compilation][rustup-cross] on how to download a pre-built standard
+library built by the official Rust distributions. Most targets will need a
+system linker, and possibly other things.
+
+[rustup]: https://github.com/rust-lang/rustup
+[rustup-cross]: https://github.com/rust-lang/rustup#cross-compilation
diff --git a/src/tools/tier-check/Cargo.toml b/src/tools/tier-check/Cargo.toml
new file mode 100644
index 00000000000..9917b383aab
--- /dev/null
+++ b/src/tools/tier-check/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "tier-check"
+version = "0.1.0"
+authors = ["Eric Huss"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+
+[dependencies]
diff --git a/src/tools/tier-check/src/main.rs b/src/tools/tier-check/src/main.rs
new file mode 100644
index 00000000000..b8d60a5e2fe
--- /dev/null
+++ b/src/tools/tier-check/src/main.rs
@@ -0,0 +1,52 @@
+//! This is a script for validating the platform support page in the rustc book.
+//!
+//! The script takes two arguments, the path to the Platform Support source
+//! page, and the second argument is the path to `rustc`.
+
+use std::collections::HashSet;
+
+fn main() {
+    let mut args = std::env::args().skip(1);
+    let src = args.next().expect("expected source file as first argument");
+    let filename = std::path::Path::new(&src).file_name().unwrap().to_str().unwrap();
+    let rustc = args.next().expect("expected rustc as second argument");
+    let output = std::process::Command::new(rustc)
+        .arg("--print=target-list")
+        .output()
+        .expect("rustc should run");
+    if !output.status.success() {
+        eprintln!("rustc failed to run");
+        std::process::exit(0);
+    }
+    let stdout = std::str::from_utf8(&output.stdout).expect("utf8");
+    let target_list: HashSet<_> = stdout.lines().collect();
+
+    let doc_targets_md = std::fs::read_to_string(&src).expect("failed to read input source");
+    let doc_targets: HashSet<_> = doc_targets_md
+        .lines()
+        .filter(|line| line.starts_with('`') && line.contains('|'))
+        // These platforms only exist on macos.
+        .filter(|line| !line.contains("[^apple]") || cfg!(target_os = "macos"))
+        .map(|line| line.split('`').skip(1).next().expect("expected target code span"))
+        .collect();
+
+    let missing: Vec<_> = target_list.difference(&doc_targets).collect();
+    let extra: Vec<_> = doc_targets.difference(&target_list).collect();
+    for target in &missing {
+        eprintln!(
+            "error: target `{}` is missing from {}\n\
+            If this is a new target, please add it to {}.",
+            target, filename, src
+        );
+    }
+    for target in &extra {
+        eprintln!(
+            "error: target `{}` is in {}, but does not appear in the rustc target list\n\
+            If the target has been removed, please edit {} and remove the target.",
+            target, filename, src
+        );
+    }
+    if !missing.is_empty() || !extra.is_empty() {
+        std::process::exit(1);
+    }
+}