futhark_bindgen/
compiler.rs

1use crate::*;
2
3/// Wrapper around the Futhark compiler
4#[derive(Debug, Clone)]
5pub struct Compiler {
6    exe: String,
7    backend: Backend,
8    src: std::path::PathBuf,
9    extra_args: Vec<String>,
10    output_dir: std::path::PathBuf,
11}
12
13impl Compiler {
14    /// Create a new `Compiler` instance with the selected backend and Futhark source file
15    pub fn new(backend: Backend, src: impl AsRef<std::path::Path>) -> Compiler {
16        Compiler {
17            exe: String::from("futhark"),
18            src: src.as_ref().to_path_buf(),
19            extra_args: Vec::new(),
20            output_dir: src
21                .as_ref()
22                .canonicalize()
23                .unwrap()
24                .parent()
25                .unwrap()
26                .to_path_buf(),
27            backend,
28        }
29    }
30
31    /// By default the executable name is set to `futhark`, this function can be
32    /// used to set a different name or path
33    pub fn with_executable_name(mut self, name: impl AsRef<str>) -> Self {
34        self.exe = name.as_ref().into();
35        self
36    }
37
38    /// Supply additional arguments to be passed to the `futhark` executable
39    pub fn with_extra_args(mut self, args: Vec<String>) -> Self {
40        self.extra_args = args;
41        self
42    }
43
44    /// Set the output directory where the C files and manifest will be created
45    pub fn with_output_dir(mut self, dir: impl AsRef<std::path::Path>) -> Self {
46        self.output_dir = dir.as_ref().to_path_buf();
47        self
48    }
49
50    /// Compile the package
51    ///
52    /// This will generate a C file, C header file and manifest
53    pub fn compile(&self) -> Result<Package, Error> {
54        // Create -o argument
55        let output = &self
56            .output_dir
57            .join(self.src.with_extension("").file_name().unwrap());
58
59        let ok = std::process::Command::new(&self.exe)
60            .arg(self.backend.to_str())
61            .args(&self.extra_args)
62            .args(["-o", &output.to_string_lossy()])
63            .arg("--lib")
64            .arg(&self.src)
65            .status()?
66            .success();
67
68        if !ok {
69            return Err(Error::CompilationFailed);
70        }
71
72        // Load manifest after successful compilation
73        let manifest = Manifest::parse_file(output.with_extension("json"))?;
74        let c_file = output.with_extension("c");
75        let h_file = output.with_extension("h");
76        Ok(Package {
77            manifest,
78            c_file,
79            h_file,
80            src: self.src.clone(),
81        })
82    }
83}