From 237815d97565192b7db0c198674bf5fe8ff518d6 Mon Sep 17 00:00:00 2001 From: amirb Date: Tue, 25 Nov 2025 14:06:20 +0200 Subject: [PATCH] Add per-target LIBBPF_SYS_LIBRARY_PATH environment variable to help cross-compilation environments This solves an issue when cross-compiling an application that uses libbpf-sys in build.rs(Usually via libbpf-cargo). In that case, the libbpf-sys crate is built twice - once for the host triplet (let's say x86_64-unknown-linux-gnu, when compiling build.rs) and once for the target triplet (let's say aarch64-linux-android, when compiling the actual application). If we set `LIBBPF_SYS_LIBRARY_PATH` to a path that contains the libelf for the target triplet, then `build.rs` will link to the incorrect library, failing the build. --- README.md | 1 + build.rs | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a4d8ff2..b25039d 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ $ cargo build - `LIBBPF_SYS_EXTRA_CFLAGS` can be used to pass extra cflags when vendoring libbpf, libz or libelf. - `LIBBPF_SYS_LIBRARY_PATH`: colon separated paths for the linker to find native libs. +- `LIBBPF_SYS_LIBRARY_PATH_`: similar to `LIBBPF_SYS_LIBRARY_PATH`, but used to set per-target library path, to help cross-compilation environments. If `LIBBPF_SYS_LIBRARY_PATH_` and `LIBBPF_SYS_LIBRARY_PATH` are defined, the paths from both will be used, and the "target" paths will have precedence. ### Distribution diff --git a/build.rs b/build.rs index 268a516..8e04244 100644 --- a/build.rs +++ b/build.rs @@ -203,11 +203,30 @@ fn main() { ); println!("cargo:include={}/include", out_dir.to_string_lossy()); - println!("cargo:rerun-if-env-changed=LIBBPF_SYS_LIBRARY_PATH"); - if let Ok(lib_path) = env::var("LIBBPF_SYS_LIBRARY_PATH") { - for path in lib_path.split(':') { - if !path.is_empty() { - println!("cargo:rustc-link-search=native={}", path); + let global_lib_path = "LIBBPF_SYS_LIBRARY_PATH"; + let target_lib_path = format!("{}_{}", global_lib_path, env::var("TARGET").unwrap()); + let target_lib_path_underscored = format!( + "{}_{}", + global_lib_path, + env::var("TARGET").unwrap().replace('-', "_") + ); + + println!("cargo:rerun-if-env-changed={}", global_lib_path); + println!("cargo:rerun-if-env-changed={}", target_lib_path); + println!("cargo:rerun-if-env-changed={}", target_lib_path_underscored); + + let lib_paths = vec![ + env::var(target_lib_path), + env::var(target_lib_path_underscored), + env::var(global_lib_path), + ]; + + for lib_path in lib_paths { + if let Ok(lib_path) = lib_path { + for path in lib_path.split(':') { + if !path.is_empty() { + println!("cargo:rustc-link-search=native={}", path); + } } } }