-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.rs
131 lines (108 loc) · 4.24 KB
/
build.rs
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::{env, path::Path};
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
let bindings = bindgen::Builder::default()
.header("LuaJIT/src/luajit.h")
.header("LuaJIT/src/lualib.h")
.header("LuaJIT/src/lauxlib.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.whitelist_var("lua.*")
.whitelist_type("lua.*")
.whitelist_function("lua.*")
.whitelist_var("LUA.*")
.whitelist_type("LUA.*")
.whitelist_function("LUA.*")
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_dir.join("bindings.rs"))
.expect("Couldn't write bindings!");
#[cfg(not(feature = "ci"))]
{
link();
}
}
fn link() {
#[cfg(target_os = "windows")]
{
use std::{fs::File, io::Write, path::PathBuf, process::Command};
let out_dir = env::var("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
fn get_tool(name: &str) -> Command {
cc::windows_registry::find(&env::var("TARGET").unwrap(), name).unwrap()
}
fn get_exports<P: AsRef<Path>>(dll_path: P) -> Vec<String> {
let dll_path = dll_path.as_ref();
let output = get_tool("dumpbin.exe")
.arg("/EXPORTS")
.arg(dll_path)
.output()
.unwrap();
let stdout = String::from_utf8(output.stdout).unwrap();
stdout
.split("\r\n")
.map(|line| line.trim())
.skip_while(|line| line != &"ordinal hint RVA name")
.skip(2)
.take_while(|line| line != &"")
.map(|line| line.split_whitespace().nth(3).unwrap())
.map(|line| line.to_string())
.collect::<Vec<_>>()
}
fn find_lua_shared_dll() -> Option<PathBuf> {
if let Ok(lua_shared_dll_path) = env::var("LUA_SHARED_DLL_PATH") {
return Some(PathBuf::from(lua_shared_dll_path));
}
let steam_paths: Vec<PathBuf> = [
r#"C:\Program Files (x86)\Steam"#,
r#"C:\SteamLibrary"#,
r#"D:\SteamLibrary"#,
r#"E:\SteamLibrary"#,
r#"F:\SteamLibrary"#,
]
.iter()
.map(|a| a.into())
.collect();
for steam_path in steam_paths {
let lua_shared_dll_path = steam_path
.join("steamapps")
.join("common")
.join("GarrysMod")
.join("bin")
.join("win64")
.join("lua_shared.dll");
if lua_shared_dll_path.is_file() {
return Some(lua_shared_dll_path);
}
}
None
}
let lua_shared_dll_path = find_lua_shared_dll().expect(
"lua_shared.dll couldn't be found! Try setting the environment variable \
LUA_SHARED_DLL_PATH to where lua_shared.dll is located",
);
assert_eq!(lua_shared_dll_path.extension().unwrap(), "dll");
let lua_shared_file_stem = lua_shared_dll_path.file_stem().unwrap().to_str().unwrap();
let lua_shared_lib_path = out_dir.join(format!("{}.lib", lua_shared_file_stem));
let lua_shared_def_path = out_dir.join(format!("{}.def", lua_shared_file_stem));
{
let exports = get_exports(&lua_shared_dll_path);
let mut lua_shared_def = File::create(&lua_shared_def_path).unwrap();
writeln!(lua_shared_def, "EXPORTS").unwrap();
for function_name in exports {
writeln!(lua_shared_def, "{}", function_name).unwrap();
}
}
assert!(get_tool("lib.exe")
.arg("/NOLOGO")
.arg("/MACHINE:x64")
.arg(format!("/DEF:{}", lua_shared_def_path.display()))
.arg(format!("/OUT:{}", lua_shared_lib_path.display()))
.status()
.unwrap()
.success());
println!("cargo:rustc-link-search=native={}", out_dir.display());
println!("cargo:rustc-link-lib=dylib={}", lua_shared_file_stem);
}
}