Regenerate QEMU binding stubs only for newer versions of the nightly compiler (#2177)
* Regenerate binding stubs only for newer versions of the nightly compiler. * fmt * clippy
This commit is contained in:
parent
19087f3dab
commit
b127f0579d
@ -37,3 +37,4 @@ pkg-config = "0.3.26"
|
||||
cc = "1.0"
|
||||
regex = "1"
|
||||
rustversion = "1.0"
|
||||
rustc_version = "0.4"
|
@ -95,7 +95,7 @@ pub fn generate(
|
||||
) -> Result<Bindings, BindgenError> {
|
||||
let wrapper_h = build_dir.join("wrapper.h");
|
||||
|
||||
store_generated_content_if_different(&wrapper_h, WRAPPER_HEADER.as_bytes());
|
||||
store_generated_content_if_different(&wrapper_h, WRAPPER_HEADER.as_bytes(), None, None, false);
|
||||
|
||||
let bindings = bindgen::Builder::default()
|
||||
.derive_debug(true)
|
||||
|
@ -6,12 +6,14 @@ use std::{
|
||||
env, fs,
|
||||
fs::File,
|
||||
hash::Hasher,
|
||||
io::{Read, Seek, SeekFrom, Write},
|
||||
io::{BufRead, BufReader, Read, Seek, SeekFrom, Write},
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
ptr::addr_of_mut,
|
||||
};
|
||||
|
||||
use regex::Regex;
|
||||
use rustc_version::Version;
|
||||
use which::which;
|
||||
|
||||
mod bindings;
|
||||
@ -243,26 +245,37 @@ fn include_path(build_dir: &Path, path: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_generated_content_if_different(file_to_update: &PathBuf, fresh_content: &[u8]) {
|
||||
/// If `fresh_content` != `content_file_to_update` (the file is read directly if `content_file_to_update` is None), update the file. prefix is not considered for comparison.
|
||||
/// If a prefix is given, it will be added as the first line of the file.
|
||||
pub fn store_generated_content_if_different(
|
||||
file_to_update: &PathBuf,
|
||||
fresh_content: &[u8],
|
||||
content_file_to_update: Option<Vec<u8>>,
|
||||
first_line_prefix: Option<&str>,
|
||||
force_regeneration: bool,
|
||||
) {
|
||||
let mut must_rewrite_file = true;
|
||||
|
||||
// Check if equivalent file already exists without relying on filesystem timestamp.
|
||||
let mut file_to_check =
|
||||
if let Ok(mut wrapper_file) = File::options().read(true).write(true).open(file_to_update) {
|
||||
let mut existing_file_content = Vec::with_capacity(fresh_content.len());
|
||||
wrapper_file
|
||||
.read_to_end(existing_file_content.as_mut())
|
||||
.unwrap();
|
||||
let existing_file_content = content_file_to_update.unwrap_or_else(|| {
|
||||
let mut content = Vec::with_capacity(fresh_content.len());
|
||||
wrapper_file.read_to_end(content.as_mut()).unwrap();
|
||||
content
|
||||
});
|
||||
|
||||
let mut existing_wrapper_hasher = hash_map::DefaultHasher::new();
|
||||
existing_wrapper_hasher.write(existing_file_content.as_ref());
|
||||
if !force_regeneration {
|
||||
let mut existing_wrapper_hasher = hash_map::DefaultHasher::new();
|
||||
existing_wrapper_hasher.write(existing_file_content.as_ref());
|
||||
|
||||
let mut wrapper_h_hasher = hash_map::DefaultHasher::new();
|
||||
wrapper_h_hasher.write(fresh_content);
|
||||
let mut wrapper_h_hasher = hash_map::DefaultHasher::new();
|
||||
wrapper_h_hasher.write(fresh_content);
|
||||
|
||||
// Check if wrappers are the same
|
||||
if existing_wrapper_hasher.finish() == wrapper_h_hasher.finish() {
|
||||
must_rewrite_file = false;
|
||||
// Check if wrappers are the same
|
||||
if existing_wrapper_hasher.finish() == wrapper_h_hasher.finish() {
|
||||
must_rewrite_file = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset file cursor if it's going to be rewritten
|
||||
@ -280,6 +293,10 @@ pub fn store_generated_content_if_different(file_to_update: &PathBuf, fresh_cont
|
||||
};
|
||||
|
||||
if must_rewrite_file {
|
||||
if let Some(prefix) = first_line_prefix {
|
||||
writeln!(&file_to_check, "{prefix}").expect("Could not write prefix");
|
||||
}
|
||||
|
||||
file_to_check
|
||||
.write_all(fresh_content)
|
||||
.unwrap_or_else(|_| panic!("Unable to write in {}", file_to_update.display()));
|
||||
@ -293,12 +310,74 @@ pub fn maybe_generate_stub_bindings(
|
||||
bindings_file: &PathBuf,
|
||||
) {
|
||||
if cpu_target == "x86_64" && emulation_mode == "usermode" {
|
||||
store_generated_content_if_different(
|
||||
stub_bindings_file,
|
||||
fs::read(bindings_file)
|
||||
.expect("Could not read generated bindings file")
|
||||
.as_slice(),
|
||||
);
|
||||
let current_rustc_version =
|
||||
rustc_version::version().expect("Could not get current rustc version");
|
||||
let semver_re = Regex::new(r"/\* (.*) \*/").unwrap();
|
||||
|
||||
// We only try to store the stub if the current rustc version is strictly bigger than the one used to generate
|
||||
// the versioned stub.
|
||||
let (try_generate, force_regeneration, stub_content): (bool, bool, Option<Vec<u8>>) =
|
||||
if let Ok(stub_file) = File::open(stub_bindings_file) {
|
||||
let mut stub_rdr = BufReader::new(stub_file);
|
||||
|
||||
let mut first_line = String::new();
|
||||
let mut stub_content = Vec::<u8>::new();
|
||||
assert!(
|
||||
stub_rdr
|
||||
.read_line(&mut first_line)
|
||||
.expect("Could not read first line")
|
||||
> 0,
|
||||
"Error while reading first line."
|
||||
);
|
||||
|
||||
if let Some((_, [version_str])) = semver_re
|
||||
.captures_iter(&first_line)
|
||||
.next()
|
||||
.map(|caps| caps.extract())
|
||||
{
|
||||
// The first line matches the regex
|
||||
|
||||
if let Ok(version) = Version::parse(version_str) {
|
||||
// The first line contains a version
|
||||
|
||||
stub_rdr
|
||||
.read_to_end(&mut stub_content)
|
||||
.expect("could not read stub content");
|
||||
(current_rustc_version > version, false, Some(stub_content))
|
||||
} else {
|
||||
stub_rdr.seek(SeekFrom::Start(0)).unwrap();
|
||||
stub_rdr
|
||||
.read_to_end(&mut stub_content)
|
||||
.expect("could not read stub content");
|
||||
|
||||
(true, true, Some(stub_content))
|
||||
}
|
||||
} else {
|
||||
stub_rdr.seek(SeekFrom::Start(0)).unwrap();
|
||||
stub_rdr
|
||||
.read_to_end(&mut stub_content)
|
||||
.expect("could not read stub content");
|
||||
|
||||
(true, true, Some(stub_content))
|
||||
}
|
||||
} else {
|
||||
// No stub file stored
|
||||
(true, true, None)
|
||||
};
|
||||
|
||||
let header = format!("/* {current_rustc_version} */");
|
||||
|
||||
if try_generate {
|
||||
store_generated_content_if_different(
|
||||
stub_bindings_file,
|
||||
fs::read(bindings_file)
|
||||
.expect("Could not read generated bindings file")
|
||||
.as_slice(),
|
||||
stub_content,
|
||||
Some(header.as_str()),
|
||||
force_regeneration,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* 1.80.0-nightly */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* 1.80.0-nightly */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
pub const _STDINT_H: u32 = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user