about summary refs log tree commit diff
path: root/tests/run-make/embed-metadata/rmake.rs
blob: 2de6575feb88652077dbd1889ba4980058397ca5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//@ ignore-cross-compile
//@ needs-crate-type: dylib

// 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
}