From 8c61fc9ea6d1d52b38a238541fb229bc850c82ac Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 10 Jul 2023 14:59:09 -0400 Subject: [PATCH] integration-test: compile C probes using build.rs - Add libbpf as a submodule. This prevents having to plumb its location around (which can't be passed to Cargo build scripts) and also controls the version against which codegen has run. - Move bpf written in C to the integration-test crate and define constants for each probe. - Remove magic; each C source file must be directly enumerated in the build script and in lib.rs. --- .github/workflows/gen.yml | 7 +- .github/workflows/integration-tests.yml | 6 +- .gitignore | 1 - .gitmodules | 3 + aya/src/util.rs | 2 +- libbpf | 1 + test/README.md | 10 +-- .../src => integration-test}/bpf/ext.bpf.c | 0 .../src => integration-test}/bpf/main.bpf.c | 0 .../bpf/multimap-btf.bpf.c | 0 .../bpf/text_64_64_reloc.c | 0 test/integration-test/build.rs | 88 +++++++++++++++++++ test/integration-test/src/lib.rs | 7 ++ test/integration-test/tests/load.rs | 4 +- test/integration-test/tests/rbpf.rs | 4 +- test/integration-test/tests/relocations.rs | 5 +- test/integration-test/tests/smoke.rs | 10 +-- test/run.sh | 17 ++-- xtask/src/build_ebpf.rs | 86 +----------------- xtask/src/codegen/aya.rs | 44 +++++----- xtask/src/codegen/aya_bpf_bindings.rs | 29 +++--- xtask/src/codegen/mod.rs | 32 ++++--- xtask/src/run.rs | 10 +-- 23 files changed, 184 insertions(+), 182 deletions(-) create mode 100644 .gitmodules create mode 160000 libbpf rename test/{integration-ebpf/src => integration-test}/bpf/ext.bpf.c (100%) rename test/{integration-ebpf/src => integration-test}/bpf/main.bpf.c (100%) rename test/{integration-ebpf/src => integration-test}/bpf/multimap-btf.bpf.c (100%) rename test/{integration-ebpf/src => integration-test}/bpf/text_64_64_reloc.c (100%) create mode 100644 test/integration-test/build.rs diff --git a/.github/workflows/gen.yml b/.github/workflows/gen.yml index cf5939df..ac271be7 100644 --- a/.github/workflows/gen.yml +++ b/.github/workflows/gen.yml @@ -9,11 +9,6 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/checkout@v3 - with: - repository: libbpf/libbpf - path: libbpf - - name: libbpf-version working-directory: libbpf run: echo "LIBBPF_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV @@ -32,7 +27,7 @@ jobs: - name: Run codegen run: | - cargo xtask codegen --libbpf-dir ./libbpf + cargo xtask codegen - name: Check for changes run: | diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e3e21f81..11674142 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -17,11 +17,9 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v3 - uses: actions/checkout@v3 with: - repository: libbpf/libbpf - path: libbpf + submodules: recursive - name: Install Pre-requisites run: | @@ -40,4 +38,4 @@ jobs: key: tmp-files-${{ hashFiles('test/run.sh') }} - name: Run integration tests - run: test/run.sh ./libbpf + run: test/run.sh diff --git a/.gitignore b/.gitignore index 0248fbf2..38ed638e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ Cargo.lock target/ -libbpf/ .vscode/ !.vscode/settings.json site/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e606d2b6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libbpf"] + path = libbpf + url = https://github.com/libbpf/libbpf diff --git a/aya/src/util.rs b/aya/src/util.rs index aaca0f5f..fb1026af 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -299,7 +299,7 @@ macro_rules! include_bytes_aligned { pub bytes: Bytes, } - static ALIGNED: &Aligned<[u8]> = &Aligned { + const ALIGNED: &Aligned<[u8]> = &Aligned { _align: [], bytes: *include_bytes!($path), }; diff --git a/libbpf b/libbpf new file mode 160000 index 00000000..a2258003 --- /dev/null +++ b/libbpf @@ -0,0 +1 @@ +Subproject commit a2258003f21d9d52afd48aa64787b65ef80bd355 diff --git a/test/README.md b/test/README.md index 09a7c49d..58a94113 100644 --- a/test/README.md +++ b/test/README.md @@ -30,13 +30,13 @@ From the root of this repository: ### Native ``` -cargo xtask integration-test --libbpf-dir /path/to/libbpf +cargo xtask integration-test ``` ### Virtualized ``` -./test/run.sh /path/to/libbpf +./test/run.sh ``` ### Writing an integration test @@ -45,9 +45,9 @@ Tests should follow these guidelines: - Rust eBPF code should live in `integration-ebpf/${NAME}.rs` and included in `integration-ebpf/Cargo.toml`. -- C eBPF code should live in `integration-ebpf/src/bpf/${NAME}.bpf.c`. It's automatically compiled - and made available as `${OUT_DIR}/${NAME}.bpf.o`. -- Any bytecode should be included in the integration test binary using `include_bytes_aligned!`. +- C eBPF code should live in `integration-test/bpf/${NAME}.bpf.c`. It should be + added to the list of files in `integration-test/build.rs` and the list of + constants in `integration-test/src/lib.rs` using `include_bytes_aligned!`. - Tests should be added to `integration-test/tests`. - You may add a new module, or use an existing one. - Test functions should not return `anyhow::Result<()>` since this produces errors without stack diff --git a/test/integration-ebpf/src/bpf/ext.bpf.c b/test/integration-test/bpf/ext.bpf.c similarity index 100% rename from test/integration-ebpf/src/bpf/ext.bpf.c rename to test/integration-test/bpf/ext.bpf.c diff --git a/test/integration-ebpf/src/bpf/main.bpf.c b/test/integration-test/bpf/main.bpf.c similarity index 100% rename from test/integration-ebpf/src/bpf/main.bpf.c rename to test/integration-test/bpf/main.bpf.c diff --git a/test/integration-ebpf/src/bpf/multimap-btf.bpf.c b/test/integration-test/bpf/multimap-btf.bpf.c similarity index 100% rename from test/integration-ebpf/src/bpf/multimap-btf.bpf.c rename to test/integration-test/bpf/multimap-btf.bpf.c diff --git a/test/integration-ebpf/src/bpf/text_64_64_reloc.c b/test/integration-test/bpf/text_64_64_reloc.c similarity index 100% rename from test/integration-ebpf/src/bpf/text_64_64_reloc.c rename to test/integration-test/bpf/text_64_64_reloc.c diff --git a/test/integration-test/build.rs b/test/integration-test/build.rs new file mode 100644 index 00000000..872f3106 --- /dev/null +++ b/test/integration-test/build.rs @@ -0,0 +1,88 @@ +use std::{env, ffi::OsString, path::PathBuf, process::Command}; + +fn main() { + let manifest_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); + let manifest_dir = PathBuf::from(manifest_dir); + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = PathBuf::from(out_dir); + + let libbpf_dir = manifest_dir + .parent() + .unwrap() + .parent() + .unwrap() + .join("libbpf"); + + let libbpf_headers_dir = out_dir.join("libbpf_headers"); + + let mut includedir = OsString::new(); + includedir.push("INCLUDEDIR="); + includedir.push(&libbpf_headers_dir); + + let mut cmd = Command::new("make"); + cmd.arg("-C") + .arg(libbpf_dir.join("src")) + .arg(includedir) + .arg("install_headers"); + let status = cmd + .status() + .unwrap_or_else(|err| panic!("failed to run {cmd:?}: {err}")); + match status.code() { + Some(code) => match code { + 0 => {} + code => panic!("{cmd:?} exited with code {code}"), + }, + None => panic!("{cmd:?} terminated by signal"), + } + + let bpf_dir = manifest_dir.join("bpf"); + + let endian = env::var_os("CARGO_CFG_TARGET_ENDIAN").unwrap(); + let target = if endian == "big" { + "bpfeb" + } else if endian == "little" { + "bpfel" + } else { + panic!("unsupported endian={:?}", endian) + }; + + let mut target_arch = OsString::new(); + target_arch.push("-D__TARGET_ARCH_"); + + let arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap(); + if arch == "x86_64" { + target_arch.push("x86"); + } else if arch == "aarch64" { + target_arch.push("arm64"); + } else { + target_arch.push(arch); + }; + + for (src, dst) in [ + ("ext.bpf.c", "ext.bpf.o"), + ("main.bpf.c", "main.bpf.o"), + ("multimap-btf.bpf.c", "multimap-btf.bpf.o"), + ("text_64_64_reloc.c", "text_64_64_reloc.o"), + ] { + let src = bpf_dir.join(src); + let out = out_dir.join(dst); + let mut cmd = Command::new("clang"); + cmd.arg("-I") + .arg(&libbpf_headers_dir) + .args(["-g", "-O2", "-target", target, "-c"]) + .arg(&target_arch) + .arg(src) + .arg("-o") + .arg(out); + let status = cmd + .status() + .unwrap_or_else(|err| panic!("failed to run {cmd:?}: {err}")); + match status.code() { + Some(code) => match code { + 0 => {} + code => panic!("{cmd:?} exited with code {code}"), + }, + None => panic!("{cmd:?} terminated by signal"), + } + } +} diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 8b137891..2ecb410b 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -1 +1,8 @@ +use aya::include_bytes_aligned; +pub const EXT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/ext.bpf.o")); +pub const MAIN: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/main.bpf.o")); +pub const MULTIMAP_BTF: &[u8] = + include_bytes_aligned!(concat!(env!("OUT_DIR"), "/multimap-btf.bpf.o")); +pub const TEXT_64_64_RELOC: &[u8] = + include_bytes_aligned!(concat!(env!("OUT_DIR"), "/text_64_64_reloc.o")); diff --git a/test/integration-test/tests/load.rs b/test/integration-test/tests/load.rs index 3f35e06e..2b1a85dd 100644 --- a/test/integration-test/tests/load.rs +++ b/test/integration-test/tests/load.rs @@ -33,9 +33,7 @@ fn long_name() { #[test] fn multiple_btf_maps() { - let bytes = - include_bytes_aligned!("../../../target/bpfel-unknown-none/release/multimap-btf.bpf.o"); - let mut bpf = Bpf::load(bytes).unwrap(); + let mut bpf = Bpf::load(integration_test::MULTIMAP_BTF).unwrap(); let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); diff --git a/test/integration-test/tests/rbpf.rs b/test/integration-test/tests/rbpf.rs index cfeb1334..f4ef56e1 100644 --- a/test/integration-test/tests/rbpf.rs +++ b/test/integration-test/tests/rbpf.rs @@ -34,9 +34,7 @@ static mut MULTIMAP_MAPS: [*mut Vec; 2] = [null_mut(), null_mut()]; #[test] fn use_map_with_rbpf() { - let bytes = - include_bytes_aligned!("../../../target/bpfel-unknown-none/release/multimap-btf.bpf.o"); - let mut object = Object::parse(bytes).unwrap(); + let mut object = Object::parse(integration_test::MULTIMAP_BTF).unwrap(); assert_eq!(object.programs.len(), 1); matches::assert_matches!( diff --git a/test/integration-test/tests/relocations.rs b/test/integration-test/tests/relocations.rs index 702494c3..fc46ef5f 100644 --- a/test/integration-test/tests/relocations.rs +++ b/test/integration-test/tests/relocations.rs @@ -20,10 +20,7 @@ fn relocations() { #[test] fn text_64_64_reloc() { - let mut bpf = load_and_attach( - "test_text_64_64_reloc", - include_bytes_aligned!("../../../target/bpfel-unknown-none/release/text_64_64_reloc.o"), - ); + let mut bpf = load_and_attach("test_text_64_64_reloc", integration_test::TEXT_64_64_RELOC); let mut m = aya::maps::Array::<_, u64>::try_from(bpf.map_mut("RESULTS").unwrap()).unwrap(); m.set(0, 1, 0).unwrap(); diff --git a/test/integration-test/tests/smoke.rs b/test/integration-test/tests/smoke.rs index 304772e8..746821e5 100644 --- a/test/integration-test/tests/smoke.rs +++ b/test/integration-test/tests/smoke.rs @@ -27,15 +27,15 @@ fn extension() { eprintln!("skipping test on kernel {kernel_version:?}, XDP uses netlink"); return; } - let main_bytes = - include_bytes_aligned!("../../../target/bpfel-unknown-none/release/main.bpf.o"); - let mut bpf = Bpf::load(main_bytes).unwrap(); + let mut bpf = Bpf::load(integration_test::MAIN).unwrap(); let pass: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); pass.load().unwrap(); pass.attach("lo", XdpFlags::default()).unwrap(); - let ext_bytes = include_bytes_aligned!("../../../target/bpfel-unknown-none/release/ext.bpf.o"); - let mut bpf = BpfLoader::new().extension("drop").load(ext_bytes).unwrap(); + let mut bpf = BpfLoader::new() + .extension("drop") + .load(integration_test::EXT) + .unwrap(); let drop_: &mut Extension = bpf.program_mut("drop").unwrap().try_into().unwrap(); drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap(); } diff --git a/test/run.sh b/test/run.sh index dd2461c7..33e2b6e0 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,7 +7,6 @@ if [ "$(uname -s)" = "Darwin" ]; then fi AYA_SOURCE_DIR="$(realpath $(dirname $0)/..)" -LIBBPF_DIR=$1 # Temporary directory for tests to use. AYA_TMPDIR="${AYA_SOURCE_DIR}/.tmp" @@ -236,25 +235,19 @@ cleanup_vm() { fi } -if [ -z "$LIBBPF_DIR" ]; then - echo "path to libbpf required" - exit 1 -fi - start_vm trap cleanup_vm EXIT -# make sure we always use fresh aya and libbpf (also see comment at the end) -exec_vm "rm -rf aya/* libbpf" +# make sure we always use fresh sources (also see comment at the end) +exec_vm "rm -rf aya/*" rsync_vm "--exclude=target --exclude=.tmp $AYA_SOURCE_DIR" -rsync_vm "$LIBBPF_DIR" # need to build or linting will fail trying to include object files; don't run the tests though. -exec_vm "cd aya; cargo xtask integration-test --libbpf-dir ~/libbpf -- filter-that-matches-nothing" +exec_vm "cd aya; cargo xtask integration-test -- filter-that-matches-nothing" exec_vm "cd aya; cargo clippy --all-targets -p integration-test -- --deny warnings" -exec_vm "cd aya; cargo xtask integration-test --libbpf-dir ~/libbpf" +exec_vm "cd aya; cargo xtask integration-test" # we rm and sync but it doesn't seem to work reliably - I guess we could sleep a # few seconds after but ain't nobody got time for that. Instead we also rm # before rsyncing. -exec_vm "rm -rf aya/* libbpf; sync" +exec_vm "rm -rf aya/*; sync" diff --git a/xtask/src/build_ebpf.rs b/xtask/src/build_ebpf.rs index bdbf44ed..5c974921 100644 --- a/xtask/src/build_ebpf.rs +++ b/xtask/src/build_ebpf.rs @@ -1,11 +1,4 @@ -use std::{ - borrow::Cow, - env, - ffi::{OsStr, OsString}, - fs, - path::{Path, PathBuf}, - process::Command, -}; +use std::{path::PathBuf, process::Command}; use anyhow::Result; use clap::Parser; @@ -44,21 +37,10 @@ pub struct BuildEbpfOptions { /// Set the endianness of the BPF target #[clap(default_value = "bpfel-unknown-none", long)] pub target: Architecture, - /// Libbpf dir, required for compiling C code - #[clap(long, action)] - pub libbpf_dir: PathBuf, } pub fn build_ebpf(opts: BuildEbpfOptions) -> Result<()> { - build_rust_ebpf(&opts)?; - build_c_ebpf(&opts) -} - -fn build_rust_ebpf(opts: &BuildEbpfOptions) -> Result<()> { - let BuildEbpfOptions { - target, - libbpf_dir: _, - } = opts; + let BuildEbpfOptions { target } = opts; let mut dir = PathBuf::from(workspace_root()); dir.push("test/integration-ebpf"); @@ -72,67 +54,3 @@ fn build_rust_ebpf(opts: &BuildEbpfOptions) -> Result<()> { .current_dir(&dir), ) } - -fn get_libbpf_headers(libbpf_dir: &Path, include_path: &Path) -> Result<()> { - fs::create_dir_all(include_path)?; - let mut includedir = OsString::new(); - includedir.push("INCLUDEDIR="); - includedir.push(include_path); - exec( - Command::new("make") - .current_dir(libbpf_dir.join("src")) - .arg(includedir) - .arg("install_headers"), - ) -} - -fn build_c_ebpf(opts: &BuildEbpfOptions) -> Result<()> { - let BuildEbpfOptions { target, libbpf_dir } = opts; - - let mut src = PathBuf::from(workspace_root()); - src.push("test/integration-ebpf/src/bpf"); - - let mut out_path = PathBuf::from(workspace_root()); - out_path.push("target"); - out_path.push(target.to_string()); - out_path.push("release"); - - let include_path = out_path.join("include"); - get_libbpf_headers(libbpf_dir, &include_path)?; - let files = fs::read_dir(&src).unwrap(); - for file in files { - let p = file.unwrap().path(); - if let Some(ext) = p.extension() { - if ext == "c" { - let mut out = PathBuf::from(&out_path); - out.push(p.file_name().unwrap()); - out.set_extension("o"); - compile_with_clang(&p, &out, &include_path)?; - } - } - } - Ok(()) -} - -/// Build eBPF programs with clang and libbpf headers. -fn compile_with_clang(src: &Path, out: &Path, include_path: &Path) -> Result<()> { - let clang: Cow<'_, _> = match env::var_os("CLANG") { - Some(val) => val.into(), - None => OsStr::new("/usr/bin/clang").into(), - }; - let arch = match env::consts::ARCH { - "x86_64" => "x86", - "aarch64" => "arm64", - arch => arch, - }; - exec( - Command::new(clang) - .arg("-I") - .arg(include_path) - .args(["-g", "-O2", "-target", "bpf", "-c"]) - .arg(format!("-D__TARGET_ARCH_{arch}")) - .arg(src) - .arg("-o") - .arg(out), - ) -} diff --git a/xtask/src/codegen/aya.rs b/xtask/src/codegen/aya.rs index 6758eed4..c9f48b48 100644 --- a/xtask/src/codegen/aya.rs +++ b/xtask/src/codegen/aya.rs @@ -3,20 +3,22 @@ use std::path::PathBuf; use aya_tool::{bindgen, write_to_file}; -use crate::codegen::{Architecture, Options}; +use crate::codegen::{Architecture, SysrootOptions}; -pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> { - codegen_internal_btf_bindings(opts)?; +pub fn codegen(opts: &SysrootOptions) -> Result<(), anyhow::Error> { + codegen_internal_btf_bindings()?; codegen_bindings(opts) } -fn codegen_internal_btf_bindings(opts: &Options) -> Result<(), anyhow::Error> { +fn codegen_internal_btf_bindings() -> Result<(), anyhow::Error> { let dir = PathBuf::from("aya-obj"); let generated = dir.join("src/generated"); + let libbpf_dir = PathBuf::from("libbpf"); + let mut bindgen = bindgen::user_builder() .clang_arg(format!( "-I{}", - opts.libbpf_dir + libbpf_dir .join("include/uapi") .canonicalize() .unwrap() @@ -24,17 +26,13 @@ fn codegen_internal_btf_bindings(opts: &Options) -> Result<(), anyhow::Error> { )) .clang_arg(format!( "-I{}", - opts.libbpf_dir + libbpf_dir .join("include") .canonicalize() .unwrap() .to_string_lossy() )) - .header( - opts.libbpf_dir - .join("src/libbpf_internal.h") - .to_string_lossy(), - ) + .header(libbpf_dir.join("src/libbpf_internal.h").to_string_lossy()) .constified_enum_module("bpf_core_relo_kind"); let types = ["bpf_core_relo", "btf_ext_header"]; @@ -54,7 +52,13 @@ fn codegen_internal_btf_bindings(opts: &Options) -> Result<(), anyhow::Error> { Ok(()) } -fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> { +fn codegen_bindings(opts: &SysrootOptions) -> Result<(), anyhow::Error> { + let SysrootOptions { + x86_64_sysroot, + aarch64_sysroot, + armv7_sysroot, + riscv64_sysroot, + } = opts; let types = [ // BPF "BPF_TYPES", @@ -158,15 +162,13 @@ fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> { let dir = PathBuf::from("aya-obj"); let generated = dir.join("src/generated"); + let libbpf_dir = PathBuf::from("libbpf"); let builder = || { bindgen::user_builder() .header(dir.join("include/linux_wrapper.h").to_string_lossy()) - .clang_args(&[ - "-I", - &*opts.libbpf_dir.join("include/uapi").to_string_lossy(), - ]) - .clang_args(&["-I", &*opts.libbpf_dir.join("include").to_string_lossy()]) + .clang_args(&["-I", &*libbpf_dir.join("include/uapi").to_string_lossy()]) + .clang_args(&["-I", &*libbpf_dir.join("include").to_string_lossy()]) }; for arch in Architecture::supported() { @@ -185,10 +187,10 @@ fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> { // Set the sysroot. This is needed to ensure that the correct arch // specific headers are imported. let sysroot = match arch { - Architecture::X86_64 => &opts.x86_64_sysroot, - Architecture::ARMv7 => &opts.armv7_sysroot, - Architecture::AArch64 => &opts.aarch64_sysroot, - Architecture::RISCV64 => &opts.riscv64_sysroot, + Architecture::X86_64 => x86_64_sysroot, + Architecture::ARMv7 => armv7_sysroot, + Architecture::AArch64 => aarch64_sysroot, + Architecture::RISCV64 => riscv64_sysroot, }; bindgen = bindgen.clang_args(&["-I", &*sysroot.to_string_lossy()]); diff --git a/xtask/src/codegen/aya_bpf_bindings.rs b/xtask/src/codegen/aya_bpf_bindings.rs index 1bfcbc5b..d0af3221 100644 --- a/xtask/src/codegen/aya_bpf_bindings.rs +++ b/xtask/src/codegen/aya_bpf_bindings.rs @@ -8,11 +8,19 @@ use syn::{parse_str, Item}; use crate::codegen::{ helpers::{expand_helpers, extract_helpers}, - Architecture, Options, + Architecture, SysrootOptions, }; -pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> { +pub fn codegen(opts: &SysrootOptions) -> Result<(), anyhow::Error> { + let SysrootOptions { + x86_64_sysroot, + aarch64_sysroot, + armv7_sysroot, + riscv64_sysroot, + } = opts; + let dir = PathBuf::from("bpf/aya-bpf-bindings"); + let libbpf_dir = PathBuf::from("libbpf"); let builder = || { let mut bindgen = bindgen::bpf_builder() @@ -20,12 +28,9 @@ pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> { // aya-tool uses aya_bpf::cty. We can't use that here since aya-bpf // depends on aya-bpf-bindings so it would create a circular dep. .ctypes_prefix("::aya_bpf_cty") - .clang_args(&[ - "-I", - &*opts.libbpf_dir.join("include/uapi").to_string_lossy(), - ]) - .clang_args(&["-I", &*opts.libbpf_dir.join("include").to_string_lossy()]) - .clang_args(&["-I", &*opts.libbpf_dir.join("src").to_string_lossy()]) + .clang_args(&["-I", &*libbpf_dir.join("include/uapi").to_string_lossy()]) + .clang_args(&["-I", &*libbpf_dir.join("include").to_string_lossy()]) + .clang_args(&["-I", &*libbpf_dir.join("src").to_string_lossy()]) // open aya-bpf-bindings/.../bindings.rs and look for mod // _bindgen, those are anonymous enums .constified_enum("BPF_F_.*") @@ -82,10 +87,10 @@ pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> { // Set the sysroot. This is needed to ensure that the correct arch // specific headers are imported. let sysroot = match arch { - Architecture::X86_64 => &opts.x86_64_sysroot, - Architecture::ARMv7 => &opts.armv7_sysroot, - Architecture::AArch64 => &opts.aarch64_sysroot, - Architecture::RISCV64 => &opts.riscv64_sysroot, + Architecture::X86_64 => x86_64_sysroot, + Architecture::ARMv7 => armv7_sysroot, + Architecture::AArch64 => aarch64_sysroot, + Architecture::RISCV64 => riscv64_sysroot, }; bindgen = bindgen.clang_args(&["-I", &*sysroot.to_string_lossy()]); diff --git a/xtask/src/codegen/mod.rs b/xtask/src/codegen/mod.rs index e2321142..6722c660 100644 --- a/xtask/src/codegen/mod.rs +++ b/xtask/src/codegen/mod.rs @@ -52,13 +52,10 @@ impl std::fmt::Display for Architecture { } } +// sysroot options. Default to ubuntu headers installed by the +// libc6-dev-{arm64,armel}-cross packages. #[derive(Parser)] -pub struct Options { - #[arg(long, action)] - libbpf_dir: PathBuf, - - // sysroot options. Default to ubuntu headers installed by the - // libc6-dev-{arm64,armel}-cross packages. +pub struct SysrootOptions { #[arg(long, default_value = "/usr/include/x86_64-linux-gnu", action)] x86_64_sysroot: PathBuf, @@ -70,6 +67,12 @@ pub struct Options { #[arg(long, default_value = "/usr/riscv64-linux-gnu/include", action)] riscv64_sysroot: PathBuf, +} + +#[derive(Parser)] +pub struct Options { + #[command(flatten)] + sysroot_options: SysrootOptions, #[command(subcommand)] command: Option, @@ -84,13 +87,18 @@ enum Command { } pub fn codegen(opts: Options) -> Result<(), anyhow::Error> { - use Command::*; - match opts.command { - Some(Aya) => aya::codegen(&opts), - Some(AyaBpfBindings) => aya_bpf_bindings::codegen(&opts), + let Options { + sysroot_options, + command, + } = opts; + match command { + Some(command) => match command { + Command::Aya => aya::codegen(&sysroot_options), + Command::AyaBpfBindings => aya_bpf_bindings::codegen(&sysroot_options), + }, None => { - aya::codegen(&opts)?; - aya_bpf_bindings::codegen(&opts) + aya::codegen(&sysroot_options)?; + aya_bpf_bindings::codegen(&sysroot_options) } } } diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 0c7a241d..7e3d4c22 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -22,9 +22,6 @@ pub struct Options { /// The command used to wrap your application #[clap(short, long, default_value = "sudo -E")] pub runner: String, - /// libbpf directory - #[clap(long, action)] - pub libbpf_dir: PathBuf, /// Arguments to pass to your application #[clap(name = "args", last = true)] pub run_args: Vec, @@ -90,16 +87,11 @@ pub fn run(opts: Options) -> Result<()> { bpf_target, release, runner, - libbpf_dir, run_args, } = opts; // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: bpf_target, - libbpf_dir, - }) - .context("error while building eBPF program")?; + build_ebpf(BuildOptions { target: bpf_target }).context("error while building eBPF program")?; let binaries = build(release).context("error while building userspace application")?; let mut args = runner.trim().split_terminator(' ');