Use a stub stdlib.h when compiling for UEFI targets

int_util.c includes stdlib.h if `_WIN32` is defined. When compiling
the UEFI targets with clang they are treated as Windows targets (e.g. if
the Rust target is x86_64-unknown-uefi, the clang target is
x86_64-unknown-windows-gnu). So stdlib.h gets included, even though we
are compilling with `-ffreestanding` and don't want stdlib.h to be
used. That file may not be present, or an incompatible version might be
installed leading to typedef redefinition errors.

The contents of stdlib.h aren't actually needed for these targets anyway
(due to `__STDC_HOSTED__` being 0), so create a minimal stdlib.h in
`build.rs` when `target_os == uefi` and add it to the include path.
This commit is contained in:
Nicholas Bishop 2022-11-16 17:52:46 -05:00 committed by Nicholas Bishop
parent 371a6856ee
commit ebaca42a41

View file

@ -98,7 +98,7 @@ mod c {
use std::collections::{BTreeMap, HashSet};
use std::env;
use std::fs::File;
use std::fs::{self, File};
use std::io::Write;
use std::path::{Path, PathBuf};
@ -190,6 +190,21 @@ mod c {
cfg.define("VISIBILITY_HIDDEN", None);
}
// int_util.c tries to include stdlib.h if `_WIN32` is defined,
// which it is when compiling UEFI targets with clang. This is
// at odds with compiling with `-ffreestanding`, as the header
// may be incompatible or not present. Create a minimal stub
// header to use instead.
if target_os == "uefi" {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let include_dir = out_dir.join("include");
if !include_dir.exists() {
fs::create_dir(&include_dir).unwrap();
}
fs::write(include_dir.join("stdlib.h"), "#include <stddef.h>").unwrap();
cfg.flag(&format!("-I{}", include_dir.to_str().unwrap()));
}
let mut sources = Sources::new();
sources.extend(&[
("__absvdi2", "absvdi2.c"),