// Tests the -Zembed-metadata compiler flag. // Tracking issue: https://github.com/rust-lang/rust/issues/139165 use run_make_support::rfs::{create_dir, remove_file, rename}; use run_make_support::{Rustc, dynamic_lib_name, path, run_in_tmpdir, rust_lib_name, rustc}; #[derive(Debug, Copy, Clone)] enum LibraryKind { Rlib, Dylib, } impl LibraryKind { fn crate_type(&self) -> &str { match self { LibraryKind::Rlib => "rlib", LibraryKind::Dylib => "dylib", } } fn add_extern(&self, rustc: &mut Rustc, dep_name: &str, dep_path: &str) { let dep_path = match self { LibraryKind::Dylib => format!("{dep_path}/{}", dynamic_lib_name(dep_name)), LibraryKind::Rlib => format!("{dep_path}/{}", rust_lib_name(dep_name)), }; rustc.extern_(dep_name, dep_path); } } fn main() { // The compiler takes different paths based on if --extern is passed or not, so we test all // combinations (`rlib`/`dylib` x `--extern`/`no --extern`). for kind in [LibraryKind::Rlib, LibraryKind::Dylib] { eprintln!("Testing library kind {kind:?}"); lookup_rmeta_in_lib_dir(kind); lookup_rmeta_through_extern(kind); lookup_rmeta_missing(kind); } } // Lookup .rmeta file in the same directory as a rlib/dylib with stub metadata. fn lookup_rmeta_in_lib_dir(kind: LibraryKind) { run_in_tmpdir(|| { build_dep_rustc(kind).run(); rustc().input("foo.rs").run(); }); } // Lookup .rmeta file when specifying the dependency using --extern. fn lookup_rmeta_through_extern(kind: LibraryKind) { run_in_tmpdir(|| { // Generate libdep1.rlib and libdep1.rmeta in deps create_dir("deps"); build_dep_rustc(kind).out_dir("deps").run(); let mut rustc = rustc(); kind.add_extern(&mut rustc, "dep1", "deps"); rustc.extern_("dep1", path("deps").join("libdep1.rmeta")); rustc.input("foo.rs").run(); }); } // Check the error message when the .rmeta file is missing. fn lookup_rmeta_missing(kind: LibraryKind) { run_in_tmpdir(|| { create_dir("deps"); build_dep_rustc(kind).out_dir("deps").run(); let mut rustc = rustc(); kind.add_extern(&mut rustc, "dep1", "deps"); rustc.input("foo.rs").run_fail().assert_stderr_contains("only metadata stub found"); }); } fn build_dep_rustc(kind: LibraryKind) -> Rustc { let mut dep_rustc = rustc(); dep_rustc .arg("-Zembed-metadata=no") .crate_type(kind.crate_type()) .input("dep1.rs") .emit("metadata,link"); if matches!(kind, LibraryKind::Dylib) { dep_rustc.arg("-Cprefer-dynamic"); } dep_rustc }