aya-gen: run bindgen as a child process

pull/297/head
Davide Bertola 3 years ago
parent 3694ccb469
commit 044877a435

@ -13,3 +13,4 @@ syn = "1"
quote = "1" quote = "1"
proc-macro2 = "1" proc-macro2 = "1"
indexmap = "1.6" indexmap = "1.6"
tempfile = "3"

@ -1,10 +1,13 @@
use std::{ use std::{
fs, io, fs::{self, File},
io::{self, Write},
path::{Path, PathBuf}, path::{Path, PathBuf},
process::Command, process::Command,
str::from_utf8, str::from_utf8,
}; };
use tempfile::tempdir;
use thiserror::Error; use thiserror::Error;
use crate::bindgen; use crate::bindgen;
@ -18,7 +21,10 @@ pub enum Error {
BpfToolExit { code: i32, stderr: String }, BpfToolExit { code: i32, stderr: String },
#[error("bindgen failed")] #[error("bindgen failed")]
Bindgen, Bindgen(#[source] io::Error),
#[error("{stderr}\nbindgen failed with exit code {code}")]
BindgenExit { code: i32, stderr: String },
#[error("rustfmt failed")] #[error("rustfmt failed")]
Rustfmt(#[source] io::Error), Rustfmt(#[source] io::Error),
@ -35,25 +41,49 @@ pub enum InputFile {
pub fn generate<T: AsRef<str>>(input_file: InputFile, types: &[T]) -> Result<String, Error> { pub fn generate<T: AsRef<str>>(input_file: InputFile, types: &[T]) -> Result<String, Error> {
let mut bindgen = bindgen::bpf_builder(); let mut bindgen = bindgen::bpf_builder();
match input_file { let (c_header, name) = match input_file {
InputFile::Btf(path) => { InputFile::Btf(path) => (c_header_from_btf(&path)?, "kernel_types.h".to_string()),
let c_header = c_header_from_btf(&path)?; InputFile::Header(header) => (
bindgen = bindgen.header_contents("kernel_types.h", &c_header); fs::read_to_string(&header).map_err(|_| Error::ReadHeaderFile)?,
} header.file_name().unwrap().to_str().unwrap().to_owned(),
InputFile::Header(header) => { ),
let c_header = fs::read_to_string(&header).map_err(|_| Error::ReadHeaderFile)?; };
let name = Path::new(&header).file_name().unwrap().to_str().unwrap();
bindgen = bindgen.header_contents(name, &c_header);
}
}
for ty in types { for ty in types {
bindgen = bindgen.allowlist_type(ty); bindgen = bindgen.allowlist_type(ty);
} }
let bindings = bindgen.generate().or(Err(Error::Bindgen))?.to_string(); // TODO: check if this part should be moved to bindgen::generate()
let dir = tempdir().unwrap();
let file_path = dir.path().join(name);
let mut file = File::create(&file_path).unwrap();
let _ = file.write(c_header.as_bytes()).unwrap();
let flags = bindgen.command_line_flags();
// TODO: check proper logging; it seems useful to see what command is
// launched but we can't disturb the normal output of the aya-gen tool
println!(
"Launching bindgen {} {}",
file_path.to_str().unwrap(),
flags.join(" ")
);
let output = Command::new("bindgen")
.arg(file_path)
.args(flags)
// TODO: pass additional arguments after --
.output()
.map_err(Error::Bindgen)?;
if !output.status.success() {
return Err(Error::BindgenExit {
code: output.status.code().unwrap(),
stderr: from_utf8(&output.stderr).unwrap().to_owned(),
});
}
Ok(bindings) Ok(from_utf8(&output.stdout).unwrap().to_owned())
} }
fn c_header_from_btf(path: &Path) -> Result<String, Error> { fn c_header_from_btf(path: &Path) -> Result<String, Error> {

Loading…
Cancel
Save