#[cfg(feature = "nss")] mod nss { use bindgen::Builder; use serde_derive::Deserialize; use std::{
collections::HashMap,
env, fs,
path::{Path, PathBuf},
process::Command,
};
// This is the format of a single section of the configuration file. #[derive(Deserialize)] struct Bindings { /// types that are explicitly included #[serde(default)]
types: Vec<String>, /// functions that are explicitly included #[serde(default)]
functions: Vec<String>, /// variables (and `#define`s) that are explicitly included #[serde(default)]
variables: Vec<String>, /// types that should be explicitly marked as opaque #[serde(default)]
opaque: Vec<String>, /// enumerations that are turned into a module (without this, the enum is /// mapped using the default, which means that the individual values are /// formed with an underscore as <enum_type>_<enum_value_name>). #[serde(default)]
enums: Vec<String>,
/// Any item that is specifically excluded; if none of the types, functions, /// or variables fields are specified, everything defined will be mapped, /// so this can be used to limit that. #[serde(default)]
exclude: Vec<String>,
/// Whether the file is to be interpreted as C++ #[serde(default)]
cplusplus: bool,
}
// bindgen needs access to libclang. // On windows, this doesn't just work, you have to set LIBCLANG_PATH. // Rather than download the 400Mb+ files, like gecko does, let's just reuse their work. fn setup_clang() { if env::consts::OS != "windows" { return;
}
println!("rerun-if-env-changed=LIBCLANG_PATH");
println!("rerun-if-env-changed=MOZBUILD_STATE_PATH"); if env::var("LIBCLANG_PATH").is_ok() { return;
} let mozbuild_root = iflet Ok(dir) = env::var("MOZBUILD_STATE_PATH") {
PathBuf::from(dir.trim())
} else {
eprintln!("warning: Building without a gecko setup is not likely to work.");
eprintln!(" A working libclang is needed to build neqo.");
eprintln!(" Either LIBCLANG_PATH or MOZBUILD_STATE_PATH needs to be set.");
eprintln!();
eprintln!(" We recommend checking out https://github.com/mozilla/gecko-dev");
eprintln!(" Then run `./mach bootstrap` which will retrieve clang.");
eprintln!(" Make sure to export MOZBUILD_STATE_PATH when building."); return;
}; let libclang_dir = mozbuild_root.join("clang").join("lib"); if libclang_dir.is_dir() {
env::set_var("LIBCLANG_PATH", libclang_dir.to_str().unwrap());
println!("rustc-env:LIBCLANG_PATH={}", libclang_dir.to_str().unwrap());
} else {
println!("warning: LIBCLANG_PATH isn't set; maybe run ./mach bootstrap with gecko");
}
}
fn nss_dir() -> Option<PathBuf> { // Note that this returns a relative path because UNC // paths on windows cause certain tools to explode.
env::var("NSS_DIR").ok().map(|dir| { let dir = PathBuf::from(dir.trim());
assert!(dir.is_dir());
dir
})
}
fn get_bash() -> PathBuf { // When running under MOZILLABUILD, we need to make sure not to invoke // another instance of bash that might be sitting around (like WSL). match env::var("MOZILLABUILD") {
Ok(d) => PathBuf::from(d).join("msys").join("bin").join("bash.exe"),
Err(_) => PathBuf::from("bash"),
}
}
// NSS optionally builds platform-specific acceleration libraries as // separate static libraries. let accel_libs = &[ "gcm-aes-x86_c_lib", "sha-x86_c_lib", "hw-acc-crypto-avx", "hw-acc-crypto-avx2", "armv8_c_lib", "gcm-aes-arm32-neon_c_lib", "gcm-aes-aarch64_c_lib", // NOTE: The intel-gcm-* libraries are already automatically // included in freebl_static as source files.
];
// Build rules are complex, so simply check the lib directory to see if // any of the accelerator libraries were built to decide what to // include. Check different variations of the filename to handle // platform differences. for libname in accel_libs { let filename = if env::consts::OS == "windows" {
format!("{libname}.lib")
} else {
format!("lib{libname}.a")
}; if nsslibdir.join(filename).is_file() {
static_libs.push(libname);
}
}
if use_static_softoken { // Statically link pk11/softokn/freebl
static_libs.append(&mut static_softoken_libs(nsslibdir));
} else { // Use dlopen to get softokn3.so
static_libs.push("pk11wrap");
}
// Dynamic libs that aren't transitively included by NSS libs. if env::consts::OS != "windows" {
dynamic_libs.extend_from_slice(&["pthread", "dl", "c", "z"]);
} if cfg!(not(feature = "external-sqlite")) && env::consts::OS == "macos" {
dynamic_libs.push("sqlite3");
}
for lib in &static_libs {
println!("cargo:rustc-link-lib=static={}", lib);
} for lib in &dynamic_libs {
println!("cargo:rustc-link-lib=dylib={}", lib);
}
}
fn get_includes(nsstarget: &Path, nssdist: &Path) -> Vec<PathBuf> { let nsprinclude = nsstarget.join("include").join("nspr"); let nssinclude = nssdist.join("public").join("nss"); let includes = vec![nsprinclude, nssinclude]; for i in &includes {
println!("cargo:include={}", i.to_str().unwrap());
}
includes
}
fn build_bindings(base: &str, bindings: &Bindings, flags: &[String]) { let suffix = if bindings.cplusplus { ".hpp" } else { ".h" }; let header_path = PathBuf::from(BINDINGS_DIR).join(String::from(base) + suffix); let header = header_path.to_str().unwrap(); let out = PathBuf::from(env::var("OUT_DIR").unwrap()).join(String::from(base) + ".rs");
// Apply the configuration. for v in &bindings.types {
builder = builder.allowlist_type(v);
} for v in &bindings.functions {
builder = builder.allowlist_function(v);
} for v in &bindings.variables {
builder = builder.allowlist_var(v);
} for v in &bindings.exclude {
builder = builder.blocklist_item(v);
} for v in &bindings.opaque {
builder = builder.opaque_type(v);
} for v in &bindings.enums {
builder = builder.constified_enum_module(v);
}
let bindings = builder.generate().expect("unable to generate bindings");
bindings
.write_to_file(out)
.expect("couldn't write bindings");
}
// $NSS_DIR/../dist/ let nssdist = nss.parent().unwrap().join("dist");
println!("cargo:rerun-if-env-changed=NSS_TARGET"); let nsstarget = env::var("NSS_TARGET")
.unwrap_or_else(|_| fs::read_to_string(nssdist.join("latest")).unwrap()); let nsstarget = nssdist.join(nsstarget.trim());
let includes = get_includes(&nsstarget, &nssdist);
let nsslibdir = nsstarget.join("lib");
println!( "cargo:rustc-link-search=native={}",
nsslibdir.to_str().unwrap()
); if is_debug() { let use_static_softoken = true; let use_static_nspr = true;
static_link(&nsslibdir, use_static_softoken, use_static_nspr);
} else {
dynamic_link();
}
letmut flags: Vec<String> = Vec::new(); for i in includes {
flags.push(String::from("-I") + i.to_str().unwrap());
}
flags
}
fn pkg_config() -> Vec<String> { let modversion = Command::new("pkg-config")
.args(&["--modversion", "nss"])
.output()
.expect("pkg-config reports NSS as absent")
.stdout; let modversion_str = String::from_utf8(modversion).expect("non-UTF8 from pkg-config"); letmut v = modversion_str.split('.');
assert_eq!(
v.next(),
Some("3"), "NSS version 3.62 or higher is needed (or set $NSS_DIR)"
); iflet Some(minor) = v.next() { let minor = minor
.trim_end()
.parse::<u32>()
.expect("NSS minor version is not a number");
assert!(
minor >= 62, "NSS version 3.62 or higher is needed (or set $NSS_DIR)",
);
}
let cfg = Command::new("pkg-config")
.args(&["--cflags", "--libs", "nss"])
.output()
.expect("NSS flags not returned by pkg-config")
.stdout; let cfg_str = String::from_utf8(cfg).expect("non-UTF8 from pkg-config");
letmut flags: Vec<String> = Vec::new(); for f in cfg_str.split(' ') { iflet Some(include) = f.strip_prefix("-I") {
flags.push(String::from(f));
println!("cargo:include={}", include);
} elseiflet Some(path) = f.strip_prefix("-L") {
println!("cargo:rustc-link-search=native={}", path);
} elseiflet Some(lib) = f.strip_prefix("-l") {
println!("cargo:rustc-link-lib=dylib={}", lib);
} else {
println!("Warning: Unknown flag from pkg-config: {}", f);
}
}
flags
}
#[cfg(feature = "gecko")] fn setup_for_gecko() -> Vec<String> { use mozbuild::TOPOBJDIR;
letmut flags: Vec<String> = Vec::new();
let fold_libs = mozbuild::config::MOZ_FOLD_LIBS; let libs = if fold_libs {
vec!["nss3"]
} else {
vec!["nssutil3", "nss3", "ssl3", "plds4", "plc4", "nspr4"]
};
for lib in &libs {
println!("cargo:rustc-link-lib=dylib={}", lib);
}
#[cfg(feature = "app-svc")] fn setup_for_app_svc() -> Vec<String> { // Locate the NSS libraries that application_services is using. // NOTE: This directory has a slightly different layout than then normal // 'dist' directory that NSS builds output. let nss_dir = nss_dir().expect("NSS_DIR env must be set for app_svc builds"); if !nss_dir.exists() {
eprintln!( "NSS_DIR path (obtained via `env`) does not exist: {}",
nss_dir.display()
);
panic!("It looks like NSS is not built. Please run `libs/verify-[platform]-environment.sh` in application-services first!");
}
let lib_dir = nss_dir.join("lib");
println!( "cargo:rustc-link-search=native={}",
lib_dir.to_string_lossy()
);
// For app_svc builds, we use static linking of NSS. let use_static_softoken = true; let use_static_nspr = true;
static_link(&lib_dir, use_static_softoken, use_static_nspr);
let include_dir = nss_dir.join("include");
println!("cargo:include={}", include_dir.to_string_lossy());
let config_file = PathBuf::from(BINDINGS_DIR).join(BINDINGS_CONFIG);
println!("cargo:rerun-if-changed={}", config_file.to_str().unwrap()); let config = fs::read_to_string(config_file).expect("unable to read binding configuration"); let config: HashMap<String, Bindings> = ::toml::from_str(&config).unwrap();
for (k, v) in &config {
build_bindings(k, v, &flags[..]);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.