Have bindgen CLI accept an output path

This commit is contained in:
Richard Feldman 2022-05-05 14:40:48 -04:00
parent 882e1a7c29
commit 2ed35e8a04
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798

View file

@ -1,46 +1,110 @@
use clap::{ArgEnum, Parser}; use clap::Parser;
use std::io::ErrorKind; use roc_bindgen::bindgen_rs;
use roc_bindgen::load::load_types;
use std::ffi::OsStr;
use std::fs::File;
use std::io::{ErrorKind, Write};
use std::path::PathBuf; use std::path::PathBuf;
use std::{fs, process}; use std::process;
#[derive(Clone, Debug, ArgEnum)] /// Printed in error messages if you try to use an unsupported extension.
enum TargetFormat { const SUPPORTED_EXTENSIONS: &str = ".c, .rs, .zig, and .json";
Rust,
Json,
C,
Zig,
}
// TODO add an option for --targets so that you can specify // TODO add an option for --targets so that you can specify
// e.g. 64-bit, 32-bit, *and* 16-bit (which can matter for alignment because of pointers) // e.g. 64-bit, 32-bit, *and* 16-bit (which can matter for alignment because of pointers)
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap(about)] #[clap(about)]
struct Opts { struct Opts {
/// The output format
#[clap(arg_enum)]
target: TargetFormat,
/// The path to the platform's Package-Config.roc file /// The path to the platform's Package-Config.roc file
platform_module: PathBuf, platform_module: PathBuf,
/// The output file, e.g. `test.rs`
dest: PathBuf,
}
enum OutputType {
Rust,
C,
Zig,
Json,
} }
pub fn main() { pub fn main() {
let opts = Opts::parse(); let opts = Opts::parse();
let path = opts.platform_module; let input_path = opts.platform_module;
let cwd = std::env::current_dir().unwrap();
let output_path = opts.dest;
let output_type = match output_path.extension().and_then(OsStr::to_str) {
Some("rs") => OutputType::Rust,
Some("c") => OutputType::C,
Some("zig") => OutputType::Zig,
Some("json") => OutputType::Json,
Some(other) => {
eprintln!(
"Unsupported output file extension: \".{}\" - currently supported extensions are {}",
other,
SUPPORTED_EXTENSIONS
);
match fs::read_to_string(&path) { process::exit(1);
Ok(src) => { }
println!("Got this source: {:?}", src); None => {
eprintln!("The output file path needs to have a file extension in order to tell what output format to use. Currently supported extensions are {}", SUPPORTED_EXTENSIONS);
process::exit(1);
}
};
match load_types(input_path.clone(), &cwd) {
Ok(types) => {
let mut buf = String::new();
let result = match output_type {
OutputType::Rust => bindgen_rs::write_types(&types, &mut buf),
OutputType::C => todo!("TODO: Generate bindings for C"),
OutputType::Zig => todo!("TODO: Generate bindings for Zig"),
OutputType::Json => todo!("TODO: Generate bindings for JSON"),
};
if let Err(err) = result {
eprintln!(
"Unable to generate binding string {} - {:?}",
output_path.display(),
err
);
process::exit(1);
}
let mut file = File::create(output_path.clone()).unwrap_or_else(|err| {
eprintln!(
"Unable to create output file {} - {:?}",
output_path.display(),
err
);
process::exit(1);
});
file.write_all(buf.as_bytes()).unwrap_or_else(|err| {
eprintln!(
"Unable to write bindings to output file {} - {:?}",
output_path.display(),
err
);
process::exit(1);
});
} }
Err(err) => match err.kind() { Err(err) => match err.kind() {
ErrorKind::NotFound => { ErrorKind::NotFound => {
eprintln!("Platform module file not found: {}", path.display()); eprintln!("Platform module file not found: {}", input_path.display());
process::exit(1); process::exit(1);
} }
error => { error => {
eprintln!( eprintln!(
"Error loading platform module file {} - {:?}", "Error loading platform module file {} - {:?}",
path.display(), input_path.display(),
error error
); );
process::exit(1); process::exit(1);