1use core::panic;
2use std::fs::create_dir_all;
3use std::path::PathBuf;
4use std::process::Command;
5use std::str::FromStr;
6
7#[derive(Debug, Clone, Copy)]
8pub enum Backend {
9 Cuda,
10 ISPC,
11 Multicore,
12 OpenCL,
13 C,
14}
15
16impl FromStr for Backend {
17 type Err = String;
18
19 fn from_str(s: &str) -> Result<Self, Self::Err> {
20 let s = s.to_lowercase();
21
22 match s.trim() {
23 "cuda" => Ok(Backend::Cuda),
24 "ispc" => Ok(Backend::ISPC),
25 "multicore" => Ok(Backend::Multicore),
26 "opencl" => Ok(Backend::OpenCL),
27 "c" => Ok(Backend::C),
28 _ => Err("Unknown backend, availible backends are: cuda, ispc, multicore (written in in c), none, opencl, c (sequential).".to_owned()),
29 }
30 }
31}
32
33impl Backend {
34 pub(crate) fn to_feature(self) -> &'static str {
35 match self {
36 Backend::Cuda => "cuda",
37 Backend::ISPC => "ispc",
38 Backend::Multicore => "multicore",
39 Backend::OpenCL => "opencl",
40 Backend::C => "c",
41 }
42 }
43}
44
45pub(crate) fn gen_c(backend: Backend, in_file: &std::path::Path, out_dir: &std::path::Path) {
46 let out_path = PathBuf::from(out_dir);
47 let lib_dir = out_path.join("lib");
48 if let Err(e) = create_dir_all(lib_dir.clone()) {
49 eprintln!("Error creating {} ({})", lib_dir.display(), e);
50 std::process::exit(1);
51 }
52 let output = Command::new("futhark")
53 .arg(backend.to_feature())
54 .arg("--library")
55 .arg("-o")
56 .arg(format!(
57 "{}/lib/a",
58 out_dir.to_str().expect("[gen_c] out_dir failed!")
59 ))
60 .arg(in_file)
61 .output()
62 .expect("[gen_c] failed to execute process");
63 if !output.status.success() {
64 println!(
65 "Futhark stdout: {}",
66 String::from_utf8(output.stdout).unwrap()
67 );
68 eprintln!(
69 "Futhark stderr: {}",
70 String::from_utf8(output.stderr).unwrap()
71 );
72 println!("Futhark status: {}", output.status);
73 panic!("Futhark did not run successfully.")
74 }
75}
76
77pub(crate) fn generate_bindings(header: &std::path::Path, out: &std::path::Path) {
78 let bindings = bindgen::Builder::default()
79 .header(
80 header
81 .to_str()
82 .expect("[generate_bindings] Error with header!"),
83 )
84 .generate()
85 .expect("Unable to generate bindings");
86 let out_path = PathBuf::from(out);
87 bindings
88 .write_to_file(out_path.join("bindings.rs"))
89 .expect("Couldn't write bindings!");
90}