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