quickscript/
linker.rs

1use which::which;
2
3#[macro_export]
4macro_rules! exists_return {
5    ($cmd: expr) => {
6        if command_exists($cmd) {
7            return $cmd;
8        }
9    };
10}
11
12pub fn command_exists<T>(cmd: T) -> bool
13where
14    T: AsRef<str>,
15{
16    which(cmd.as_ref()).is_ok()
17}
18
19pub fn get_default_linker() -> &'static str {
20    exists_return!("mold");
21    exists_return!("lld");
22    exists_return!("gold");
23    exists_return!("ld");
24    exists_return!("clang");
25    exists_return!("gcc");
26
27    "cc"
28}
29
30#[cfg(any(target_os = "linux", target_os = "android"))]
31pub fn get_dynamic_linker(
32    prefix: String,
33    target_arch: Option<String>,
34    target_env: Option<String>,
35) -> String {
36    use std::env::consts::ARCH;
37
38    use crate::target::ENV;
39
40    let env = target_env.unwrap_or(ENV.to_string());
41
42    if env == "android" {
43        return "/system/lib/ld-android.so".to_string();
44    }
45
46    format!(
47        "{}/lib/ld-linux-{}.so.1",
48        prefix,
49        target_arch.unwrap_or(ARCH.to_string())
50    )
51}
52
53#[cfg(any(target_os = "linux", target_os = "android"))]
54pub fn get_library_dir(
55    prefix_dir: Option<String>,
56    target_arch: Option<String>,
57    target_os: Option<String>,
58    target_env: Option<String>,
59) -> Vec<String> {
60    use std::env::consts::{ARCH, OS};
61
62    use crate::target::ENV;
63
64    let prefix = prefix_dir.unwrap_or(std::env::var("PREFIX").unwrap_or(String::from("/usr")));
65
66    // TODO: mingw support
67
68    vec![
69        format!("-L{}/lib", prefix),
70        format!(
71            "-L{}/lib/{}-{}-{}",
72            prefix,
73            target_arch.clone().unwrap_or(ARCH.to_string()),
74            target_os.clone().unwrap_or(OS.to_string()),
75            target_env.clone().unwrap_or(ENV.to_string())
76        ),
77        format!(
78            "-L{}/{}-{}-{}/lib",
79            prefix,
80            target_arch.clone().unwrap_or(ARCH.to_string()),
81            target_os.unwrap_or(OS.to_string()),
82            target_env.clone().unwrap_or(ENV.to_string())
83        ),
84        "--dynamic-linker".to_string(),
85        get_dynamic_linker(prefix, target_arch, target_env),
86    ]
87}
88
89#[cfg(target_os = "windows")]
90pub fn get_library_dir(_target_arch: String, _target_c: String) -> Vec<String> {
91    todo!("get_library_dir is not supported on Windows yet!")
92}
93
94#[cfg(target_os = "windows")]
95pub fn get_dynamic_linker(
96    _prefix: String,
97    _target_arch: Option<String>,
98    _target_env: Option<String>,
99) -> String {
100    todo!("get_dynamic_linker is not supported on Windows yet!")
101}