idalib_build/
lib.rs

1use std::env;
2use std::path::{Path, PathBuf};
3
4fn link_path() -> PathBuf {
5    #[cfg(target_os = "macos")]
6    return PathBuf::from("/Applications/IDA Professional 9.2.app/Contents/MacOS");
7
8    #[cfg(target_os = "linux")]
9    return PathBuf::from(env::var("HOME").unwrap()).join("ida-pro-9.2");
10
11    #[cfg(target_os = "windows")]
12    return PathBuf::from("C:\\Program Files\\IDA Professional 9.2");
13}
14
15pub fn idalib_sdk_paths() -> (PathBuf, PathBuf, PathBuf, PathBuf) {
16    idalib_sdk_paths_with(true)
17}
18
19pub fn idalib_sdk_paths_with(check: bool) -> (PathBuf, PathBuf, PathBuf, PathBuf) {
20    let sdk_path = PathBuf::from(env!("IDALIB_SDK"));
21    let pro_h = sdk_path.join("include").join("pro.h");
22
23    if check && !pro_h.exists() {
24        panic!("`{}` does not exist; SDK is not usable", pro_h.display());
25    }
26
27    let (stubs_path, idalib, ida) = if cfg!(target_os = "linux") {
28        let path = sdk_path.join("lib/x64_linux_gcc_64");
29        let idalib = path.join("libidalib.so");
30        let ida = path.join("libida.so");
31        (path, idalib, ida)
32    } else if cfg!(target_os = "macos") {
33        let path = if cfg!(target_arch = "x86_64") {
34            sdk_path.join("lib/x64_mac_clang_64")
35        } else {
36            sdk_path.join("lib/arm64_mac_clang_64")
37        };
38        let idalib = path.join("libidalib.dylib");
39        let ida = path.join("libida.dylib");
40        (path, idalib, ida)
41    } else if cfg!(target_os = "windows") {
42        let path = sdk_path.join("lib\\x64_win_vc_64");
43        let idalib = path.join("idalib.lib");
44        let ida = path.join("ida.lib");
45        (path, idalib, ida)
46    } else {
47        panic!("unsupported platform");
48    };
49
50    (sdk_path, stubs_path, idalib, ida)
51}
52
53pub fn idalib_install_paths() -> (PathBuf, PathBuf, PathBuf) {
54    idalib_install_paths_with(true)
55}
56
57pub fn idalib_install_paths_with(check: bool) -> (PathBuf, PathBuf, PathBuf) {
58    let path = env::var("IDADIR").map_or_else(|_| link_path(), PathBuf::from);
59
60    let (idalib, ida) = if cfg!(target_os = "linux") {
61        (path.join("libidalib.so"), path.join("libida.so"))
62    } else if cfg!(target_os = "macos") {
63        (path.join("libidalib.dylib"), path.join("libida.dylib"))
64    } else if cfg!(target_os = "windows") {
65        (path.join("idalib.dll"), path.join("ida.dll"))
66    } else {
67        panic!("unsupported platform")
68    };
69
70    if check && !idalib.exists() {
71        panic!(
72            "`{}` does not exist; cannot find a compatible IDA Pro installation",
73            idalib.display()
74        );
75    }
76
77    (path, idalib, ida)
78}
79
80pub fn idalib_library_paths() -> (PathBuf, PathBuf) {
81    idalib_library_paths_with(true)
82}
83
84pub fn idalib_library_paths_with(check: bool) -> (PathBuf, PathBuf) {
85    let (_, idalib, ida) = idalib_install_paths_with(check);
86    (idalib, ida)
87}
88
89fn configure_linkage_aux(path: &Path) {
90    println!("cargo::rustc-link-search=native={}", path.display());
91    if cfg!(target_os = "windows") {
92        // .lib
93        println!("cargo::rustc-link-lib=static=ida");
94        println!("cargo::rustc-link-lib=static=idalib");
95    } else {
96        // .dylib/.so
97        println!("cargo::rustc-link-lib=dylib=ida");
98        println!("cargo::rustc-link-lib=dylib=idalib");
99    }
100}
101
102pub fn configure_idalib_linkage() {
103    let (install_path, _, _) = idalib_install_paths();
104    configure_linkage_aux(&install_path);
105}
106
107pub fn configure_idasdk_linkage() {
108    let (_, stubs_path, _, _) = idalib_sdk_paths();
109    configure_linkage_aux(&stubs_path);
110
111    if cfg!(target_os = "windows") {
112        // FIXME: this seems to be required otherwise we report missing symbols and bail during
113        // linking (seems to be due to autocxx)...
114        println!("cargo::rustc-link-arg=/FORCE:UNRESOLVED");
115    }
116}
117
118pub fn configure_linkage() -> anyhow::Result<()> {
119    if cfg!(target_os = "windows") {
120        configure_idasdk_linkage();
121        return Ok(());
122    }
123
124    #[cfg(not(target_os = "windows"))]
125    {
126        let (install_path, _, _) = idalib_install_paths();
127        let (_, stub_path, _, _) = idalib_sdk_paths();
128
129        #[cfg(target_os = "linux")]
130        {
131            println!(
132                "cargo::rustc-link-arg=-Wl,-rpath,{},-L{},-l:libida.so",
133                install_path.display(),
134                stub_path.display(),
135            );
136            println!(
137                "cargo::rustc-link-arg=-Wl,-rpath,{},-L{},-l:libidalib.so",
138                install_path.display(),
139                stub_path.display(),
140            );
141        }
142
143        #[cfg(target_os = "macos")]
144        {
145            println!(
146                "cargo::rustc-link-arg=-Wl,-rpath,{},-L{},-lida",
147                install_path.display(),
148                stub_path.display(),
149            );
150            println!(
151                "cargo::rustc-link-arg=-Wl,-rpath,{},-L{},-lidalib",
152                install_path.display(),
153                stub_path.display(),
154            );
155        }
156    }
157
158    Ok(())
159}