Skip to content

Commit

Permalink
libbpf-cargo: Simplify build_btf_mmap() test helper
Browse files Browse the repository at this point in the history
The build_btf_mmap() function is almost comically complex in what it
does. In order to compile a single .bpf.c file it creates an entire
Cargo Rust project and builds that, instead of simply compiling the file
directly. Now that we have the BpfObjBuilder type, we can just about
accomplish the latter without jumping through dozens of hoops. Do it. As
a pleasant side effect of this reduction in complexity, the btf_dump
test runtime more than halves:

Before:
  $ time target/debug/deps/libbpf_cargo-37cf1fde780326f7 btf_dump
  > running 34 tests
  > [...]
  > ________________________________________________________
  > Executed in    2.09 secs    fish           external

After:
  $ time target/debug/deps/libbpf_cargo-37cf1fde780326f7 btf_dump
  > running 34 tests
  > [...]
  > ________________________________________________________
  > Executed in  810.13 millis    fish           external

Not the motivating factor at this point, but we take it.

Signed-off-by: Daniel Müller <deso@posteo.net>
  • Loading branch information
d-e-s-o committed Jan 21, 2025
1 parent 3b30d20 commit 239a0cc
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 18 deletions.
2 changes: 1 addition & 1 deletion libbpf-cargo/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl BpfObjBuilder {
/// Build a BPF object file.
pub fn build(&mut self, src: &Path, dst: &Path) -> Result<CompilationOutput> {
self.build_many([src], dst).map(|vec| {
// SANITY: We pass in a single file we `build_many` is
// SANITY: We pass in a single file and `build_many` is
// guaranteed to produce as many outputs as input
// files; so there must be one.
vec.into_iter().next().unwrap()
Expand Down
37 changes: 20 additions & 17 deletions libbpf-cargo/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use tempfile::TempDir;
use test_log::test;

use crate::build::build_project;
use crate::build::BpfObjBuilder;
use crate::gen::GenBtf;
use crate::gen::GenStructOps;
use crate::make::make;
Expand Down Expand Up @@ -122,19 +123,23 @@ fn get_libbpf_rs_path() -> PathBuf {
.expect("failed to canonicalize libbpf-rs")
}

/// Add vmlinux header into `project`'s src/bpf dir
fn add_vmlinux_header(project: &Path) {
fn write_vmlinux_header(dir: &Path) {
let mut vmlinux = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(project.join("src/bpf/vmlinux.h"))
.open(dir.join("vmlinux.h"))
.expect("failed to open vmlinux.h");
let () = vmlinux
.write_all(vmlinux::VMLINUX)
.expect("failed to write vmlinux.h");
}

/// Add vmlinux header into `project`'s src/bpf dir
fn add_vmlinux_header(project: &Path) {
write_vmlinux_header(&project.join("src/bpf"))
}

#[test]
fn test_build_default() {
let (_dir, proj_dir, cargo_toml) = setup_temp_project();
Expand Down Expand Up @@ -1174,30 +1179,28 @@ macro_rules! find_type_in_btf {
/// returns struct Btf if able to compile
/// fails calling test if unable to compile
fn build_btf_mmap(prog_text: &str) -> Mmap {
let (_dir, proj_dir, cargo_toml) = setup_temp_project();

// Add prog dir
create_dir(proj_dir.join("src/bpf")).expect("failed to create prog dir");

// Add a prog
let mut prog = OpenOptions::new()
let dir = tempdir().expect("failed to create tempdir");
let dir = dir.path();
let bpf_c = dir.join("prog.bpf.c");
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(proj_dir.join("src/bpf/prog.bpf.c"))
.open(&bpf_c)
.expect("failed to open prog.bpf.c");

write!(prog, "{prog_text}").expect("failed to write prog.bpf.c");

let () = file
.write_all(prog_text.as_bytes())
.expect("failed to write prog.bpf.c");
// Lay down the necessary header files
add_vmlinux_header(&proj_dir);
let () = write_vmlinux_header(dir);

// Build the .bpf.o
build_project(Some(&cargo_toml), None, Vec::new()).expect("failed to compile");
let bpf_o = dir.join("prog.bpf.o");
let _output = BpfObjBuilder::default().build(&bpf_c, &bpf_o).unwrap();

let obj = OpenOptions::new()
.read(true)
.open(proj_dir.as_path().join("target/bpf/prog.bpf.o").as_path())
.open(bpf_o)
.expect("failed to open object file");
unsafe { Mmap::map(&obj) }.expect("Failed to mmap object file")
}
Expand Down

0 comments on commit 239a0cc

Please sign in to comment.