Skip to content

Commit de3d062

Browse files
committed
Overhaul vendoring/linking features
This change overhauls the vendoring & static linking features that the library exposes, in an attempt to make everything more to the point. Please refer to the larger discussion [0] for additional context, but in short: we introduce separate features for vendoring/linking each of the three system library dependencies: libbpf, libelf, zlib. "static" and "vendored" meta-features are still available, which apply to all three libraries in unison. The remaining dependencies are expressed declaratively via dependent features. E.g., because zlib is only a dependency of libbpf (and not a direct one), linking it statically implies linking libbpf statically. In the future, this design would make it possible to enable additional configurations. For example, currently vendoring any library implies linking it statically, because we only build the static version. This is more of a simplification than a strict requirement and if needed, we could support dynamic linking when using a vendored copy. The default features mirror the previous default and no behavior change should occur. The existing novendor feature is kept but deprecated and should be removed in the future (a warning will be printed as part of the build). It was certainly one of the main causes of confusion where novendor and vendored could co-exist and it was hard to understand what would or wouldn't happen. In the new world, users are advised to simply build with all features disabled. I tested everything on a binary depending on libbpf-sys with various features enabled and spot checked the expected dynamic library dependencies. We could enshrine that as a CI step, but given that this logic is expected to change infrequently I didn't go down that road. [0] libbpf#64 (comment) Signed-off-by: Daniel Müller <[email protected]>
1 parent e062bb1 commit de3d062

File tree

4 files changed

+73
-36
lines changed

4 files changed

+73
-36
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- rust-target: x86_64-unknown-linux-gnu
1919
os-target: x86_64-linux-gnu
2020
os-arch: amd64
21-
args: --features=novendor
21+
args: --no-default-features
2222
install-sys-libbpf: y
2323

2424
- rust-target: aarch64-unknown-linux-gnu
@@ -87,7 +87,7 @@ jobs:
8787
matrix:
8888
include:
8989
- args: ''
90-
- args: --features=novendor
90+
- args: --no-default-features
9191
install-sys-libbpf: y
9292
env:
9393
CARGO_TERM_VERBOSE: 'true'

Cargo.toml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,25 @@ num_cpus = "^1.16.0"
3636
crate-type = ["lib", "staticlib"]
3737

3838
[features]
39+
default = ["vendored-libbpf"]
40+
# Don't vendor anything. This feature is deprecated. Simply build without
41+
# any features instead.
3942
novendor = []
40-
static = []
41-
vendored = ["static"]
43+
# Meta-feature to use vendored versions of all dependencies.
44+
vendored = ["vendored-libbpf", "vendored-libelf", "vendored-zlib"]
45+
# Use vendored `libbpf`. Implies linking it statically.
46+
vendored-libbpf = ["static-libbpf"]
47+
# Use vendored `libelf`. Implies linking it statically.
48+
vendored-libelf = ["static-libelf"]
49+
# Use vendored `zlib`. Implies linking it statically.
50+
vendored-zlib = ["static-zlib"]
51+
# Meta-feature to link against all dependencies statically.
52+
static = ["static-libbpf", "static-libelf", "static-zlib"]
53+
# Link libbpf statically.
54+
static-libbpf = []
55+
# Link libelf statically. Implies linking libbpf statically, because libbpf is
56+
# the libelf consumer.
57+
static-libelf = ["static-libbpf"]
58+
# Link zlib statically. Implies linking libbpf statically, because libbpf is
59+
# the libelf consumer.
60+
static-zlib = ["static-libbpf"]

build.rs

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,10 @@ fn generate_bindings(src_dir: path::PathBuf) {
8080
#[cfg(not(feature = "bindgen"))]
8181
fn generate_bindings(_: path::PathBuf) {}
8282

83-
#[cfg(feature = "static")]
84-
fn library_prefix() -> String {
85-
"static=".to_string()
86-
}
87-
88-
#[cfg(not(feature = "static"))]
89-
fn library_prefix() -> String {
90-
"".to_string()
91-
}
92-
9383
fn pkg_check(pkg: &str) {
9484
if process::Command::new(pkg).status().is_err() {
9585
panic!(
96-
"{} is required to compile libbpf-sys using the vendored copy of libbpf",
86+
"{} is required to compile libbpf-sys with the selected set of features",
9787
pkg
9888
);
9989
}
@@ -104,17 +94,38 @@ fn main() {
10494

10595
generate_bindings(src_dir.clone());
10696

97+
let vendored_libbpf = cfg!(feature = "vendored-libbpf");
98+
let vendored_libelf = cfg!(feature = "vendored-libelf");
99+
let vendored_zlib = cfg!(feature = "vendored-zlib");
100+
println!("Using feature vendored-libbpf={}", vendored_libbpf);
101+
println!("Using feature vendored-libelf={}", vendored_libelf);
102+
println!("Using feature vendored-zlib={}", vendored_zlib);
103+
104+
let static_libbpf = cfg!(feature = "static-libbpf");
105+
let static_libelf = cfg!(feature = "static-libelf");
106+
let static_zlib = cfg!(feature = "static-zlib");
107+
println!("Using feature static-libbpf={}", static_libbpf);
108+
println!("Using feature static-libelf={}", static_libelf);
109+
println!("Using feature static-zlib={}", static_zlib);
110+
107111
if cfg!(feature = "novendor") {
108-
println!("cargo:rustc-link-lib={}bpf\n", library_prefix());
112+
println!("cargo:warning=the `novendor` feature of `libbpf-sys` is deprecated; build without features instead");
113+
println!(
114+
"cargo:rustc-link-lib={}bpf",
115+
if static_libbpf { "static=" } else { "" }
116+
);
109117
return;
110118
}
111119

112120
let out_dir = path::PathBuf::from(env::var_os("OUT_DIR").unwrap());
113121

114122
// check for all necessary compilation tools
115-
pkg_check("make");
116-
pkg_check("pkg-config");
117-
if cfg!(feature = "vendored") {
123+
// TODO: Not all packages are required for all builds. Dependencies should
124+
// be clarified and these checks be pushed into individual `make_*`
125+
// functions.
126+
if vendored_libbpf || vendored_libelf || vendored_zlib {
127+
pkg_check("make");
128+
pkg_check("pkg-config");
118129
pkg_check("autoreconf");
119130
pkg_check("autopoint");
120131
pkg_check("flex");
@@ -129,32 +140,38 @@ fn main() {
129140
),
130141
};
131142

132-
if cfg!(feature = "vendored") {
143+
let mut cflags = compiler.cflags_env();
144+
145+
if vendored_zlib {
133146
make_zlib(&compiler, &src_dir, &out_dir);
134-
make_elfutils(&compiler, &src_dir, &out_dir);
147+
cflags.push(&format!(" -I{}/zlib/", src_dir.display()));
135148
}
136149

137-
let cflags = if cfg!(feature = "vendored") {
138-
// make sure that the headerfiles from libelf and zlib
139-
// for libbpf come from the vendorized version
140-
141-
let mut cflags = compiler.cflags_env();
150+
if vendored_libelf {
151+
make_elfutils(&compiler, &src_dir, &out_dir);
142152
cflags.push(&format!(" -I{}/elfutils/libelf/", src_dir.display()));
143-
cflags.push(&format!(" -I{}/zlib/", src_dir.display()));
144-
cflags
145-
} else {
146-
compiler.cflags_env()
147-
};
153+
}
148154

149-
make_libbpf(&compiler, &cflags, &src_dir, &out_dir);
155+
if vendored_libbpf {
156+
make_libbpf(&compiler, &cflags, &src_dir, &out_dir);
157+
}
150158

151159
println!(
152160
"cargo:rustc-link-search=native={}",
153161
out_dir.to_string_lossy()
154162
);
155-
println!("cargo:rustc-link-lib={}elf", library_prefix());
156-
println!("cargo:rustc-link-lib={}z", library_prefix());
157-
println!("cargo:rustc-link-lib=static=bpf");
163+
println!(
164+
"cargo:rustc-link-lib={}elf",
165+
if static_libelf { "static=" } else { "" }
166+
);
167+
println!(
168+
"cargo:rustc-link-lib={}z",
169+
if static_zlib { "static=" } else { "" }
170+
);
171+
println!(
172+
"cargo:rustc-link-lib={}bpf",
173+
if static_libbpf { "static=" } else { "" }
174+
);
158175
println!("cargo:include={}/include", out_dir.to_string_lossy());
159176

160177
if let Ok(ld_path) = env::var("LD_LIBRARY_PATH") {

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
include!("bindings.rs");
88

9+
#[cfg(feature = "vendor-libbpf")]
910
macro_rules! header {
1011
($file:literal) => {
1112
($file, include_str!(concat!("../libbpf/src/", $file)))
@@ -15,7 +16,7 @@ macro_rules! header {
1516
/// Vendored libbpf headers
1617
///
1718
/// Tuple format is: (header filename, header contents)
18-
#[cfg(not(feature = "novendor"))]
19+
#[cfg(feature = "vendor-libbpf")]
1920
pub const API_HEADERS: [(&str, &str); 10] = [
2021
header!("bpf.h"),
2122
header!("libbpf.h"),

0 commit comments

Comments
 (0)