genfut/
genc.rs

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}