aboutsummaryrefslogtreecommitdiff
path: root/xtask/src/lib.rs
diff options
context:
space:
mode:
authorGravatar bors[bot] <26634292+bors[bot]@users.noreply.github.com> 2020-08-28 20:34:31 +0000
committerGravatar GitHub <noreply@github.com> 2020-08-28 20:34:31 +0000
commit54f541c87b0723ad8976f978b2233d56100702b6 (patch)
treeb284d3ef162113aeae169228a5b294a1c33f8234 /xtask/src/lib.rs
parent36886f19b6ca0ac3b30ddf8543d330a445506057 (diff)
parent0a118397332c10080c48d76e7416ce854a0260ba (diff)
downloadcortex-m-54f541c87b0723ad8976f978b2233d56100702b6.tar.gz
cortex-m-54f541c87b0723ad8976f978b2233d56100702b6.tar.zst
cortex-m-54f541c87b0723ad8976f978b2233d56100702b6.zip
Merge #261
261: Replace shell scripts with integration test r=therealprof a=jonas-schievink * Removes the Clippy check from CI (I don't think we should fail CI when Clippy finds something, it seems better to use the GitHub Actions plugin) * Tests all targets (thumbv8m.base was missing) * Bumps MSRV to 1.35.0 (to get the thumbv8m.base libcore) Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
Diffstat (limited to 'xtask/src/lib.rs')
-rw-r--r--xtask/src/lib.rs206
1 files changed, 206 insertions, 0 deletions
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
new file mode 100644
index 0000000..4575f65
--- /dev/null
+++ b/xtask/src/lib.rs
@@ -0,0 +1,206 @@
+//! `cargo xtask` automation.
+//!
+//! Please refer to <https://github.com/matklad/cargo-xtask/> for an explanation of the concept.
+//!
+//! Also see the docs in `asm.rs`.
+
+use process::Stdio;
+use std::env::current_dir;
+use std::{
+ collections::BTreeMap,
+ fs::{self, File},
+ process::{self, Command},
+};
+
+fn toolchain() -> String {
+ fs::read_to_string("asm-toolchain")
+ .unwrap()
+ .trim()
+ .to_string()
+}
+
+fn rustc() -> Command {
+ let mut cmd = Command::new("rustc");
+ cmd.arg(format!("+{}", toolchain()));
+ cmd
+}
+
+fn assemble_really(target: &str, cfgs: &[&str], plugin_lto: bool) {
+ let mut cmd = rustc();
+
+ // Set the codegen target.
+ cmd.arg("--target").arg(target);
+ // Set all the `--cfg` directives for the target.
+ cmd.args(cfgs.iter().map(|cfg| format!("--cfg={}", cfg)));
+
+ // We want some level of debuginfo to allow unwinding through the functions.
+ cmd.arg("-g");
+ // We always optimize the assembly shims. There's not really any reason not to.
+ cmd.arg("-O");
+
+ // rustc will usually add frame pointers by default to aid with debugging, but that is a high
+ // overhead for the tiny assembly routines.
+ cmd.arg("-Cforce-frame-pointers=no");
+
+ // We don't want any system-specific paths to show up since we ship the result to other users.
+ // Add `--remap-path-prefix $(pwd)=.`.
+ let mut dir = current_dir().unwrap().as_os_str().to_os_string();
+ dir.push("=.");
+ cmd.arg("--remap-path-prefix").arg(dir);
+
+ // We let rustc build a single object file, not a staticlib, since the latter pulls in loads of
+ // code that will never be used (`compiler_builtins` and `core::fmt`, etc.). We build the static
+ // archive by hand after compiling.
+ cmd.arg("--emit=obj");
+
+ if plugin_lto {
+ // Make artifacts compatible with Linker-Plugin LTO (and incompatible with everything else).
+ cmd.arg("-Clinker-plugin-lto");
+ }
+
+ let file_stub = if plugin_lto {
+ format!("{}-lto", target)
+ } else {
+ target.to_string()
+ };
+
+ let obj_file = format!("bin/{}.o", file_stub);
+
+ // Pass output and input file.
+ cmd.arg("-o").arg(&obj_file);
+ cmd.arg("asm.rs");
+
+ println!("{:?}", cmd);
+ let status = cmd.status().unwrap();
+ assert!(status.success());
+
+ // Archive `target.o` -> `bin/target.a`.
+ let mut builder = ar::Builder::new(File::create(format!("bin/{}.a", file_stub)).unwrap());
+
+ // Use `append`, not `append_path`, to avoid adding any filesystem metadata (modification times,
+ // etc.).
+ let file = fs::read(&obj_file).unwrap();
+ builder
+ .append(
+ &ar::Header::new(obj_file.as_bytes().to_vec(), file.len() as u64),
+ &*file,
+ )
+ .unwrap();
+
+ fs::remove_file(&obj_file).unwrap();
+}
+
+fn assemble(target: &str, cfgs: &[&str]) {
+ assemble_really(target, cfgs, false);
+ assemble_really(target, cfgs, true);
+}
+
+// `--target` -> `--cfg` list (mirrors what `build.rs` does).
+static TARGETS: &[(&str, &[&str])] = &[
+ ("thumbv6m-none-eabi", &[]),
+ ("thumbv7m-none-eabi", &["armv7m"]),
+ ("thumbv7em-none-eabi", &["armv7m", "armv7em"]),
+ ("thumbv7em-none-eabihf", &["armv7m", "armv7em", "has_fpu"]),
+ ("thumbv8m.base-none-eabi", &["armv8m", "armv8m_base"]),
+ (
+ "thumbv8m.main-none-eabi",
+ &["armv7m", "armv8m", "armv8m_main"],
+ ),
+ (
+ "thumbv8m.main-none-eabihf",
+ &["armv7m", "armv8m", "armv8m_main", "has_fpu"],
+ ),
+];
+
+pub fn install_targets(targets: &mut dyn Iterator<Item = &str>, toolchain: Option<&str>) {
+ let mut rustup = Command::new("rustup");
+ rustup.arg("target").arg("add").args(targets);
+
+ if let Some(toolchain) = toolchain {
+ rustup.arg("--toolchain").arg(toolchain);
+ }
+
+ let status = rustup.status().unwrap();
+ assert!(status.success(), "rustup command failed: {:?}", rustup);
+}
+
+pub fn assemble_blobs() {
+ let mut cmd = rustc();
+ cmd.arg("-V");
+ cmd.stdout(Stdio::null());
+ let status = cmd.status().unwrap();
+ let toolchain = toolchain();
+
+ if !status.success() {
+ println!(
+ "asm toolchain {} does not seem to be installed. installing it now.",
+ toolchain
+ );
+
+ let mut rustup = Command::new("rustup");
+ let status = rustup.arg("install").arg(&toolchain).status().unwrap();
+ assert!(status.success(), "rustup command failed: {:?}", rustup);
+ }
+
+ install_targets(
+ &mut TARGETS.iter().map(|(target, _)| *target),
+ Some(&*toolchain),
+ );
+
+ for (target, cfgs) in TARGETS {
+ println!("building artifacts for {}", target);
+ assemble(target, cfgs);
+ }
+}
+
+pub fn check_blobs() {
+ // Load each `.a` file in `bin` into memory.
+ let mut files_before = BTreeMap::new();
+ for entry in fs::read_dir("bin").unwrap() {
+ let entry = entry.unwrap();
+ if entry.path().extension().unwrap() == "a" {
+ files_before.insert(
+ entry
+ .path()
+ .file_name()
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .to_string(),
+ fs::read(entry.path()).unwrap(),
+ );
+ }
+ }
+
+ assemble_blobs();
+
+ let mut files_after = BTreeMap::new();
+ for entry in fs::read_dir("bin").unwrap() {
+ let entry = entry.unwrap();
+ if entry.path().extension().unwrap() == "a" {
+ files_after.insert(
+ entry
+ .path()
+ .file_name()
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .to_string(),
+ fs::read(entry.path()).unwrap(),
+ );
+ }
+ }
+
+ // Ensure they contain the same files.
+ let before = files_before.keys().collect::<Vec<_>>();
+ let after = files_after.keys().collect::<Vec<_>>();
+ assert_eq!(before, after);
+
+ for ((file, before), (_, after)) in files_before.iter().zip(files_after.iter()) {
+ if before != after {
+ panic!("{} differs between rebuilds", file);
+ }
+ }
+
+ println!("Blobs identical.");
+}