|
@@ -2,51 +2,34 @@ use std::{
|
|
|
env,
|
|
|
ffi::OsString,
|
|
|
fmt::Write as _,
|
|
|
- fs::copy,
|
|
|
+ fs,
|
|
|
io::BufReader,
|
|
|
path::PathBuf,
|
|
|
process::{Child, Command, Stdio},
|
|
|
};
|
|
|
|
|
|
-use cargo_metadata::{Artifact, CompilerMessage, Message, Target};
|
|
|
+use cargo_metadata::{
|
|
|
+ Artifact, CompilerMessage, Message, Metadata, MetadataCommand, Package, Target,
|
|
|
+};
|
|
|
|
|
|
fn main() {
|
|
|
+ const AYA_BUILD_INTEGRATION_BPF: &str = "AYA_BUILD_INTEGRATION_BPF";
|
|
|
+
|
|
|
+ println!("cargo:rerun-if-env-changed={}", AYA_BUILD_INTEGRATION_BPF);
|
|
|
+
|
|
|
+ let build_integration_bpf = match env::var_os(AYA_BUILD_INTEGRATION_BPF) {
|
|
|
+ None => false,
|
|
|
+ Some(s) => {
|
|
|
+ let s = s.to_str().unwrap();
|
|
|
+ s.parse::<bool>().unwrap()
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
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"
|
|
@@ -56,34 +39,36 @@ fn main() {
|
|
|
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 [
|
|
|
+ const C_BPF_PROBES: &[(&str, &str)] = &[
|
|
|
("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 c_bpf_probes = C_BPF_PROBES
|
|
|
+ .iter()
|
|
|
+ .map(|(src, dst)| (src, out_dir.join(dst)));
|
|
|
+
|
|
|
+ if build_integration_bpf {
|
|
|
+ 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}"));
|
|
@@ -94,64 +79,118 @@ fn main() {
|
|
|
},
|
|
|
None => panic!("{cmd:?} terminated by signal"),
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- let ebpf_dir = manifest_dir.parent().unwrap().join("integration-ebpf");
|
|
|
- let target = format!("{target}-unknown-none");
|
|
|
-
|
|
|
- let mut cmd = Command::new("cargo");
|
|
|
- cmd.current_dir(&ebpf_dir).args([
|
|
|
- "build",
|
|
|
- "-Z",
|
|
|
- "build-std=core",
|
|
|
- "--release",
|
|
|
- "--message-format=json",
|
|
|
- "--target",
|
|
|
- &target,
|
|
|
- ]);
|
|
|
- let mut child = cmd
|
|
|
- .stdout(Stdio::piped())
|
|
|
- .spawn()
|
|
|
- .unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}"));
|
|
|
- let Child { stdout, .. } = &mut child;
|
|
|
- let stdout = stdout.take().unwrap();
|
|
|
- let reader = BufReader::new(stdout);
|
|
|
- let mut executables = Vec::new();
|
|
|
- let mut compiler_messages = String::new();
|
|
|
- for message in Message::parse_stream(reader) {
|
|
|
- #[allow(clippy::collapsible_match)]
|
|
|
- match message.expect("valid JSON") {
|
|
|
- Message::CompilerArtifact(Artifact {
|
|
|
- executable,
|
|
|
- target: Target { name, .. },
|
|
|
- ..
|
|
|
- }) => {
|
|
|
- if let Some(executable) = executable {
|
|
|
- executables.push((name, executable.into_std_path_buf()));
|
|
|
- }
|
|
|
+ let bpf_dir = manifest_dir.join("bpf");
|
|
|
+
|
|
|
+ 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 c_bpf_probes {
|
|
|
+ let src = bpf_dir.join(src);
|
|
|
+ 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(dst);
|
|
|
+ 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"),
|
|
|
}
|
|
|
- Message::CompilerMessage(CompilerMessage { message, .. }) => {
|
|
|
- writeln!(&mut compiler_messages, "{message}").unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ let ebpf_dir = manifest_dir.parent().unwrap().join("integration-ebpf");
|
|
|
+ let target = format!("{target}-unknown-none");
|
|
|
+
|
|
|
+ let mut cmd = Command::new("cargo");
|
|
|
+ cmd.current_dir(&ebpf_dir).args([
|
|
|
+ "build",
|
|
|
+ "-Z",
|
|
|
+ "build-std=core",
|
|
|
+ "--release",
|
|
|
+ "--message-format=json",
|
|
|
+ "--target",
|
|
|
+ &target,
|
|
|
+ ]);
|
|
|
+ let mut child = cmd
|
|
|
+ .stdout(Stdio::piped())
|
|
|
+ .spawn()
|
|
|
+ .unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}"));
|
|
|
+ let Child { stdout, .. } = &mut child;
|
|
|
+ let stdout = stdout.take().unwrap();
|
|
|
+ let reader = BufReader::new(stdout);
|
|
|
+ let mut executables = Vec::new();
|
|
|
+ let mut compiler_messages = String::new();
|
|
|
+ for message in Message::parse_stream(reader) {
|
|
|
+ #[allow(clippy::collapsible_match)]
|
|
|
+ match message.expect("valid JSON") {
|
|
|
+ Message::CompilerArtifact(Artifact {
|
|
|
+ executable,
|
|
|
+ target: Target { name, .. },
|
|
|
+ ..
|
|
|
+ }) => {
|
|
|
+ if let Some(executable) = executable {
|
|
|
+ executables.push((name, executable.into_std_path_buf()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Message::CompilerMessage(CompilerMessage { message, .. }) => {
|
|
|
+ writeln!(&mut compiler_messages, "{message}").unwrap()
|
|
|
+ }
|
|
|
+ _ => {}
|
|
|
}
|
|
|
- _ => {}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- let status = child
|
|
|
- .wait()
|
|
|
- .unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}"));
|
|
|
+ let status = child
|
|
|
+ .wait()
|
|
|
+ .unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}"));
|
|
|
|
|
|
- match status.code() {
|
|
|
- Some(code) => match code {
|
|
|
- 0 => {}
|
|
|
- code => panic!("{cmd:?} exited with status code {code}:\n{compiler_messages}"),
|
|
|
- },
|
|
|
- None => panic!("{cmd:?} terminated by signal"),
|
|
|
- }
|
|
|
+ match status.code() {
|
|
|
+ Some(code) => match code {
|
|
|
+ 0 => {}
|
|
|
+ code => panic!("{cmd:?} exited with status code {code}:\n{compiler_messages}"),
|
|
|
+ },
|
|
|
+ None => panic!("{cmd:?} terminated by signal"),
|
|
|
+ }
|
|
|
|
|
|
- for (name, binary) in executables {
|
|
|
- let dst = out_dir.join(name);
|
|
|
- let _: u64 = copy(&binary, &dst)
|
|
|
- .unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}"));
|
|
|
+ for (name, binary) in executables {
|
|
|
+ let dst = out_dir.join(name);
|
|
|
+ let _: u64 = fs::copy(&binary, &dst)
|
|
|
+ .unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}"));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (_src, dst) in c_bpf_probes {
|
|
|
+ fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}"));
|
|
|
+ }
|
|
|
+
|
|
|
+ let Metadata { packages, .. } = MetadataCommand::new().no_deps().exec().unwrap();
|
|
|
+ for Package { name, targets, .. } in packages {
|
|
|
+ if name != "integration-ebpf" {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for Target { name, kind, .. } in targets {
|
|
|
+ if kind != ["bin"] {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ let dst = out_dir.join(name);
|
|
|
+ fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}"));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|