xtask: ensure libbpf submodule is initialized

Libbpf is used by xtasks, in the command, ensure that the submodules
are initialized. This eases the user-experience so that users don't
need to think about the submodule, while retaining all the benefits
of using a submodule vs forcing the user to manually check out libbpf
and stick it in some pre-defined place.

We use the symbol pointing to libbpf in xtask in the build script
to avoid repeating this constant.

Also, we install git in the vm so that we can init the submodule
when we build in the vm.
pull/664/head
Andrew Werner 1 year ago
parent 4306b222d8
commit 15b3c459ae

@ -26,3 +26,4 @@ tokio = { version = "1.24", default-features = false, features = [
[build-dependencies] [build-dependencies]
cargo_metadata = { version = "0.15.4", default-features = false } cargo_metadata = { version = "0.15.4", default-features = false }
which = { version = "4.4.0", default-features = false } which = { version = "4.4.0", default-features = false }
xtask = { path = "../../xtask" }

@ -13,6 +13,7 @@ use cargo_metadata::{
Artifact, CompilerMessage, Dependency, Message, Metadata, MetadataCommand, Package, Target, Artifact, CompilerMessage, Dependency, Message, Metadata, MetadataCommand, Package, Target,
}; };
use which::which; use which::which;
use xtask::{exec, LIBBPF_DIR};
fn main() { fn main() {
const AYA_BUILD_INTEGRATION_BPF: &str = "AYA_BUILD_INTEGRATION_BPF"; const AYA_BUILD_INTEGRATION_BPF: &str = "AYA_BUILD_INTEGRATION_BPF";
@ -69,7 +70,8 @@ fn main() {
.unwrap() .unwrap()
.parent() .parent()
.unwrap() .unwrap()
.join("libbpf"); .join(LIBBPF_DIR);
println!("cargo:rerun-if-changed={}", libbpf_dir.to_str().unwrap());
let libbpf_headers_dir = out_dir.join("libbpf_headers"); let libbpf_headers_dir = out_dir.join("libbpf_headers");
@ -77,21 +79,14 @@ fn main() {
includedir.push("INCLUDEDIR="); includedir.push("INCLUDEDIR=");
includedir.push(&libbpf_headers_dir); includedir.push(&libbpf_headers_dir);
let mut cmd = Command::new("make"); exec(
cmd.arg("-C") Command::new("make")
.arg(libbpf_dir.join("src")) .arg("-C")
.arg(includedir) .arg(libbpf_dir.join("src"))
.arg("install_headers"); .arg(includedir)
let status = cmd .arg("install_headers"),
.status() )
.unwrap_or_else(|err| panic!("failed to run {cmd:?}: {err}")); .unwrap();
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 bpf_dir = manifest_dir.join("bpf");
@ -110,24 +105,18 @@ fn main() {
for (src, dst) in c_bpf_probes { for (src, dst) in c_bpf_probes {
let src = bpf_dir.join(src); let src = bpf_dir.join(src);
println!("cargo:rerun-if-changed={}", src.to_str().unwrap()); println!("cargo:rerun-if-changed={}", src.to_str().unwrap());
let mut cmd = Command::new("clang");
cmd.arg("-I") exec(
.arg(&libbpf_headers_dir) Command::new("clang")
.args(["-g", "-O2", "-target", target, "-c"]) .arg("-I")
.arg(&target_arch) .arg(&libbpf_headers_dir)
.arg(src) .args(["-g", "-O2", "-target", target, "-c"])
.arg("-o") .arg(&target_arch)
.arg(dst); .arg(src)
let status = cmd .arg("-o")
.status() .arg(dst),
.unwrap_or_else(|err| panic!("failed to run {cmd:?}: {err}")); )
match status.code() { .unwrap();
Some(code) => match code {
0 => {}
code => panic!("{cmd:?} exited with code {code}"),
},
None => panic!("{cmd:?} terminated by signal"),
}
} }
let target = format!("{target}-unknown-none"); let target = format!("{target}-unknown-none");

@ -192,7 +192,7 @@ EOF
exec_vm sudo dnf config-manager --set-enabled updates-testing exec_vm sudo dnf config-manager --set-enabled updates-testing
exec_vm sudo dnf config-manager --set-enabled updates-testing-modular exec_vm sudo dnf config-manager --set-enabled updates-testing-modular
echo "Installing dependencies" echo "Installing dependencies"
exec_vm sudo dnf install -qy bpftool llvm llvm-devel clang clang-devel zlib-devel exec_vm sudo dnf install -qy bpftool llvm llvm-devel clang clang-devel zlib-devel git
exec_vm 'curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ exec_vm 'curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
-y --profile minimal --default-toolchain nightly --component rust-src --component clippy' -y --profile minimal --default-toolchain nightly --component rust-src --component clippy'
exec_vm 'echo source ~/.cargo/env >> ~/.bashrc' exec_vm 'echo source ~/.cargo/env >> ~/.bashrc'

@ -1,19 +1,18 @@
use anyhow::anyhow; use anyhow::anyhow;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use aya_tool::{bindgen, write_to_file}; use aya_tool::{bindgen, write_to_file};
use crate::codegen::{Architecture, SysrootOptions}; use crate::codegen::{Architecture, SysrootOptions};
pub fn codegen(opts: &SysrootOptions) -> Result<(), anyhow::Error> { pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::Error> {
codegen_internal_btf_bindings()?; codegen_internal_btf_bindings(libbpf_dir)?;
codegen_bindings(opts) codegen_bindings(opts, libbpf_dir)
} }
fn codegen_internal_btf_bindings() -> Result<(), anyhow::Error> { fn codegen_internal_btf_bindings(libbpf_dir: &Path) -> Result<(), anyhow::Error> {
let dir = PathBuf::from("aya-obj"); let dir = PathBuf::from("aya-obj");
let generated = dir.join("src/generated"); let generated = dir.join("src/generated");
let libbpf_dir = PathBuf::from("libbpf");
let mut bindgen = bindgen::user_builder() let mut bindgen = bindgen::user_builder()
.clang_arg(format!( .clang_arg(format!(
@ -52,7 +51,7 @@ fn codegen_internal_btf_bindings() -> Result<(), anyhow::Error> {
Ok(()) Ok(())
} }
fn codegen_bindings(opts: &SysrootOptions) -> Result<(), anyhow::Error> { fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::Error> {
let SysrootOptions { let SysrootOptions {
x86_64_sysroot, x86_64_sysroot,
aarch64_sysroot, aarch64_sysroot,
@ -162,7 +161,6 @@ fn codegen_bindings(opts: &SysrootOptions) -> Result<(), anyhow::Error> {
let dir = PathBuf::from("aya-obj"); let dir = PathBuf::from("aya-obj");
let generated = dir.join("src/generated"); let generated = dir.join("src/generated");
let libbpf_dir = PathBuf::from("libbpf");
let builder = || { let builder = || {
bindgen::user_builder() bindgen::user_builder()

@ -1,7 +1,7 @@
use anyhow::anyhow; use anyhow::anyhow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::ToTokens; use quote::ToTokens;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use aya_tool::{bindgen, write_to_file_fmt}; use aya_tool::{bindgen, write_to_file_fmt};
use syn::{parse_str, Item}; use syn::{parse_str, Item};
@ -11,7 +11,7 @@ use crate::codegen::{
Architecture, SysrootOptions, Architecture, SysrootOptions,
}; };
pub fn codegen(opts: &SysrootOptions) -> Result<(), anyhow::Error> { pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::Error> {
let SysrootOptions { let SysrootOptions {
x86_64_sysroot, x86_64_sysroot,
aarch64_sysroot, aarch64_sysroot,
@ -20,7 +20,6 @@ pub fn codegen(opts: &SysrootOptions) -> Result<(), anyhow::Error> {
} = opts; } = opts;
let dir = PathBuf::from("bpf/aya-bpf-bindings"); let dir = PathBuf::from("bpf/aya-bpf-bindings");
let libbpf_dir = PathBuf::from("libbpf");
let builder = || { let builder = || {
let mut bindgen = bindgen::bpf_builder() let mut bindgen = bindgen::bpf_builder()

@ -2,7 +2,7 @@ mod aya;
mod aya_bpf_bindings; mod aya_bpf_bindings;
mod helpers; mod helpers;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use clap::Parser; use clap::Parser;
@ -86,19 +86,19 @@ enum Command {
AyaBpfBindings, AyaBpfBindings,
} }
pub fn codegen(opts: Options) -> Result<(), anyhow::Error> { pub fn codegen(opts: Options, libbpf_dir: &Path) -> Result<(), anyhow::Error> {
let Options { let Options {
sysroot_options, sysroot_options,
command, command,
} = opts; } = opts;
match command { match command {
Some(command) => match command { Some(command) => match command {
Command::Aya => aya::codegen(&sysroot_options), Command::Aya => aya::codegen(&sysroot_options, libbpf_dir),
Command::AyaBpfBindings => aya_bpf_bindings::codegen(&sysroot_options), Command::AyaBpfBindings => aya_bpf_bindings::codegen(&sysroot_options, libbpf_dir),
}, },
None => { None => {
aya::codegen(&sysroot_options)?; aya::codegen(&sysroot_options, libbpf_dir)?;
aya_bpf_bindings::codegen(&sysroot_options) aya_bpf_bindings::codegen(&sysroot_options, libbpf_dir)
} }
} }
} }

@ -1,22 +1,10 @@
use anyhow::{anyhow, Context as _, Result}; use anyhow::{Context as _, Result};
use cargo_metadata::{Metadata, MetadataCommand}; use cargo_metadata::Metadata;
use indoc::{indoc, writedoc}; use indoc::{indoc, writedoc};
use std::{ffi::OsString, fs, io::Write as _, process::Command}; use std::{ffi::OsString, fs, io::Write as _, process::Command};
use xtask::exec;
pub fn exec(cmd: &mut Command) -> Result<()> { pub fn docs(metadata: Metadata) -> Result<()> {
let status = cmd
.status()
.with_context(|| format!("failed to run {cmd:?}"))?;
match status.code() {
Some(code) => match code {
0 => Ok(()),
code => Err(anyhow!("{cmd:?} exited with code {code}")),
},
None => Err(anyhow!("{cmd:?} terminated by signal")),
}
}
pub fn docs() -> Result<()> {
const PACKAGE_TO_DESCRIPTION: &[(&str, &str)] = &[ const PACKAGE_TO_DESCRIPTION: &[(&str, &str)] = &[
("aya", "User-space BPF program loading and manipulation"), ("aya", "User-space BPF program loading and manipulation"),
("aya-bpf", "Kernel-space BPF program implementation toolkit"), ("aya-bpf", "Kernel-space BPF program implementation toolkit"),
@ -31,7 +19,7 @@ pub fn docs() -> Result<()> {
workspace_root, workspace_root,
target_directory, target_directory,
.. ..
} = MetadataCommand::new().exec().context("cargo metadata")?; } = metadata;
exec( exec(
Command::new("cargo") Command::new("cargo")

@ -0,0 +1,17 @@
use anyhow::{anyhow, Context as _, Result};
use std::process::Command;
pub fn exec(cmd: &mut Command) -> Result<()> {
let status = cmd
.status()
.with_context(|| format!("failed to run {cmd:?}"))?;
match status.code() {
Some(code) => match code {
0 => Ok(()),
code => Err(anyhow!("{cmd:?} exited with code {code}")),
},
None => Err(anyhow!("{cmd:?} terminated by signal")),
}
}
pub const LIBBPF_DIR: &str = "libbpf";

@ -2,29 +2,48 @@ mod codegen;
mod docs; mod docs;
mod run; mod run;
use anyhow::{Context as _, Result};
use cargo_metadata::{Metadata, MetadataCommand};
use clap::Parser; use clap::Parser;
use std::process::Command;
use xtask::{exec, LIBBPF_DIR};
#[derive(Parser)] #[derive(Parser)]
pub struct XtaskOptions { pub struct XtaskOptions {
#[clap(subcommand)] #[clap(subcommand)]
command: Command, command: Subcommand,
} }
#[derive(Parser)] #[derive(Parser)]
enum Command { enum Subcommand {
Codegen(codegen::Options), Codegen(codegen::Options),
Docs, Docs,
BuildIntegrationTest(run::BuildOptions), BuildIntegrationTest(run::BuildOptions),
IntegrationTest(run::Options), IntegrationTest(run::Options),
} }
fn main() -> anyhow::Result<()> { fn main() -> Result<()> {
let XtaskOptions { command } = Parser::parse(); let XtaskOptions { command } = Parser::parse();
let metadata = MetadataCommand::new()
.no_deps()
.exec()
.context("failed to run cargo metadata")?;
let Metadata { workspace_root, .. } = &metadata;
// Initialize the submodules.
exec(Command::new("git").arg("-C").arg(workspace_root).args([
"submodule",
"update",
"--init",
]))?;
let libbpf_dir = workspace_root.join(LIBBPF_DIR);
let libbpf_dir = libbpf_dir.as_std_path();
match command { match command {
Command::Codegen(opts) => codegen::codegen(opts), Subcommand::Codegen(opts) => codegen::codegen(opts, libbpf_dir),
Command::Docs => docs::docs(), Subcommand::Docs => docs::docs(metadata),
Command::BuildIntegrationTest(opts) => { Subcommand::BuildIntegrationTest(opts) => {
let binaries = run::build(opts)?; let binaries = run::build(opts)?;
let mut stdout = std::io::stdout(); let mut stdout = std::io::stdout();
for (_name, binary) in binaries { for (_name, binary) in binaries {
@ -35,6 +54,6 @@ fn main() -> anyhow::Result<()> {
} }
Ok(()) Ok(())
} }
Command::IntegrationTest(opts) => run::run(opts), Subcommand::IntegrationTest(opts) => run::run(opts),
} }
} }

Loading…
Cancel
Save