ソースを参照

integration-ebpf: invalidate on bpf-linker

Extract the symlink-to-bpf-linker logic from integration-test to xtask
and use it in a new build script in integration-ebpf, causing ebpf
probes to be rebuilt when bpf-linker changes. Previously bpf-linker
changes would rebuild integration-test, but not integration-ebpf,
resulting in stale tests.

Note that this still doesn't address the possibility that a new
bpf-linker is added to the PATH ahead of the cached one. Solving this in
the general case would require rebuild-if-changed-env=PATH *and*
rebuild-if-changed={every-directory-in-PATH} which would likely mean far
too much cache invalidation.
Tamir Duberstein 1 年間 前
コミット
e276c07f73

+ 3 - 0
test/integration-ebpf/Cargo.toml

@@ -8,6 +8,9 @@ publish = false
 aya-bpf = { path = "../../bpf/aya-bpf" }
 aya-log-ebpf = { path = "../../bpf/aya-log-ebpf" }
 
+[build-dependencies]
+xtask = { path = "../../xtask" }
+
 [[bin]]
 name = "log"
 path = "src/log.rs"

+ 23 - 0
test/integration-ebpf/build.rs

@@ -0,0 +1,23 @@
+use std::{env, path::PathBuf};
+
+use xtask::{create_symlink_to_binary, AYA_BUILD_INTEGRATION_BPF};
+
+fn main() {
+    println!("cargo:rerun-if-env-changed={}", AYA_BUILD_INTEGRATION_BPF);
+
+    let build_integration_bpf = env::var(AYA_BUILD_INTEGRATION_BPF)
+        .as_deref()
+        .map(str::parse)
+        .map(Result::unwrap)
+        .unwrap_or_default();
+
+    if build_integration_bpf {
+        let out_dir = env::var_os("OUT_DIR").unwrap();
+        let out_dir = PathBuf::from(out_dir);
+        let bpf_linker_symlink = create_symlink_to_binary(&out_dir, "bpf-linker").unwrap();
+        println!(
+            "cargo:rerun-if-changed={}",
+            bpf_linker_symlink.to_str().unwrap()
+        );
+    }
+}

+ 0 - 1
test/integration-test/Cargo.toml

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

+ 11 - 33
test/integration-test/build.rs

@@ -12,21 +12,16 @@ use std::{
 use cargo_metadata::{
     Artifact, CompilerMessage, Dependency, Message, Metadata, MetadataCommand, Package, Target,
 };
-use which::which;
-use xtask::{exec, LIBBPF_DIR};
+use xtask::{create_symlink_to_binary, exec, AYA_BUILD_INTEGRATION_BPF, LIBBPF_DIR};
 
 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 build_integration_bpf = env::var(AYA_BUILD_INTEGRATION_BPF)
+        .as_deref()
+        .map(str::parse)
+        .map(Result::unwrap)
+        .unwrap_or_default();
 
     const INTEGRATION_EBPF_PACKAGE: &str = "integration-ebpf";
 
@@ -137,28 +132,11 @@ fn main() {
             }
         }
 
-        // Create a symlink in the out directory to work around the fact that cargo ignores anything
-        // in `$CARGO_HOME`, which is also where `cargo install` likes to place binaries. Cargo will
-        // stat through the symlink and discover that bpf-linker has changed.
-        //
-        // This was introduced in https://github.com/rust-lang/cargo/commit/99f841c.
-        {
-            let bpf_linker = which("bpf-linker").unwrap();
-            let bpf_linker_symlink = out_dir.join("bpf-linker");
-            match fs::remove_file(&bpf_linker_symlink) {
-                Ok(()) => {}
-                Err(err) => {
-                    if err.kind() != std::io::ErrorKind::NotFound {
-                        panic!("failed to remove symlink: {err}")
-                    }
-                }
-            }
-            std::os::unix::fs::symlink(&bpf_linker, &bpf_linker_symlink).unwrap();
-            println!(
-                "cargo:rerun-if-changed={}",
-                bpf_linker_symlink.to_str().unwrap()
-            );
-        }
+        let bpf_linker_symlink = create_symlink_to_binary(&out_dir, "bpf-linker").unwrap();
+        println!(
+            "cargo:rerun-if-changed={}",
+            bpf_linker_symlink.to_str().unwrap()
+        );
 
         let mut cmd = Command::new("cargo");
         cmd.args([

+ 1 - 0
xtask/Cargo.toml

@@ -14,3 +14,4 @@ proc-macro2 = "1"
 quote = "1"
 syn = "2"
 tempfile = "3"
+which = { version = "4.4.0", default-features = false }

+ 31 - 2
xtask/src/lib.rs

@@ -1,5 +1,13 @@
 use anyhow::{anyhow, Context as _, Result};
-use std::process::Command;
+use std::{
+    fs,
+    path::{Path, PathBuf},
+    process::Command,
+};
+use which::which;
+
+pub const AYA_BUILD_INTEGRATION_BPF: &str = "AYA_BUILD_INTEGRATION_BPF";
+pub const LIBBPF_DIR: &str = "xtask/libbpf";
 
 pub fn exec(cmd: &mut Command) -> Result<()> {
     let status = cmd
@@ -14,4 +22,25 @@ pub fn exec(cmd: &mut Command) -> Result<()> {
     }
 }
 
-pub const LIBBPF_DIR: &str = "xtask/libbpf";
+// Create a symlink in the out directory to work around the fact that cargo ignores anything
+// in `$CARGO_HOME`, which is also where `cargo install` likes to place binaries. Cargo will
+// stat through the symlink and discover that the binary has changed.
+//
+// This was introduced in https://github.com/rust-lang/cargo/commit/99f841c.
+//
+// TODO(https://github.com/rust-lang/cargo/pull/12369): Remove this when the fix is available.
+pub fn create_symlink_to_binary(out_dir: &Path, binary_name: &str) -> Result<PathBuf> {
+    let binary = which(binary_name).unwrap();
+    let symlink = out_dir.join(binary_name);
+    match fs::remove_file(&symlink) {
+        Ok(()) => {}
+        Err(err) => {
+            if err.kind() != std::io::ErrorKind::NotFound {
+                return Err(err).context(format!("failed to remove symlink {}", symlink.display()));
+            }
+        }
+    }
+    std::os::unix::fs::symlink(binary, &symlink)
+        .with_context(|| format!("failed to create symlink {}", symlink.display()))?;
+    Ok(symlink)
+}

+ 2 - 1
xtask/src/run.rs

@@ -8,6 +8,7 @@ use std::{
 use anyhow::{Context as _, Result};
 use cargo_metadata::{Artifact, CompilerMessage, Message, Target};
 use clap::Parser;
+use xtask::AYA_BUILD_INTEGRATION_BPF;
 
 #[derive(Debug, Parser)]
 pub struct BuildOptions {
@@ -35,7 +36,7 @@ pub struct Options {
 pub fn build(opts: BuildOptions) -> Result<Vec<(String, PathBuf)>> {
     let BuildOptions { release, target } = opts;
     let mut cmd = Command::new("cargo");
-    cmd.env("AYA_BUILD_INTEGRATION_BPF", "true").args([
+    cmd.env(AYA_BUILD_INTEGRATION_BPF, "true").args([
         "build",
         "--tests",
         "--message-format=json",