mirror of https://github.com/aya-rs/aya
test: Add compile_c_ebpf to library
This allows for C code to be compiled and used in tests! It does require libbpf on the host machine though... Also moved removal of the `user` and `ebpf` dirs created by rust-script into `lib.sh` and parameterized bits of the XDP smoke test for ease of copying Signed-off-by: Dave Tucker <dave@dtucker.co.uk>pull/182/head
parent
f41db116ac
commit
657fb44525
@ -0,0 +1,85 @@
|
||||
//! ```cargo
|
||||
//! [dependencies]
|
||||
//! libbpf-sys = { version = "0.6.1-1" }
|
||||
//! anyhow = "1"
|
||||
//! ```
|
||||
|
||||
use std::{
|
||||
env,
|
||||
fs::{self, OpenOptions},
|
||||
io::Write,
|
||||
path::Path,
|
||||
process::Command,
|
||||
string::String,
|
||||
};
|
||||
use anyhow::{bail, Context, Result};
|
||||
static CLANG_DEFAULT: &str = "/usr/bin/clang";
|
||||
|
||||
/// Extract vendored libbpf headers from libbpf-sys.
|
||||
fn extract_libbpf_headers<P: AsRef<Path>>(include_path: P) -> Result<()> {
|
||||
let dir = include_path.as_ref().join("bpf");
|
||||
fs::create_dir_all(&dir)?;
|
||||
for (filename, contents) in libbpf_sys::API_HEADERS.iter() {
|
||||
let path = dir.as_path().join(filename);
|
||||
let mut file = OpenOptions::new().write(true).create(true).open(path)?;
|
||||
file.write_all(contents.as_bytes())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Build eBPF programs with clang and libbpf headers.
|
||||
fn build_ebpf<P: Clone + AsRef<Path>>(in_file: P, out_file: P, include_path: P) -> Result<()> {
|
||||
extract_libbpf_headers(include_path.clone())?;
|
||||
let clang = match env::var("CLANG") {
|
||||
Ok(val) => val,
|
||||
Err(_) => String::from(CLANG_DEFAULT),
|
||||
};
|
||||
let arch = match std::env::consts::ARCH {
|
||||
"x86_64" => "x86",
|
||||
"aarch64" => "arm64",
|
||||
_ => std::env::consts::ARCH,
|
||||
};
|
||||
let mut cmd = Command::new(clang);
|
||||
cmd.arg(format!("-I{}", include_path.as_ref().to_string_lossy()))
|
||||
.arg("-g")
|
||||
.arg("-O2")
|
||||
.arg("-target")
|
||||
.arg("bpf")
|
||||
.arg("-c")
|
||||
.arg(format!("-D__TARGET_ARCH_{}", arch))
|
||||
.arg(in_file.as_ref().as_os_str())
|
||||
.arg("-o")
|
||||
.arg(out_file.as_ref().as_os_str());
|
||||
|
||||
let output = cmd.output().context("Failed to execute clang")?;
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"Failed to compile eBPF programs\n \
|
||||
stdout=\n \
|
||||
{}\n \
|
||||
stderr=\n \
|
||||
{}\n",
|
||||
String::from_utf8(output.stdout).unwrap(),
|
||||
String::from_utf8(output.stderr).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 3 {
|
||||
bail!("requires 2 arguments. src and dst")
|
||||
}
|
||||
let path = env::current_dir()?;
|
||||
let src = Path::new(&args[1]);
|
||||
let dst = Path::new(&args[2]);
|
||||
|
||||
let include_path = path.join("include");
|
||||
fs::create_dir_all(include_path.clone())?;
|
||||
build_ebpf(src, dst, &include_path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue