diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 0706f3bee05c1..50c909793f5e1 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -170,6 +170,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-32bit", "only-64bit", "only-aarch64", + "only-aarch64-unknown-linux-gnu", "only-apple", "only-arm", "only-avr", @@ -204,6 +205,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-watchos", "only-windows", "only-windows-gnu", + "only-windows-msvc", "only-x86", "only-x86_64", "only-x86_64-fortanix-unknown-sgx", diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5c1d9a2d47e20..5ad688b55287a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -16,16 +16,12 @@ run-make/macos-deployment-target/Makefile run-make/min-global-align/Makefile run-make/native-link-modifier-bundle/Makefile run-make/no-alloc-shim/Makefile -run-make/pdb-buildinfo-cl-cmd/Makefile -run-make/pgo-indirect-call-promotion/Makefile run-make/remap-path-prefix-dwarf/Makefile run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/split-debuginfo/Makefile -run-make/staticlib-dylib-linkage/Makefile run-make/symbol-mangling-hashed/Makefile run-make/sysroot-crates-are-unstable/Makefile -run-make/thumb-none-cortex-m/Makefile run-make/thumb-none-qemu/Makefile run-make/translation/Makefile run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile diff --git a/tests/run-make/mte-ffi/bar.h b/tests/run-make/mte-ffi/bar.h new file mode 100644 index 0000000000000..a2292ae02a308 --- /dev/null +++ b/tests/run-make/mte-ffi/bar.h @@ -0,0 +1,43 @@ +#ifndef __BAR_H +#define __BAR_H + +#include +#include +#include +#include +#include + +// Set the allocation tag on the destination address using the STG instruction. +#define set_tag(tagged_addr) do { \ + asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \ +} while (0) + +int mte_enabled() { + return (getauxval(AT_HWCAP2)) & HWCAP2_MTE; +} + +void *alloc_page() { + // Enable MTE with synchronous checking + if (prctl(PR_SET_TAGGED_ADDR_CTRL, + PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT), + 0, 0, 0)) + { + perror("prctl() failed"); + } + + // Using `mmap` allows us to ensure that, on systems which support MTE, the allocated + // memory is 16-byte aligned for MTE. + // This also allows us to explicitly specify whether the region should be protected by + // MTE or not. + if (mte_enabled()) { + void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE), + PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + } else { + void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE), + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + } +} + +#endif // __BAR_H diff --git a/tests/run-make/mte-ffi/bar_float.c b/tests/run-make/mte-ffi/bar_float.c new file mode 100644 index 0000000000000..a1590f62765a6 --- /dev/null +++ b/tests/run-make/mte-ffi/bar_float.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include "bar.h" + +extern void foo(char*); + +void bar(char *ptr) { + if (((uintptr_t)ptr >> 56) != 0x1f) { + fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); + exit(1); + } +} + +int main(void) +{ + float *ptr = alloc_page(); + if (ptr == MAP_FAILED) + { + perror("mmap() failed"); + return EXIT_FAILURE; + } + + // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be), + // and a different value in the ignored top 4 bits. + ptr = (float *)((uintptr_t)ptr | 0x1fl << 56); + + if (mte_enabled()) { + set_tag(ptr); + } + + ptr[0] = 2.0f; + ptr[1] = 1.5f; + + foo(ptr); // should change the contents of the page and call `bar` + + if (ptr[0] != 0.5f || ptr[1] != 0.2f) { + fprintf(stderr, "invalid data in memory; expected '0.5 0.2', got '%f %f'\n", + ptr[0], ptr[1]); + return EXIT_FAILURE; + } + + return 0; +} diff --git a/tests/run-make/mte-ffi/bar_function.c b/tests/run-make/mte-ffi/bar_function.c new file mode 100644 index 0000000000000..1fa48d32a0c88 --- /dev/null +++ b/tests/run-make/mte-ffi/bar_function.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include "bar.h" + +typedef void (*fp)(int (*)()); + +extern void foo(fp); + +void bar(int (*ptr)()) { + if (((uintptr_t)ptr >> 56) != 0x2f) { + fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); + exit(1); + } + + int r = (*ptr)(); + if (r != 32) { + fprintf(stderr, "invalid return value; expected 32, got '%d'\n", r); + exit(1); + } +} + +int main(void) +{ + fp ptr = alloc_page(); + if (ptr == MAP_FAILED) + { + perror("mmap() failed"); + return EXIT_FAILURE; + } + + // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be), + // and a different value in the ignored top 4 bits. + ptr = (fp)((uintptr_t)&bar | 0x1fl << 56); + + foo(ptr); + + return 0; +} diff --git a/tests/run-make/mte-ffi/bar_int.c b/tests/run-make/mte-ffi/bar_int.c new file mode 100644 index 0000000000000..d1c79e95dc9cb --- /dev/null +++ b/tests/run-make/mte-ffi/bar_int.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include "bar.h" + +extern void foo(unsigned int *); + +void bar(char *ptr) { + if (((uintptr_t)ptr >> 56) != 0x1f) { + fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); + exit(1); + } +} + +int main(void) +{ + // Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag. + // It's only necessary that the tag is preserved across FFI bounds for this test. + unsigned int *ptr; + + ptr = alloc_page(); + if (ptr == MAP_FAILED) + { + perror("mmap() failed"); + return EXIT_FAILURE; + } + + // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be), + // and a different value in the ignored top 4 bits. + ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56); + + if (mte_enabled()) { + set_tag(ptr); + } + + ptr[0] = 61; + ptr[1] = 62; + + foo(ptr); // should change the contents of the page to start with 0x63 0x64 and call `bar` + + if (ptr[0] != 0x63 || ptr[1] != 0x64) { + fprintf(stderr, "invalid data in memory; expected '63 64', got '%d %d'\n", ptr[0], ptr[1]); + return EXIT_FAILURE; + } + + return 0; +} diff --git a/tests/run-make/mte-ffi/bar_string.c b/tests/run-make/mte-ffi/bar_string.c new file mode 100644 index 0000000000000..5669ffd6695e7 --- /dev/null +++ b/tests/run-make/mte-ffi/bar_string.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include "bar.h" + +extern void foo(char*); + +void bar(char *ptr) { + if (((uintptr_t)ptr >> 56) != 0x2f) { + fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); + exit(1); + } + + if (strcmp(ptr, "cd")) { + fprintf(stderr, "invalid data in memory; expected 'cd', got '%s'\n", ptr); + exit(1); + } +} + +int main(void) +{ + // Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag. + // It's only necessary that the tag is preserved across FFI bounds for this test. + char *ptr; + + ptr = alloc_page(); + if (ptr == MAP_FAILED) + { + perror("mmap() failed"); + return EXIT_FAILURE; + } + + // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be), + // and a different value in the ignored top 4 bits. + ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56); + + if (mte_enabled()) { + set_tag(ptr); + } + + ptr[0] = 'a'; + ptr[1] = 'b'; + ptr[2] = '\0'; + + foo(ptr); + + return 0; +} diff --git a/tests/run-make/mte-ffi/foo_float.rs b/tests/run-make/mte-ffi/foo_float.rs new file mode 100644 index 0000000000000..c1bedd5249459 --- /dev/null +++ b/tests/run-make/mte-ffi/foo_float.rs @@ -0,0 +1,19 @@ +#![crate_type = "cdylib"] +#![crate_name = "foo"] + +use std::os::raw::c_float; + +extern "C" { + fn bar(ptr: *const c_float); +} + +#[no_mangle] +pub extern "C" fn foo(ptr: *mut c_float) { + assert_eq!((ptr as usize) >> 56, 0x1f); + + unsafe { + *ptr = 0.5; + *ptr.wrapping_add(1) = 0.2; + bar(ptr); + } +} diff --git a/tests/run-make/mte-ffi/foo_function.rs b/tests/run-make/mte-ffi/foo_function.rs new file mode 100644 index 0000000000000..2c8e0b2623851 --- /dev/null +++ b/tests/run-make/mte-ffi/foo_function.rs @@ -0,0 +1,17 @@ +#![crate_type = "cdylib"] +#![crate_name = "foo"] + +extern "C" fn ret32() -> i32 { + 32 +} + +#[no_mangle] +pub extern "C" fn foo(ptr: extern "C" fn(extern "C" fn() -> i32)) { + assert_eq!((ptr as usize) >> 56, 0x1f); + + // Store an arbitrary tag in the tag bits, and convert back to the correct pointer type. + let p = ((ret32 as usize) | (0x2f << 56)) as *const (); + let p: extern "C" fn() -> i32 = unsafe { std::mem::transmute(p) }; + + unsafe { ptr(p) } +} diff --git a/tests/run-make/mte-ffi/foo_int.rs b/tests/run-make/mte-ffi/foo_int.rs new file mode 100644 index 0000000000000..106d863cb8127 --- /dev/null +++ b/tests/run-make/mte-ffi/foo_int.rs @@ -0,0 +1,19 @@ +#![crate_type = "cdylib"] +#![crate_name = "foo"] + +use std::os::raw::c_uint; + +extern "C" { + fn bar(ptr: *const c_uint); +} + +#[no_mangle] +pub extern "C" fn foo(ptr: *mut c_uint) { + assert_eq!((ptr as usize) >> 56, 0x1f); + + unsafe { + *ptr = 0x63; + *ptr.wrapping_add(1) = 0x64; + bar(ptr); + } +} diff --git a/tests/run-make/mte-ffi/foo_string.rs b/tests/run-make/mte-ffi/foo_string.rs new file mode 100644 index 0000000000000..5474480244892 --- /dev/null +++ b/tests/run-make/mte-ffi/foo_string.rs @@ -0,0 +1,27 @@ +#![crate_type = "cdylib"] +#![crate_name = "foo"] + +use std::arch::asm; +use std::ffi::{CStr, CString}; +use std::os::raw::c_char; + +extern "C" { + fn bar(ptr: *const c_char); +} + +#[no_mangle] +pub extern "C" fn foo(ptr: *const c_char) { + assert_eq!((ptr as usize) >> 56, 0x1f); + + let s = unsafe { CStr::from_ptr(ptr) }; + assert_eq!(s.to_str().unwrap(), "ab"); + + let s = CString::from_vec_with_nul("cd\0".into()).unwrap(); + let mut p = ((s.as_ptr() as usize) | (0x2f << 56)) as *const c_char; + unsafe { + #[cfg(target_feature = "mte")] + asm!("stg {p}, [{p}]", p = inout(reg) p); + + bar(p); + } +} diff --git a/tests/run-make/mte-ffi/rmake.rs b/tests/run-make/mte-ffi/rmake.rs new file mode 100644 index 0000000000000..f4fafb796e3c5 --- /dev/null +++ b/tests/run-make/mte-ffi/rmake.rs @@ -0,0 +1,38 @@ +// Tests that MTE tags and values stored in the top byte of a pointer (TBI) are +// preserved across FFI boundaries (C <-> Rust). +// This test does not require MTE: whilst the test will use MTE if available, if it is not, +// arbitrary tag bits are set using TBI. + +// This test is only valid for AArch64. +// The linker must be explicitly specified when cross-compiling, so it is limited to +// `aarch64-unknown-linux-gnu`. +//@ only-aarch64-unknown-linux-gnu + +use run_make_support::{cc, dynamic_lib_name, extra_c_flags, run, rustc, target}; + +fn main() { + run_test("int"); + run_test("float"); + run_test("string"); + run_test("function"); +} + +fn run_test(variant: &str) { + let flags = { + let mut flags = extra_c_flags(); + flags.push("-march=armv8.5-a+memtag"); + flags + }; + println!("{variant} test..."); + rustc() + .input(format!("foo_{variant}.rs")) + .target(target()) + .linker("aarch64-linux-gnu-gcc") + .run(); + cc().input(format!("bar_{variant}.c")) + .input(dynamic_lib_name("foo")) + .out_exe("test") + .args(&flags) + .run(); + run("test"); +} diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/Makefile b/tests/run-make/pdb-buildinfo-cl-cmd/Makefile deleted file mode 100644 index a7be301a5b0d2..0000000000000 --- a/tests/run-make/pdb-buildinfo-cl-cmd/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -include ../tools.mk - -# only-windows-msvc - -# tests if the pdb contains the following information in the LF_BUILDINFO: -# 1. the commandline args to compile it (cmd) -# 2. full path to the compiler (cl) - -# we just do a stringsearch on the pdb, as these need to show up at least once, as the LF_BUILDINFO is created for each cgu -# actual parsing would be better, but this is a simple and good enough solution for now - -all: - $(RUSTC_ORIGINAL) main.rs -g --crate-name my_crate_name --crate-type bin -C metadata=dc9ef878b0a48666 --out-dir $(TMPDIR) - cat '$(TMPDIR)/my_crate_name.pdb' | grep -F '$(RUSTC_ORIGINAL)' -# using a file containing the string so I don't have problems with escaping quotes and spaces - cat '$(TMPDIR)/my_crate_name.pdb' | grep -f 'stringlist.txt' diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs new file mode 100644 index 0000000000000..2ab9057b24c1b --- /dev/null +++ b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs @@ -0,0 +1,39 @@ +// Check if the pdb file contains the following information in the LF_BUILDINFO: +// 1. full path to the compiler (cl) +// 2. the commandline args to compile it (cmd) +// This is because these used to be missing in #96475. +// See https://github.com/rust-lang/rust/pull/113492 + +//@ only-windows-msvc +// Reason: pdb files are unique to this architecture + +use run_make_support::{assert_contains, bstr, env_var, rfs, rustc}; + +fn main() { + rustc() + .input("main.rs") + .arg("-g") + .crate_name("my_crate_name") + .crate_type("bin") + .metadata("dc9ef878b0a48666") + .run(); + let tests = [ + &env_var("RUSTC"), + r#""main.rs""#, + r#""-g""#, + r#""--crate-name""#, + r#""my_crate_name""#, + r#""--crate-type""#, + r#""bin""#, + r#""-Cmetadata=dc9ef878b0a48666""#, + ]; + for test in tests { + assert_pdb_contains(test); + } +} + +fn assert_pdb_contains(needle: &str) { + let needle = needle.as_bytes(); + use bstr::ByteSlice; + assert!(&rfs::read("my_crate_name.pdb").find(needle).is_some()); +} diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt b/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt deleted file mode 100644 index 634e9f19e8973..0000000000000 --- a/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt +++ /dev/null @@ -1 +0,0 @@ -"main.rs" "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-C" "metadata=dc9ef878b0a48666" "--out-dir" \ No newline at end of file diff --git a/tests/run-make/pgo-indirect-call-promotion/Makefile b/tests/run-make/pgo-indirect-call-promotion/Makefile deleted file mode 100644 index 8d1e69c4aba37..0000000000000 --- a/tests/run-make/pgo-indirect-call-promotion/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# needs-profiler-support -# ignore-cross-compile - -include ../tools.mk - -all: - # We don't compile `opaque` with either optimizations or instrumentation. - # We don't compile `opaque` with either optimizations or instrumentation. - $(RUSTC) $(COMMON_FLAGS) opaque.rs - # Compile the test program with instrumentation - mkdir -p "$(TMPDIR)"/prof_data_dir - $(RUSTC) $(COMMON_FLAGS) interesting.rs \ - -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O -Ccodegen-units=1 - $(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O - # The argument below generates to the expected branch weights - $(call RUN,main) || exit 1 - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/prof_data_dir/merged.profdata \ - "$(TMPDIR)"/prof_data_dir - $(RUSTC) $(COMMON_FLAGS) interesting.rs \ - -Cprofile-use="$(TMPDIR)"/prof_data_dir/merged.profdata -O \ - -Ccodegen-units=1 --emit=llvm-ir - cat "$(TMPDIR)"/interesting.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs new file mode 100644 index 0000000000000..d0ccfd8a4d7e4 --- /dev/null +++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs @@ -0,0 +1,33 @@ +// This test checks that indirect call promotion is performed. The test +// programs calls the same function a thousand times through a function pointer. +// Only PGO data provides the information that it actually always is the same +// function. We verify that the indirect call promotion pass inserts a check +// whether it can make a direct call instead of the indirect call. +// See https://github.com/rust-lang/rust/pull/66631 + +//@ needs-profiler-support +// Reason: llvm_profdata is used +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run, rustc}; + +fn main() { + // We don't compile `opaque` with either optimizations or instrumentation. + rustc().input("opaque.rs").run(); + // Compile the test program with instrumentation + rfs::create_dir("prof_data_dir"); + rustc().input("interesting.rs").profile_generate("prof_data_dir").opt().codegen_units(1).run(); + rustc().input("main.rs").profile_generate("prof_data_dir").opt().run(); + // The argument below generates to the expected branch weights + run("main"); + llvm_profdata().merge().output("prof_data_dir/merged.profdata").input("prof_data_dir").run(); + rustc() + .input("interesting.rs") + .profile_use("prof_data_dir/merged.profdata") + .opt() + .codegen_units(1) + .emit("llvm-ir") + .run(); + llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run(); +} diff --git a/tests/run-make/staticlib-dylib-linkage/Makefile b/tests/run-make/staticlib-dylib-linkage/Makefile deleted file mode 100644 index a1e86a7ce4b65..0000000000000 --- a/tests/run-make/staticlib-dylib-linkage/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../tools.mk - -# ignore-cross-compile -# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain -# ignore-wasm wasm doesn't support dynamic libraries - -all: - $(RUSTC) -C prefer-dynamic bar.rs - $(RUSTC) foo.rs --crate-type staticlib --print native-static-libs \ - -Z staticlib-allow-rdylib-deps 2>&1 | grep 'note: native-static-libs: ' \ - | sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt - cat $(TMPDIR)/libs.txt - -ifdef IS_MSVC - $(CC) $(CFLAGS) /c foo.c /Fo:$(TMPDIR)/foo.o - $(RUSTC_LINKER) $(TMPDIR)/foo.o $(TMPDIR)/foo.lib $$(cat $(TMPDIR)/libs.txt) $(call OUT_EXE,foo) -else - $(CC) $(CFLAGS) foo.c -L $(TMPDIR) -lfoo $$(cat $(TMPDIR)/libs.txt) -o $(call RUN_BINFILE,foo) -endif - - $(call RUN,foo) diff --git a/tests/run-make/staticlib-dylib-linkage/rmake.rs b/tests/run-make/staticlib-dylib-linkage/rmake.rs new file mode 100644 index 0000000000000..415491bb8ee0a --- /dev/null +++ b/tests/run-make/staticlib-dylib-linkage/rmake.rs @@ -0,0 +1,37 @@ +// A basic smoke test to check that rustc supports linking to a rust dylib with +// --crate-type staticlib. bar is a dylib, on which foo is dependent - the native +// static lib search paths are collected and used to compile foo.c, the final executable +// which depends on both foo and bar. +// See https://github.com/rust-lang/rust/pull/106560 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed. +//@ ignore-wasm +// Reason: WASM does not support dynamic libraries +//@ ignore-msvc +//FIXME(Oneirical): Getting this to work on MSVC requires passing libcmt.lib to CC, +// which is not trivial to do. +// Tracking issue: https://github.com/rust-lang/rust/issues/128602 +// Discussion: https://github.com/rust-lang/rust/pull/128407#discussion_r1702439172 + +use run_make_support::{cc, regex, run, rustc}; + +fn main() { + rustc().arg("-Cprefer-dynamic").input("bar.rs").run(); + let libs = rustc() + .input("foo.rs") + .crate_type("staticlib") + .print("native-static-libs") + .arg("-Zstaticlib-allow-rdylib-deps") + .run() + .assert_stderr_contains("note: native-static-libs: ") + .stderr_utf8(); + let re = regex::Regex::new(r#"note: native-static-libs:\s*(.+)"#).unwrap(); + let libs = re.find(&libs).unwrap().as_str().trim(); + // remove the note + let (_, library_search_paths) = libs.split_once("note: native-static-libs: ").unwrap(); + // divide the command-line arguments in a vec + let library_search_paths = library_search_paths.split(' ').collect::>(); + cc().input("foo.c").arg("-lfoo").args(library_search_paths).out_exe("foo").run(); + run("foo"); +} diff --git a/tests/run-make/thumb-none-cortex-m/Makefile b/tests/run-make/thumb-none-cortex-m/Makefile deleted file mode 100644 index e941fc4a78e1c..0000000000000 --- a/tests/run-make/thumb-none-cortex-m/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -include ../tools.mk - -# How to run this -# $ ./x.py clean -# $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi tests/run-make - -# Supported targets: -# - 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) - -# only-thumb - -# For cargo setting -RUSTC := $(RUSTC_ORIGINAL) -LD_LIBRARY_PATH := $(HOST_RPATH_DIR) -# We need to be outside of 'src' dir in order to run cargo -WORK_DIR := $(TMPDIR) - -HERE := $(shell pwd) - -CRATE := cortex-m -CRATE_URL := https://github.com/rust-embedded/cortex-m -CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0 - -# Don't make lints fatal, but they need to at least warn or they break Cargo's target info parsing. -export RUSTFLAGS := --cap-lints=warn - -all: - env - mkdir -p $(WORK_DIR) - -cd $(WORK_DIR) && rm -rf $(CRATE) - cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1) - # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. - # These come from the top-level Rust workspace, that this crate is not a - # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. - cd $(WORK_DIR) && cd $(CRATE) && env RUSTC_BOOTSTRAP=1 $(BOOTSTRAP_CARGO) build --target $(TARGET) -v diff --git a/tests/run-make/thumb-none-cortex-m/rmake.rs b/tests/run-make/thumb-none-cortex-m/rmake.rs new file mode 100644 index 0000000000000..0ddb91d378fb7 --- /dev/null +++ b/tests/run-make/thumb-none-cortex-m/rmake.rs @@ -0,0 +1,59 @@ +//! Test building of the `cortex-m` crate, a foundational crate in the embedded ecosystem +//! for a collection of thumb targets. This is a smoke test that verifies that both cargo +//! and rustc work in this case. +//! +//! How to run this +//! $ ./x.py clean +//! $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi tests/run-make +//! +//! Supported targets: +//! - 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) + +//@ only-thumb + +use std::path::PathBuf; + +use run_make_support::rfs::create_dir; +use run_make_support::{cmd, env_var, target}; + +const CRATE: &str = "cortex-m"; +const CRATE_URL: &str = "https://github.com/rust-embedded/cortex-m"; +const CRATE_SHA1: &str = "a448e9156e2cb1e556e5441fd65426952ef4b927"; // v0.5.0 + +fn main() { + // FIXME: requires an internet connection https://github.com/rust-lang/rust/issues/128733 + // See below link for git usage: + // https://stackoverflow.com/questions/3489173#14091182 + cmd("git").args(["clone", CRATE_URL, CRATE]).run(); + std::env::set_current_dir(CRATE).unwrap(); + cmd("git").args(["reset", "--hard", CRATE_SHA1]).run(); + + let target_dir = PathBuf::from("target"); + let manifest_path = PathBuf::from("Cargo.toml"); + + let path = env_var("PATH"); + let rustc = env_var("RUSTC"); + let bootstrap_cargo = env_var("BOOTSTRAP_CARGO"); + // FIXME: extract bootstrap cargo invocations to a proper command + // https://github.com/rust-lang/rust/issues/128734 + let mut cmd = cmd(bootstrap_cargo); + cmd.args(&[ + "build", + "--manifest-path", + manifest_path.to_str().unwrap(), + "-Zbuild-std=core", + "--target", + &target(), + ]) + .env("PATH", path) + .env("RUSTC", rustc) + .env("CARGO_TARGET_DIR", &target_dir) + // Don't make lints fatal, but they need to at least warn + // or they break Cargo's target info parsing. + .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes --cap-lints=warn"); + + cmd.run(); +}