12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- //! ```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(())
- }
|