vendor: use bindgen-cli instead of bindgen library

This commit is contained in:
Ryan Heywood 2024-03-05 22:23:47 -05:00
parent fa3fdbff2d
commit a151711d86
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
3 changed files with 145 additions and 69 deletions

View File

@ -23,6 +23,8 @@ members = [
"crates/util/keyfork-prompt", "crates/util/keyfork-prompt",
"crates/util/keyfork-slip10-test-data", "crates/util/keyfork-slip10-test-data",
"crates/util/smex", "crates/util/smex",
"vendor/v4l2-sys-mit-0.3.0",
"vendor/nettle-sys-2.3.0",
] ]
[profile.dev.package.keyfork-qrcode] [profile.dev.package.keyfork-qrcode]

View File

@ -1,6 +1,8 @@
//!
use std::fs; use std::fs;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process;
/// Like std::env::var, but informs cargo. /// Like std::env::var, but informs cargo.
/// ///
@ -40,7 +42,8 @@ struct Config {
/// Nettle version number to gate features. /// Nettle version number to gate features.
#[allow(dead_code)] #[allow(dead_code)]
fn is_version_at_least<V: AsRef<str>>(nettle_version: V, need: &[u8]) -> bool { fn is_version_at_least<V: AsRef<str>>(nettle_version: V, need: &[u8]) -> bool {
for (i, (n, component)) in need.iter() for (i, (n, component)) in need
.iter()
.zip(nettle_version.as_ref().split('.')) .zip(nettle_version.as_ref().split('.'))
.enumerate() .enumerate()
{ {
@ -53,8 +56,13 @@ fn is_version_at_least<V: AsRef<str>>(nettle_version: V, need: &[u8]) -> bool {
// Compare the next component. // Compare the next component.
} }
} else { } else {
panic!("Failed to parse the {}th component of the Nettle version \ panic!(
{:?}: {:?}", i + 1, nettle_version.as_ref(), component); "Failed to parse the {}th component of the Nettle version \
{:?}: {:?}",
i + 1,
nettle_version.as_ref(),
component
);
} }
} }
@ -64,11 +72,11 @@ fn is_version_at_least<V: AsRef<str>>(nettle_version: V, need: &[u8]) -> bool {
/// Returns whether or not the feature detection should be overridden, /// Returns whether or not the feature detection should be overridden,
/// and if so, whether the feature should be enabled. /// and if so, whether the feature should be enabled.
fn check_override(feature: &str) -> Option<bool> { fn check_override(feature: &str) -> Option<bool> {
env_var(&format!("NETTLE_HAVE_{}", feature)) env_var(format!("NETTLE_HAVE_{}", feature)).ok().map(|v| {
.ok() matches!(
.map(|v| match v.to_lowercase().as_str() { v.to_lowercase().as_str(),
"1" | "y" | "yes" | "enable" | "true" => true, "1" | "y" | "yes" | "enable" | "true"
_ => false, )
}) })
} }
@ -78,23 +86,24 @@ fn check_cc(includes: &[PathBuf], header: &str, symbol: &str) -> bool {
let wd = tempfile::tempdir()?; let wd = tempfile::tempdir()?;
let testpath = wd.path().join("test.c"); let testpath = wd.path().join("test.c");
let mut testfile = fs::File::create(&testpath)?; let mut testfile = fs::File::create(&testpath)?;
write!(testfile, "#include <nettle/{}> write!(
testfile,
"#include <nettle/{}>
int int
main() main()
{{ {{
(void) {}; (void) {};
}} }}
", header, symbol)?; ",
header, symbol
)?;
let tool = cc::Build::new() let tool = cc::Build::new()
.warnings(false) .warnings(false)
.includes(includes) .includes(includes)
.try_get_compiler()?; .try_get_compiler()?;
let output = tool.to_command() let output = tool.to_command().current_dir(&wd).arg(&testpath).output()?;
.current_dir(&wd)
.arg(&testpath)
.output()?;
Ok(output.status.success()) Ok(output.status.success())
}; };
t().unwrap_or(false) t().unwrap_or(false)
@ -103,15 +112,12 @@ main()
/// Checks whether Nettle supports Curve 448. /// Checks whether Nettle supports Curve 448.
fn check_cv448(includes: &[PathBuf]) -> bool { fn check_cv448(includes: &[PathBuf]) -> bool {
check_override("CV448") check_override("CV448")
.unwrap_or_else(|| check_cc(includes, "eddsa.h", .unwrap_or_else(|| check_cc(includes, "eddsa.h", "nettle_ed448_shake256_sign"))
"nettle_ed448_shake256_sign"))
} }
/// Checks whether Nettle supports OCB mode. /// Checks whether Nettle supports OCB mode.
fn check_ocb(includes: &[PathBuf]) -> bool { fn check_ocb(includes: &[PathBuf]) -> bool {
check_override("OCB") check_override("OCB").unwrap_or_else(|| check_cc(includes, "ocb.h", "nettle_ocb_encrypt"))
.unwrap_or_else(|| check_cc(includes, "ocb.h",
"nettle_ocb_encrypt"))
} }
#[cfg(target_env = "msvc")] #[cfg(target_env = "msvc")]
@ -128,7 +134,10 @@ fn try_vcpkg() -> Result<Config> {
} }
#[cfg(not(target_env = "msvc"))] #[cfg(not(target_env = "msvc"))]
fn try_vcpkg() -> Result<Config> { Err("not applicable")?; unreachable!() } fn try_vcpkg() -> Result<Config> {
Err("not applicable")?;
unreachable!()
}
fn try_pkg_config() -> Result<Config> { fn try_pkg_config() -> Result<Config> {
let mut nettle = Library::from(pkg_config::probe_library("nettle")?) let mut nettle = Library::from(pkg_config::probe_library("nettle")?)
@ -171,14 +180,23 @@ fn real_main() -> Result<()> {
println!("cargo:rustc-link-lib=static=gmp"); println!("cargo:rustc-link-lib=static=gmp");
} }
let out_path = Path::new(&env_var("OUT_DIR").unwrap()).join("bindings.rs"); let out_dir = PathBuf::from(env_var("OUT_DIR").unwrap());
let out_path = out_dir.join("bindings.rs");
let in_file_path = out_dir.join("bindgen-wrapper.h");
fs::copy("bindgen-wrapper.h", &in_file_path).unwrap();
let mut in_file = fs::OpenOptions::new()
.append(true)
.open(&in_file_path)
.unwrap();
in_file.write_all(b"\n").unwrap();
// Check if we have a bundled bindings.rs. // Check if we have a bundled bindings.rs.
if let Ok(bundled) = env_var(NETTLE_PREGENERATED_BINDINGS) if let Ok(bundled) = env_var(NETTLE_PREGENERATED_BINDINGS) {
{
let p = Path::new(&bundled); let p = Path::new(&bundled);
if p.exists() { if p.exists() {
fs::copy(&p, &out_path)?; fs::copy(p, &out_path)?;
println!("cargo:rerun-if-changed={:?}", p); println!("cargo:rerun-if-changed={:?}", p);
// We're done. // We're done.
@ -186,6 +204,19 @@ fn real_main() -> Result<()> {
} }
} }
#[rustfmt::skip]
let mut flags = vec![
"--blocklist-type".to_string(), "max_align_t".to_string(),
"--blocklist-function".to_string(), "strtold".to_string(),
"--blocklist-function".to_string(), "qecvt".to_string(),
"--blocklist-function".to_string(), "qfcvt".to_string(),
"--blocklist-function".to_string(), "qgcvt".to_string(),
"--blocklist-function".to_string(), "qecvt_r".to_string(),
"--blocklist-function".to_string(), "qfcvt_r".to_string(),
in_file_path.display().to_string(),
];
/*
let mut builder = bindgen::Builder::default() let mut builder = bindgen::Builder::default()
// Includes all nettle headers except mini-gmp.h // Includes all nettle headers except mini-gmp.h
.header("bindgen-wrapper.h") .header("bindgen-wrapper.h")
@ -197,25 +228,52 @@ fn real_main() -> Result<()> {
.blocklist_function("qgcvt") .blocklist_function("qgcvt")
.blocklist_function("qecvt_r") .blocklist_function("qecvt_r")
.blocklist_function("qfcvt_r") .blocklist_function("qfcvt_r")
.size_t_is_usize(true); .size_t_is_usize(true); // default: true
*/
if config.have_cv448 { if config.have_cv448 {
builder = builder.header_contents("cv448-wrapper.h", "#include <nettle/curve448.h>"); in_file.write_all(b"#include <nettle/curve448.h>\n").unwrap();
// builder = builder.header_contents("cv448-wrapper.h", "#include <nettle/curve448.h>");
} }
if config.have_ocb { if config.have_ocb {
builder = builder.header_contents("ocb-wrapper.h", "#include <nettle/ocb.h>"); in_file.write_all(b"#include <nettle/ocb.h>\n").unwrap();
// builder = builder.header_contents("ocb-wrapper.h", "#include <nettle/ocb.h>");
} }
if !config.include_paths.is_empty() {
flags.push("--".to_string());
for p in config.include_paths { for p in config.include_paths {
builder = builder.clang_arg(format!("-I{}", p.display())); flags.push("-I".to_string());
flags.push(p.display().to_string())
// builder = builder.clang_arg(format!("-I{}", p.display()));
}
} }
drop(in_file);
println!("flags: {flags:?}");
let bindings = process::Command::new("bindgen")
.args(flags)
.output()
.expect("Failed to generate bindings");
assert!(
bindings.status.success(),
"Error generating bindings: {}",
String::from_utf8_lossy(&bindings.stdout)
);
fs::write(&out_path, bindings.stdout.as_slice()).expect("Failed to write bindings");
/*
let bindings = builder.generate().unwrap(); let bindings = builder.generate().unwrap();
bindings.write_to_file(&out_path)?; bindings.write_to_file(&out_path)?;
*/
let mut s = fs::OpenOptions::new().append(true).open(out_path)?; let mut s = fs::OpenOptions::new().append(true).open(out_path)?;
writeln!(s, "\ writeln!(
s,
"\
/// Compile-time configuration. /// Compile-time configuration.
pub mod config {{ pub mod config {{
/// Cv448/Ed448 support in Nettle. /// Cv448/Ed448 support in Nettle.
@ -225,8 +283,7 @@ pub mod config {{
pub const HAVE_OCB: bool = {}; pub const HAVE_OCB: bool = {};
}} }}
", ",
config.have_cv448, config.have_cv448, config.have_ocb,
config.have_ocb,
)?; )?;
if !config.have_cv448 { if !config.have_cv448 {
@ -257,38 +314,52 @@ fn main() -> Result<()> {
} }
fn print_hints() { fn print_hints() {
eprintln!("Please make sure the necessary build dependencies are \ eprintln!(
installed.\n"); "Please make sure the necessary build dependencies are \
installed.\n"
);
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
eprintln!("If you are using MSYS2, try: eprintln!(
"If you are using MSYS2, try:
$ pacman -S mingw-w64-x86_64-{{clang,pkg-config,nettle}} libnettle-devel $ pacman -S mingw-w64-x86_64-{{clang,pkg-config,nettle}} libnettle-devel
"); "
);
} else if cfg!(target_os = "macos") { } else if cfg!(target_os = "macos") {
eprintln!("If you are using MacPorts, try: eprintln!(
"If you are using MacPorts, try:
$ sudo port install nettle pkgconfig $ sudo port install nettle pkgconfig
"); "
);
} else if cfg!(target_os = "linux") { } else if cfg!(target_os = "linux") {
eprintln!("If you are using Debian (or a derivative), try: eprintln!(
"If you are using Debian (or a derivative), try:
$ sudo apt install clang llvm pkg-config nettle-dev $ sudo apt install clang llvm pkg-config nettle-dev
"); "
);
eprintln!("If you are using Arch (or a derivative), try: eprintln!(
"If you are using Arch (or a derivative), try:
$ sudo pacman -S clang pkg-config nettle --needed $ sudo pacman -S clang pkg-config nettle --needed
"); "
);
eprintln!("If you are using Fedora (or a derivative), try: eprintln!(
"If you are using Fedora (or a derivative), try:
$ sudo dnf install clang pkg-config nettle-devel $ sudo dnf install clang pkg-config nettle-devel
"); "
);
} }
eprintln!("See https://gitlab.com/sequoia-pgp/nettle-sys#building \ eprintln!(
for more information.\n"); "See https://gitlab.com/sequoia-pgp/nettle-sys#building \
for more information.\n"
);
} }
/// Writes a log message to /tmp/l. /// Writes a log message to /tmp/l.
@ -297,8 +368,12 @@ fn print_hints() {
/// function. /// function.
#[allow(dead_code)] #[allow(dead_code)]
fn log<S: AsRef<str>>(m: S) { fn log<S: AsRef<str>>(m: S) {
writeln!(&mut fs::OpenOptions::new().append(true).open("/tmp/l").unwrap(), writeln!(
"{}", m.as_ref()).unwrap(); &mut fs::OpenOptions::new().append(true).open("/tmp/l").unwrap(),
"{}",
m.as_ref()
)
.unwrap();
} }
/// Somewhat like pkg_config::Library, but only with the parts we use. /// Somewhat like pkg_config::Library, but only with the parts we use.

View File

@ -1,16 +1,15 @@
extern crate bindgen;
use std::env; use std::env;
use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command;
fn main() { fn main() {
let bindings = bindgen::Builder::default() let bindings = Command::new("bindgen")
.header("wrapper.h") .arg("wrapper.h")
.generate() .output()
.expect("Failed to generate bindings"); .expect("Failed to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings fs::write(out_path.join("v4l2_bindings.rs"), bindings.stdout.as_slice())
.write_to_file(out_path.join("v4l2_bindings.rs"))
.expect("Failed to write bindings"); .expect("Failed to write bindings");
} }