Skip to content

Commit 5f6ebdf

Browse files
committed
Re-implement the build of libelf
1 parent 89cfe6c commit 5f6ebdf

File tree

1 file changed

+82
-79
lines changed

1 file changed

+82
-79
lines changed

build.rs

Lines changed: 82 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -284,54 +284,33 @@ fn make_zlib(compiler: &cc::Tool, src_dir: &path::Path) {
284284
emit_rerun_directives_for_contents(&src_dir);
285285
}
286286

287-
fn make_elfutils(compiler: &cc::Tool, src_dir: &path::Path, out_dir: &path::Path) {
287+
fn make_elfutils(compiler: &cc::Tool, src_dir: &path::Path, _: &path::Path) {
288288
// lock README such that if two crates are trying to compile
289289
// this at the same time (eg libbpf-rs libbpf-cargo)
290290
// they wont trample each other
291-
let file = std::fs::File::open(src_dir.join("elfutils/README")).unwrap();
292-
let _lock = fcntl::Flock::lock(file, fcntl::FlockArg::LockExclusive).unwrap();
293-
294-
let flags = compiler
295-
.cflags_env()
296-
.into_string()
297-
.expect("failed to get cflags");
298-
let mut cflags: String = flags
299-
.split_whitespace()
300-
.filter_map(|arg| {
301-
if arg != "-static" {
302-
// compilation fails with -static flag
303-
Some(format!(" {arg}"))
304-
} else {
305-
None
306-
}
307-
})
308-
.collect();
291+
let project_dir = src_dir.join("elfutils");
309292

310-
#[cfg(target_arch = "aarch64")]
311-
cflags.push_str(" -Wno-error=stringop-overflow");
312-
cflags.push_str(&format!(" -I{}/zlib/", src_dir.display()));
313-
314-
let status = process::Command::new("autoreconf")
315-
.arg("--install")
316-
.arg("--force")
317-
.current_dir(src_dir.join("elfutils"))
318-
.status()
319-
.expect("could not execute make");
293+
let file = std::fs::File::open(project_dir.join("README")).unwrap();
294+
let _lock = fcntl::Flock::lock(file, fcntl::FlockArg::LockExclusive).unwrap();
320295

321-
assert!(status.success(), "make failed");
296+
let libelf_dir = project_dir.join("libelf");
297+
let project_dir = project_dir.to_str().unwrap();
322298

323-
// location of libz.a
324-
let out_lib = format!("-L{}", out_dir.display());
325-
let status = process::Command::new("./configure")
326-
.arg("--enable-maintainer-mode")
327-
.arg("--disable-debuginfod")
328-
.arg("--disable-libdebuginfod")
329-
.arg("--disable-demangler")
330-
.arg("--without-zstd")
331-
.arg("--prefix")
332-
.arg(src_dir.join("elfutils/prefix_dir"))
333-
.arg("--host")
334-
.arg({
299+
let mut build_options = vec![
300+
"--enable-maintainer-mode",
301+
"--disable-debuginfod",
302+
"--disable-libdebuginfod",
303+
"--without-lzma",
304+
"--without-bzlib",
305+
"--without-zstd",
306+
]
307+
.into_iter()
308+
.map(|s| s.to_string())
309+
.collect::<Vec<String>>();
310+
311+
if !build_android() {
312+
build_options.push("--host".to_owned());
313+
build_options.push({
335314
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
336315
let arch = match arch.as_str() {
337316
"riscv64gc" => "riscv64",
@@ -342,50 +321,58 @@ fn make_elfutils(compiler: &cc::Tool, src_dir: &path::Path, out_dir: &path::Path
342321
let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
343322
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
344323
format!("{arch}-{vendor}-{os}-{env}")
345-
})
346-
.arg("--libdir")
347-
.arg(out_dir)
348-
.env("CC", compiler.path())
349-
.env("CXX", compiler.path())
350-
.env("CFLAGS", &cflags)
351-
.env("CXXFLAGS", &cflags)
352-
.env("LDFLAGS", &out_lib)
353-
.current_dir(src_dir.join("elfutils"))
354-
.status()
355-
.expect("could not execute make");
324+
});
325+
}
356326

357-
assert!(status.success(), "make failed");
327+
autoconf(project_dir);
358328

359-
// Build in elfutils/lib because building libelf requires it.
360-
let status = process::Command::new("make")
361-
.arg("-j")
362-
.arg(format!("{}", num_cpus()))
363-
.arg("BUILD_STATIC_ONLY=y")
364-
.current_dir(src_dir.join("elfutils/lib"))
365-
.status()
366-
.expect("could not execute make");
329+
configure(project_dir, build_options.iter().map(|s| s.as_str()));
367330

368-
assert!(status.success(), "make failed");
331+
let mut builder = cc::Build::new();
369332

370-
// Build libelf only
371-
let status = process::Command::new("make")
372-
.arg("install")
373-
.arg("-j")
374-
.arg(format!("{}", num_cpus()))
375-
.arg("BUILD_STATIC_ONLY=y")
376-
.current_dir(src_dir.join("elfutils/libelf"))
377-
.status()
378-
.expect("could not execute make");
333+
builder
334+
.flag("-DHAVE_CONFIG_H")
335+
.flag("-D_GNU_SOURCE")
336+
.include(project_dir)
337+
.include(src_dir.join("zlib"))
338+
.include(format!("{project_dir}/lib"))
339+
.include(format!("{project_dir}/include"))
340+
.include(format!("{project_dir}/libelf"));
379341

380-
assert!(status.success(), "make failed");
342+
if build_android() {
343+
builder
344+
.flag("-DNAMES=1000")
345+
.flag("-std=gnu99")
346+
.flag("-D_FILE_OFFSET_BITS=64")
347+
.flag("-includeAndroidFixup.h")
348+
.include(src_dir.join("android"));
349+
} else {
350+
#[cfg(target_arch = "aarch64")]
351+
builder.flag("-Wno-error=stringop-overflow");
381352

382-
let status = process::Command::new("make")
383-
.arg("distclean")
384-
.current_dir(src_dir.join("elfutils"))
385-
.status()
386-
.expect("could not execute make");
353+
builder.compiler(compiler.path());
354+
355+
for flag in compiler.args() {
356+
if flag.ne("-static") {
357+
builder.flag(flag);
358+
}
359+
}
360+
}
361+
362+
for entry in std::fs::read_dir(libelf_dir).expect("Failed to `read_dir`") {
363+
let entry = entry.expect("Failed to `read_dir`");
364+
if entry.file_type().unwrap().is_file()
365+
&& entry.file_name().to_str().unwrap().ends_with(".c")
366+
{
367+
builder.file(entry.path());
368+
}
369+
}
370+
371+
builder
372+
.flag_if_supported("-w")
373+
.warnings(false)
374+
.compile("elf");
387375

388-
assert!(status.success(), "make failed");
389376
emit_rerun_directives_for_contents(&src_dir.join("elfutils").join("src"));
390377
}
391378

@@ -472,3 +459,19 @@ where
472459
.status()
473460
.expect(&format!("could not execute `{}`", prog.as_ref()))
474461
}
462+
463+
fn autoconf<P>(project_dir: P)
464+
where
465+
P: AsRef<str>,
466+
{
467+
let project_dir = project_dir.as_ref();
468+
469+
let status = subproc("autoreconf", project_dir, ["--install", "--force"]);
470+
471+
assert!(
472+
status.success(),
473+
"autoreconf({}) failed: {}",
474+
project_dir,
475+
status
476+
);
477+
}

0 commit comments

Comments
 (0)