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
fn main() {
let parser = "rust";
if parser == "haskell" {
use std::process::Command;
let subfolder = "lib";
let haskell_file = "ParserFFI.hs";
let c_file = "parser_api.c";
let haskell_library = "amethyst_parser";
let c_api_library = "amethyst_parser_api";
// Erases last build and prepares the lib folder for the shared objects
Command::new("rm").args(&["-r", "./lib"]).status().unwrap();
Command::new("mkdir").args(&[subfolder]).status().unwrap();
// Creates the Haskell shared library which we call from C
Command::new("ghc")
.args(&[
&format!("./src/{}", haskell_file),
"-dynamic",
"-shared",
"-fPIC",
"-isrc",
"-no-keep-hi-files",
"-no-keep-o-files",
"-stubdir ./clean",
"-o",
&format!("./{}/lib{}.so", subfolder, haskell_library),
])
.status()
.expect("Unable to create hs shared object");
// Creates the C API library
Command::new("gcc")
.args(&[
&format!("./src/{}", c_file),
"-shared",
// Paths for haskell-c linking
"-I/usr/lib/ghc/include",
"-L/usr/lib/ghc/rts",
"-Wl,-rpath,/usr/lib/ghc/rts",
// Paths for running from top of the project
&format!("-L./{}", subfolder),
&format!("-Wl,-rpath,./{}", subfolder),
// Paths for running from ./src
&format!("-L./../{}", subfolder),
&format!("-Wl,-rpath,./../{}", subfolder),
// Paths for running from ./subfolder folder
"-L.",
"-Wl,-rpath,.",
"-lHSrts-ghc8.8.4",
&format!("-l{}", haskell_library),
"-o",
&format!("./{}/lib{}.so", subfolder, c_api_library),
])
.status()
.expect("Unable to create c shared object");
// Delete the useless files
Command::new("rm")
.args(&["-r", "./clean"])
.status()
.unwrap();
// Alternative to "export LD_LIBRARY_PATH=.:./src"
println!(
"{}",
format!(
"cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN/../../{}",
subfolder
)
);
// Also the relative path from the tests directory
println!(
"{}",
format!(
"cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN/../../../{}",
subfolder
)
);
// Specify the libraries' location
println!(
"{}",
format!("cargo:rustc-link-search=native=./{}/", subfolder)
);
// Specify all the shared libraries
println!(
"{}",
format!("cargo:rustc-link-lib=dylib={}", haskell_library)
);
println!(
"{}",
format!("cargo:rustc-link-lib=dylib={}", c_api_library)
);
}
}