Skip to content

Commit a4696bf

Browse files
committed
Re-implement the build of libbpf
1 parent 5f6ebdf commit a4696bf

File tree

2 files changed

+57
-48
lines changed

2 files changed

+57
-48
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ bindgen = { version = "^0.71.1", optional = true }
3030
cc = "^1.1.6"
3131
pkg-config = "^0.3.30"
3232
nix = { version = "^0.29.0", default-features = false, features = ["fs"] }
33+
shlex = "1.3.0"
3334

3435
[lib]
3536
crate-type = ["lib", "staticlib"]

build.rs

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// build.rs
22

33
use std::env;
4-
use std::ffi;
5-
use std::fs;
64
use std::fs::read_dir;
75
use std::path;
86
use std::path::Path;
@@ -155,35 +153,35 @@ fn main() {
155153
pkg_check("aclocal");
156154
}
157155

158-
let (compiler, mut cflags) = if vendored_libbpf || vendored_libelf || vendored_zlib {
156+
let (compiler, cflags) = if vendored_libbpf || vendored_libelf || vendored_zlib {
159157
pkg_check("pkg-config");
160158

161159
let compiler = cc::Build::new().try_get_compiler().expect(
162160
"a C compiler is required to compile libbpf-sys using the vendored copy of libbpf",
163161
);
164-
let mut cflags = compiler.cflags_env();
162+
let mut cflags = Vec::new();
165163
println!("cargo:rerun-if-env-changed=LIBBPF_SYS_EXTRA_CFLAGS");
166164
if let Some(extra_cflags) = env::var_os("LIBBPF_SYS_EXTRA_CFLAGS") {
167-
cflags.push(" ");
168-
cflags.push(extra_cflags);
165+
let flags = extra_cflags.into_string().expect("LIBBPF_SYS_EXTRA_CFLAGS");
166+
if let Some(flags) = shlex::split(&flags) {
167+
cflags.extend(flags);
168+
}
169169
}
170170
(Some(compiler), cflags)
171171
} else {
172-
(None, ffi::OsString::new())
172+
(None, vec![])
173173
};
174174

175175
if vendored_zlib {
176176
make_zlib(compiler.as_ref().unwrap(), &src_dir);
177-
cflags.push(format!(" -I{}/zlib/", src_dir.display()));
178177
}
179178

180179
if vendored_libelf {
181-
make_elfutils(compiler.as_ref().unwrap(), &src_dir, &out_dir);
182-
cflags.push(format!(" -I{}/elfutils/libelf/", src_dir.display()));
180+
make_elfutils(compiler.as_ref().unwrap(), &src_dir);
183181
}
184182

185183
if vendored_libbpf {
186-
make_libbpf(compiler.as_ref().unwrap(), &cflags, &src_dir, &out_dir);
184+
make_libbpf(compiler.as_ref().unwrap(), cflags.as_slice(), &src_dir);
187185
}
188186

189187
println!(
@@ -284,7 +282,7 @@ fn make_zlib(compiler: &cc::Tool, src_dir: &path::Path) {
284282
emit_rerun_directives_for_contents(&src_dir);
285283
}
286284

287-
fn make_elfutils(compiler: &cc::Tool, src_dir: &path::Path, _: &path::Path) {
285+
fn make_elfutils(compiler: &cc::Tool, src_dir: &path::Path) {
288286
// lock README such that if two crates are trying to compile
289287
// this at the same time (eg libbpf-rs libbpf-cargo)
290288
// they wont trample each other
@@ -376,46 +374,56 @@ fn make_elfutils(compiler: &cc::Tool, src_dir: &path::Path, _: &path::Path) {
376374
emit_rerun_directives_for_contents(&src_dir.join("elfutils").join("src"));
377375
}
378376

379-
fn make_libbpf(
380-
compiler: &cc::Tool,
381-
cflags: &ffi::OsStr,
382-
src_dir: &path::Path,
383-
out_dir: &path::Path,
384-
) {
385-
let src_dir = src_dir.join("libbpf/src");
386-
// create obj_dir if it doesn't exist
387-
let obj_dir = path::PathBuf::from(&out_dir.join("obj").into_os_string());
388-
let _ = fs::create_dir(&obj_dir);
389-
390-
let status = process::Command::new("make")
391-
.arg("install")
392-
.arg("-j")
393-
.arg(format!("{}", num_cpus()))
394-
.env("BUILD_STATIC_ONLY", "y")
395-
.env("PREFIX", "/")
396-
.env("LIBDIR", "")
397-
.env("OBJDIR", &obj_dir)
398-
.env("DESTDIR", out_dir)
399-
.env("CC", compiler.path())
400-
.env("CFLAGS", cflags)
401-
.current_dir(&src_dir)
402-
.status()
403-
.expect("could not execute make");
377+
fn make_libbpf(compiler: &cc::Tool, flags: &[String], src_dir: &path::Path) {
378+
let project_dir = src_dir.join("libbpf");
404379

405-
assert!(status.success(), "make failed");
380+
let project = project_dir.to_str().unwrap();
406381

407-
let status = process::Command::new("make")
408-
.arg("clean")
409-
.current_dir(&src_dir)
410-
.status()
411-
.expect("could not execute make");
382+
let mut builder = cc::Build::new();
412383

413-
assert!(status.success(), "make failed");
414-
emit_rerun_directives_for_contents(&src_dir);
415-
}
384+
builder
385+
.include(src_dir)
386+
.include(src_dir.join("zlib"))
387+
.include(src_dir.join("elfutils").join("libelf"))
388+
.include(format!("{project}/src"))
389+
.include(format!("{project}/include"))
390+
.include(format!("{project}/include/uapi"));
391+
392+
flags.iter().for_each(|flag| {
393+
builder.flag(flag);
394+
});
395+
396+
if build_android() {
397+
let cflags = ["-DCOMPAT_NEED_REALLOCARRAY"];
398+
399+
builder.flag("-includeandroid/android.h");
400+
401+
for flag in cflags {
402+
builder.flag(flag);
403+
}
404+
} else {
405+
builder.compiler(compiler.path());
416406

417-
fn num_cpus() -> usize {
418-
std::thread::available_parallelism().map_or(1, |count| count.get())
407+
for flag in compiler.args() {
408+
builder.flag(flag);
409+
}
410+
}
411+
412+
for entry in std::fs::read_dir(project_dir.join("src")).expect("Failed to `read_dir`") {
413+
let entry = entry.unwrap();
414+
if entry.file_type().unwrap().is_file()
415+
&& entry.file_name().to_str().unwrap().ends_with(".c")
416+
{
417+
builder.file(entry.path());
418+
}
419+
}
420+
421+
builder
422+
.flag_if_supported("-w")
423+
.warnings(false)
424+
.compile("bpf");
425+
426+
emit_rerun_directives_for_contents(&src_dir);
419427
}
420428

421429
fn build_android() -> bool {

0 commit comments

Comments
 (0)