1307 lines
41 KiB
Rust
1307 lines
41 KiB
Rust
// Copyright (c) 2022, Google Inc.
|
|
// SPDX-License-Identifier: ISC
|
|
// Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0 OR ISC
|
|
|
|
// Needed until MSRV >= 1.70
|
|
#![allow(clippy::unnecessary_map_or)]
|
|
#![allow(clippy::ref_option)]
|
|
// Clippy can only be run on nightly toolchain
|
|
#![cfg_attr(clippy, feature(custom_inner_attributes))]
|
|
#![cfg_attr(clippy, clippy::msrv = "1.77")]
|
|
|
|
use std::ffi::{OsStr, OsString};
|
|
use std::fmt::Debug;
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::Command;
|
|
use std::{env, fmt};
|
|
|
|
use cc_builder::CcBuilder;
|
|
use cmake_builder::CmakeBuilder;
|
|
|
|
// These should generally match those found in aws-lc/include/openssl/opensslconf.h
|
|
const OSSL_CONF_DEFINES: &[&str] = &[
|
|
"OPENSSL_NO_ASYNC",
|
|
"OPENSSL_NO_BF",
|
|
"OPENSSL_NO_BLAKE2",
|
|
"OPENSSL_NO_BUF_FREELISTS",
|
|
"OPENSSL_NO_CAMELLIA",
|
|
"OPENSSL_NO_CAPIENG",
|
|
"OPENSSL_NO_CAST",
|
|
"OPENSSL_NO_CMS",
|
|
"OPENSSL_NO_COMP",
|
|
"OPENSSL_NO_CRYPTO_MDEBUG",
|
|
"OPENSSL_NO_CT",
|
|
"OPENSSL_NO_DANE",
|
|
"OPENSSL_NO_DEPRECATED",
|
|
"OPENSSL_NO_DGRAM",
|
|
"OPENSSL_NO_DYNAMIC_ENGINE",
|
|
"OPENSSL_NO_EC_NISTP_64_GCC_128",
|
|
"OPENSSL_NO_EC2M",
|
|
"OPENSSL_NO_EGD",
|
|
"OPENSSL_NO_ENGINE",
|
|
"OPENSSL_NO_GMP",
|
|
"OPENSSL_NO_GOST",
|
|
"OPENSSL_NO_HEARTBEATS",
|
|
"OPENSSL_NO_HW",
|
|
"OPENSSL_NO_IDEA",
|
|
"OPENSSL_NO_JPAKE",
|
|
"OPENSSL_NO_KRB5",
|
|
"OPENSSL_NO_MD2",
|
|
"OPENSSL_NO_MDC2",
|
|
"OPENSSL_NO_OCB",
|
|
"OPENSSL_NO_RC2",
|
|
"OPENSSL_NO_RC5",
|
|
"OPENSSL_NO_RFC3779",
|
|
"OPENSSL_NO_RIPEMD",
|
|
"OPENSSL_NO_RMD160",
|
|
"OPENSSL_NO_SCTP",
|
|
"OPENSSL_NO_SEED",
|
|
"OPENSSL_NO_SM2",
|
|
"OPENSSL_NO_SM3",
|
|
"OPENSSL_NO_SM4",
|
|
"OPENSSL_NO_SRP",
|
|
"OPENSSL_NO_SSL_TRACE",
|
|
"OPENSSL_NO_SSL2",
|
|
"OPENSSL_NO_SSL3",
|
|
"OPENSSL_NO_SSL3_METHOD",
|
|
"OPENSSL_NO_STATIC_ENGINE",
|
|
"OPENSSL_NO_STORE",
|
|
"OPENSSL_NO_TS",
|
|
"OPENSSL_NO_WHIRLPOOL",
|
|
];
|
|
|
|
mod cc_builder;
|
|
mod cmake_builder;
|
|
mod nasm_builder;
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
mod sys_bindgen;
|
|
|
|
pub(crate) struct EnvGuard {
|
|
key: String,
|
|
original_value: Option<String>,
|
|
}
|
|
|
|
impl EnvGuard {
|
|
fn new<T: AsRef<OsStr>>(key: &str, new_value: T) -> Self {
|
|
let original_value = env::var(key).ok();
|
|
env::set_var(key, new_value);
|
|
Self {
|
|
key: key.to_string(),
|
|
original_value,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for EnvGuard {
|
|
fn drop(&mut self) {
|
|
if let Some(ref value) = self.original_value {
|
|
env::set_var(&self.key, value);
|
|
} else {
|
|
env::remove_var(&self.key);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn is_fips_build() -> bool {
|
|
is_fips_crate() || cfg!(feature = "fips")
|
|
}
|
|
|
|
fn is_fips_crate() -> bool {
|
|
crate_name().contains("fips")
|
|
}
|
|
|
|
fn is_all_bindings() -> bool {
|
|
is_fips_crate() || env::var("CARGO_FEATURE_ALL_BINDINGS").is_ok()
|
|
}
|
|
|
|
fn is_prebuilt_nasm() -> bool {
|
|
!is_fips_build() && env::var("CARGO_FEATURE_PREBUILT_NASM").is_ok()
|
|
}
|
|
|
|
fn is_disable_prebuilt_nasm() -> bool {
|
|
is_fips_build() || env::var("CARGO_FEATURE_DISABLE_PREBUILT_NASM").is_ok()
|
|
}
|
|
|
|
pub(crate) fn get_aws_lc_include_path(manifest_dir: &Path) -> PathBuf {
|
|
manifest_dir.join("aws-lc").join("include")
|
|
}
|
|
|
|
pub(crate) fn get_rust_include_path(manifest_dir: &Path) -> PathBuf {
|
|
manifest_dir.join("include")
|
|
}
|
|
|
|
pub(crate) fn get_generated_include_path(manifest_dir: &Path) -> PathBuf {
|
|
manifest_dir.join("generated-include")
|
|
}
|
|
|
|
#[allow(unknown_lints)]
|
|
#[allow(static_mut_refs)]
|
|
pub(crate) fn get_env_includes_path() -> Option<Vec<PathBuf>> {
|
|
unsafe { SYS_INCLUDES.clone() }
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
enum OutputLib {
|
|
Crypto,
|
|
Ssl,
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
enum OutputLibType {
|
|
Static,
|
|
Dynamic,
|
|
}
|
|
|
|
fn cargo_env<N: AsRef<str>>(name: N) -> String {
|
|
let name = name.as_ref();
|
|
env::var(name).unwrap_or_else(|_| panic!("missing env var {name:?}"))
|
|
}
|
|
|
|
fn env_name_for_target<K: AsRef<OsStr>>(env_var: K) -> String {
|
|
let target = target().to_lowercase();
|
|
let target = target.replace('-', "_");
|
|
format!("{}_{target}", env_var.as_ref().to_str().unwrap())
|
|
}
|
|
|
|
// "CFLAGS" =>
|
|
// "SYS_CFLAGS_aarch64_unknown_linux_gnu" OR "SYS_CFLAGS"
|
|
// OR "CFLAGS_aarch64_unknown_linux_gnu" OR "CFLAGS"
|
|
fn optional_env_optional_crate_target<N: AsRef<str>>(name: N) -> Option<String> {
|
|
let name = name.as_ref();
|
|
optional_env_crate_target(name).or(optional_env_target(name))
|
|
}
|
|
|
|
// "EFFECTIVE_TARGET" => "SYS_EFFECTIVE_TARGET_aarch64_unknown_linux_gnu" + "SYS_EFFECTIVE_TARGET"
|
|
fn optional_env_crate_target<N: AsRef<str>>(name: N) -> Option<String> {
|
|
let name = name.as_ref();
|
|
let crate_name = crate_name().to_uppercase().replace('-', "_");
|
|
let name_for_crate = format!("{crate_name}_{name}");
|
|
let name_for_crate_target = env_name_for_target(&name_for_crate);
|
|
optional_env(name_for_crate_target).or(optional_env(name_for_crate))
|
|
}
|
|
|
|
fn optional_env_target<N: AsRef<str>>(name: N) -> Option<String> {
|
|
let name_for_target = env_name_for_target(name.as_ref());
|
|
optional_env(name_for_target).or(optional_env(name))
|
|
}
|
|
|
|
fn optional_env<N: AsRef<str>>(name: N) -> Option<String> {
|
|
let name = name.as_ref();
|
|
println!("cargo:rerun-if-env-changed={name}");
|
|
if let Ok(value) = env::var(name) {
|
|
emit_warning(format!("Environment Variable found '{name}': '{}'", &value));
|
|
return Some(value);
|
|
}
|
|
None
|
|
}
|
|
|
|
fn set_env_for_target<K, V>(env_var: K, value: V)
|
|
where
|
|
K: AsRef<OsStr>,
|
|
V: AsRef<OsStr>,
|
|
{
|
|
let env_var = env_name_for_target(env_var);
|
|
#[allow(unused_unsafe)]
|
|
unsafe {
|
|
env::set_var(&env_var, &value);
|
|
}
|
|
emit_warning(format!(
|
|
"Setting {env_var}: {}",
|
|
value.as_ref().to_str().unwrap()
|
|
));
|
|
}
|
|
|
|
fn set_env<K, V>(env_var: K, value: V)
|
|
where
|
|
K: AsRef<OsStr>,
|
|
V: AsRef<OsStr>,
|
|
{
|
|
#[allow(unused_unsafe)]
|
|
unsafe {
|
|
env::set_var(&env_var, &value);
|
|
}
|
|
emit_warning(format!(
|
|
"Setting {}: {}",
|
|
env_var.as_ref().to_str().unwrap(),
|
|
value.as_ref().to_str().unwrap()
|
|
));
|
|
}
|
|
|
|
fn env_var_to_bool(name: &str) -> Option<bool> {
|
|
if let Some(value) = optional_env(name) {
|
|
return parse_to_bool(&value);
|
|
}
|
|
None
|
|
}
|
|
|
|
fn env_crate_var_to_bool(name: &str) -> Option<bool> {
|
|
if let Some(value) = optional_env_crate_target(name) {
|
|
return parse_to_bool(&value);
|
|
}
|
|
None
|
|
}
|
|
|
|
fn parse_to_bool(env_var_value: &str) -> Option<bool> {
|
|
let env_var_value = env_var_value.to_lowercase();
|
|
if env_var_value.starts_with('0')
|
|
|| env_var_value.starts_with('n')
|
|
|| env_var_value.starts_with("off")
|
|
|| env_var_value.starts_with('f')
|
|
{
|
|
emit_warning(format!("Value: {} is false.", &env_var_value));
|
|
return Some(false);
|
|
}
|
|
if env_var_value.starts_with(|c: char| c.is_ascii_digit())
|
|
|| env_var_value.starts_with('y')
|
|
|| env_var_value.starts_with("on")
|
|
|| env_var_value.starts_with('t')
|
|
{
|
|
emit_warning(format!("Value: {} is true.", &env_var_value));
|
|
return Some(true);
|
|
}
|
|
None
|
|
}
|
|
|
|
impl Default for OutputLibType {
|
|
fn default() -> Self {
|
|
if let Some(stc_lib) = env_crate_var_to_bool("STATIC") {
|
|
if stc_lib {
|
|
OutputLibType::Static
|
|
} else {
|
|
OutputLibType::Dynamic
|
|
}
|
|
} else if !is_fips_build()
|
|
|| (is_fips_build()
|
|
&& (target_os() == "linux" || target_os().ends_with("bsd"))
|
|
&& (target_arch() == "x86_64" || target_arch() == "aarch64"))
|
|
{
|
|
OutputLibType::Static
|
|
} else {
|
|
OutputLibType::Dynamic
|
|
}
|
|
}
|
|
}
|
|
|
|
impl OutputLibType {
|
|
fn rust_lib_type(&self) -> &str {
|
|
match self {
|
|
OutputLibType::Static => "static",
|
|
OutputLibType::Dynamic => "dylib",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl OutputLib {
|
|
fn libname(self, prefix: &Option<String>) -> String {
|
|
let name = match self {
|
|
OutputLib::Crypto => "crypto",
|
|
OutputLib::Ssl => "ssl",
|
|
};
|
|
if let Some(prefix) = prefix {
|
|
format!("{prefix}_{name}")
|
|
} else {
|
|
name.to_string()
|
|
}
|
|
}
|
|
}
|
|
|
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
fn prefix_string() -> String {
|
|
format!(
|
|
"aws_lc{}_{}",
|
|
if is_fips_crate() { "_fips" } else { "" },
|
|
VERSION.to_string().replace('.', "_")
|
|
)
|
|
}
|
|
|
|
fn target_has_prefixed_symbols() -> bool {
|
|
target_vendor() == "apple" || (target_arch() == "x86" && target_os() == "windows")
|
|
}
|
|
|
|
fn is_cranelift_backend() -> bool {
|
|
// CARGO_ENCODED_RUSTFLAGS contains flags separated by 0x1f (ASCII Unit Separator)
|
|
if let Some(rustflags) = optional_env("CARGO_ENCODED_RUSTFLAGS") {
|
|
for flag in rustflags.split('\x1f') {
|
|
if flag.contains("codegen-backend") && flag.contains("cranelift") {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
false
|
|
}
|
|
|
|
fn target_chokes_on_u1() -> bool {
|
|
target_arch() == "mips" || target_arch() == "mips64" || is_cranelift_backend()
|
|
}
|
|
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
fn target_platform_prefix(name: &str) -> String {
|
|
if is_all_bindings() {
|
|
format!("{}_{}", effective_target().replace('-', "_"), name)
|
|
} else if target_has_prefixed_symbols() {
|
|
format!("universal_prefixed_{}", name.replace('-', "_"))
|
|
} else {
|
|
format!("universal_{}", name.replace('-', "_"))
|
|
}
|
|
}
|
|
|
|
pub(crate) struct TestCommandResult {
|
|
#[allow(dead_code)]
|
|
stderr: Box<str>,
|
|
#[allow(dead_code)]
|
|
stdout: Box<str>,
|
|
executed: bool,
|
|
status: bool,
|
|
}
|
|
|
|
const MAX_CMD_OUTPUT_SIZE: usize = 1 << 15;
|
|
fn execute_command(executable: &OsStr, args: &[&OsStr]) -> TestCommandResult {
|
|
if let Ok(mut result) = Command::new(executable).args(args).output() {
|
|
result.stderr.truncate(MAX_CMD_OUTPUT_SIZE);
|
|
let stderr = String::from_utf8(result.stderr)
|
|
.unwrap_or_default()
|
|
.into_boxed_str();
|
|
result.stdout.truncate(MAX_CMD_OUTPUT_SIZE);
|
|
let stdout = String::from_utf8(result.stdout)
|
|
.unwrap_or_default()
|
|
.into_boxed_str();
|
|
return TestCommandResult {
|
|
stderr,
|
|
stdout,
|
|
executed: true,
|
|
status: result.status.success(),
|
|
};
|
|
}
|
|
TestCommandResult {
|
|
stderr: String::new().into_boxed_str(),
|
|
stdout: String::new().into_boxed_str(),
|
|
executed: false,
|
|
status: false,
|
|
}
|
|
}
|
|
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
fn generate_bindings(manifest_dir: &Path, prefix: &Option<String>, bindings_path: &PathBuf) {
|
|
let options = BindingOptions {
|
|
build_prefix: prefix.clone(),
|
|
include_ssl: cfg!(feature = "ssl"),
|
|
disable_prelude: true,
|
|
};
|
|
|
|
let bindings = sys_bindgen::generate_bindings(manifest_dir, &options);
|
|
|
|
bindings
|
|
.write(Box::new(std::fs::File::create(bindings_path).unwrap()))
|
|
.expect("written bindings");
|
|
}
|
|
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
fn generate_src_bindings(manifest_dir: &Path, prefix: &Option<String>, src_bindings_path: &Path) {
|
|
sys_bindgen::generate_bindings(
|
|
manifest_dir,
|
|
&BindingOptions {
|
|
build_prefix: prefix.clone(),
|
|
include_ssl: false,
|
|
..Default::default()
|
|
},
|
|
)
|
|
.write_to_file(src_bindings_path)
|
|
.expect("write bindings");
|
|
}
|
|
|
|
fn emit_rustc_cfg(cfg: &str) {
|
|
let cfg = cfg.replace('-', "_");
|
|
emit_warning(format!("Emitting configuration: cargo:rustc-cfg={cfg}"));
|
|
println!("cargo:rustc-cfg={cfg}");
|
|
}
|
|
|
|
fn emit_warning<T: AsRef<str>>(message: T) {
|
|
println!("cargo:warning={}", message.as_ref());
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn target_family() -> String {
|
|
cargo_env("CARGO_CFG_TARGET_FAMILY")
|
|
}
|
|
|
|
fn target_os() -> String {
|
|
cargo_env("CARGO_CFG_TARGET_OS")
|
|
}
|
|
|
|
fn target_arch() -> String {
|
|
cargo_env("CARGO_CFG_TARGET_ARCH")
|
|
}
|
|
|
|
#[allow(unused)]
|
|
fn target_env() -> String {
|
|
cargo_env("CARGO_CFG_TARGET_ENV")
|
|
}
|
|
|
|
#[allow(unused)]
|
|
fn target_vendor() -> String {
|
|
cargo_env("CARGO_CFG_TARGET_VENDOR")
|
|
}
|
|
|
|
fn target() -> String {
|
|
cargo_env("TARGET")
|
|
}
|
|
|
|
fn crate_name() -> String {
|
|
cargo_env("CARGO_PKG_NAME")
|
|
}
|
|
|
|
fn effective_target() -> String {
|
|
#[allow(unknown_lints)]
|
|
#[allow(static_mut_refs)]
|
|
unsafe {
|
|
if !SYS_EFFECTIVE_TARGET.is_empty() {
|
|
return SYS_EFFECTIVE_TARGET.clone();
|
|
}
|
|
}
|
|
let target = target();
|
|
match target.as_str() {
|
|
"x86_64-alpine-linux-musl" => "x86_64-unknown-linux-musl".to_string(),
|
|
"aarch64-alpine-linux-musl" => "aarch64-unknown-linux-musl".to_string(),
|
|
_ => target,
|
|
}
|
|
}
|
|
|
|
#[allow(unused)]
|
|
fn target_underscored() -> String {
|
|
effective_target().replace('-', "_")
|
|
}
|
|
|
|
fn out_dir() -> PathBuf {
|
|
PathBuf::from(cargo_env("OUT_DIR"))
|
|
}
|
|
|
|
fn current_dir() -> PathBuf {
|
|
std::env::current_dir().unwrap()
|
|
}
|
|
|
|
fn get_builder(prefix: &Option<String>, manifest_dir: &Path, out_dir: &Path) -> Box<dyn Builder> {
|
|
let cmake_builder_builder = || {
|
|
Box::new(CmakeBuilder::new(
|
|
manifest_dir.to_path_buf(),
|
|
out_dir.to_path_buf(),
|
|
prefix.clone(),
|
|
OutputLibType::default(),
|
|
))
|
|
};
|
|
|
|
if is_fips_build() {
|
|
return cmake_builder_builder();
|
|
}
|
|
|
|
let cc_builder_builder = || {
|
|
Box::new(CcBuilder::new(
|
|
manifest_dir.to_path_buf(),
|
|
out_dir.to_path_buf(),
|
|
prefix.clone(),
|
|
OutputLibType::default(),
|
|
))
|
|
};
|
|
|
|
if let Some(val) = is_cmake_builder() {
|
|
let builder: Box<dyn Builder> = if val {
|
|
cmake_builder_builder()
|
|
} else {
|
|
cc_builder_builder()
|
|
};
|
|
builder.check_dependencies().unwrap();
|
|
return builder;
|
|
} else if is_no_asm() {
|
|
let builder = cmake_builder_builder();
|
|
builder.check_dependencies().unwrap();
|
|
return builder;
|
|
} else if !is_bindgen_required() {
|
|
let cc_builder = cc_builder_builder();
|
|
if cc_builder.check_dependencies().is_ok() {
|
|
return cc_builder;
|
|
}
|
|
}
|
|
let cmake_builder = cmake_builder_builder();
|
|
cmake_builder.check_dependencies().unwrap();
|
|
cmake_builder
|
|
}
|
|
|
|
trait Builder {
|
|
fn check_dependencies(&self) -> Result<(), String>;
|
|
fn build(&self) -> Result<(), String>;
|
|
fn name(&self) -> &str;
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub(crate) enum CStdRequested {
|
|
C99,
|
|
C11,
|
|
None,
|
|
}
|
|
|
|
impl CStdRequested {
|
|
fn from_env() -> Self {
|
|
if let Some(val) = optional_env_crate_target("C_STD") {
|
|
let cstd = match val.as_str() {
|
|
"99" => CStdRequested::C99,
|
|
"11" => CStdRequested::C11,
|
|
_ => CStdRequested::None,
|
|
};
|
|
emit_warning(format!("SYS_C_STD environment variable set: {cstd:?}"));
|
|
return cstd;
|
|
}
|
|
CStdRequested::None
|
|
}
|
|
}
|
|
|
|
static mut PREGENERATED: bool = false;
|
|
static mut SYS_NO_PREFIX: bool = false;
|
|
static mut SYS_PREGENERATING_BINDINGS: bool = false;
|
|
static mut SYS_EXTERNAL_BINDGEN: Option<bool> = None;
|
|
static mut SYS_NO_ASM: bool = false;
|
|
static mut SYS_PREBUILT_NASM: Option<bool> = None;
|
|
static mut SYS_CMAKE_BUILDER: Option<bool> = None;
|
|
static mut SYS_NO_PREGENERATED_SRC: bool = false;
|
|
static mut SYS_EFFECTIVE_TARGET: String = String::new();
|
|
static mut SYS_NO_JITTER_ENTROPY: Option<bool> = None;
|
|
static mut SYS_NO_U1_BINDINGS: Option<bool> = None;
|
|
static mut SYS_INCLUDES: Option<Vec<PathBuf>> = None;
|
|
|
|
static mut SYS_C_STD: CStdRequested = CStdRequested::None;
|
|
|
|
fn initialize() {
|
|
unsafe {
|
|
SYS_NO_PREFIX = env_crate_var_to_bool("NO_PREFIX").unwrap_or(false);
|
|
SYS_PREGENERATING_BINDINGS =
|
|
env_crate_var_to_bool("PREGENERATING_BINDINGS").unwrap_or(false);
|
|
SYS_EXTERNAL_BINDGEN = env_crate_var_to_bool("EXTERNAL_BINDGEN");
|
|
SYS_NO_ASM = env_crate_var_to_bool("NO_ASM").unwrap_or(false);
|
|
SYS_PREBUILT_NASM = env_crate_var_to_bool("PREBUILT_NASM");
|
|
SYS_C_STD = CStdRequested::from_env();
|
|
SYS_CMAKE_BUILDER = env_crate_var_to_bool("CMAKE_BUILDER");
|
|
SYS_NO_PREGENERATED_SRC = env_crate_var_to_bool("NO_PREGENERATED_SRC").unwrap_or(false);
|
|
SYS_EFFECTIVE_TARGET = optional_env_crate_target("EFFECTIVE_TARGET").unwrap_or_default();
|
|
SYS_NO_JITTER_ENTROPY = env_crate_var_to_bool("NO_JITTER_ENTROPY");
|
|
SYS_NO_U1_BINDINGS = env_crate_var_to_bool("NO_U1_BINDINGS");
|
|
SYS_INCLUDES =
|
|
optional_env_crate_target("INCLUDES").map(|v| std::env::split_paths(&v).collect());
|
|
}
|
|
|
|
assert!(
|
|
!is_fips_crate() || is_fips_build(),
|
|
"aws-lc-fips-sys requires 'fips' feature to be enabled.",
|
|
);
|
|
|
|
if !is_external_bindgen_requested().unwrap_or(false)
|
|
&& (is_pregenerating_bindings() || !has_bindgen_feature())
|
|
&& !cfg!(feature = "ssl")
|
|
{
|
|
if is_all_bindings() {
|
|
assert!(
|
|
use_no_u1_bindings() != Some(true),
|
|
"Bindgen currently cannot generate prefixed bindings w/o the \\x01 prefix.",
|
|
);
|
|
let target = effective_target();
|
|
let supported_platform = match (is_fips_crate(), target.as_str()) {
|
|
(
|
|
_,
|
|
"aarch64-apple-darwin"
|
|
| "aarch64-unknown-linux-gnu"
|
|
| "aarch64-unknown-linux-musl"
|
|
| "x86_64-apple-darwin"
|
|
| "x86_64-unknown-linux-gnu"
|
|
| "x86_64-unknown-linux-musl",
|
|
)
|
|
| (
|
|
false,
|
|
"aarch64-linux-android"
|
|
| "aarch64-pc-windows-msvc"
|
|
| "i686-pc-windows-msvc"
|
|
| "i686-unknown-linux-gnu"
|
|
| "riscv64gc-unknown-linux-gnu"
|
|
| "x86_64-pc-windows-gnu"
|
|
| "x86_64-pc-windows-msvc",
|
|
) => Some(target),
|
|
_ => None,
|
|
};
|
|
if let Some(platform) = supported_platform {
|
|
emit_rustc_cfg(platform.as_str());
|
|
unsafe {
|
|
PREGENERATED = true;
|
|
}
|
|
}
|
|
} else if !is_fips_crate() {
|
|
if use_no_u1_bindings() == Some(true)
|
|
|| (target_chokes_on_u1() && use_no_u1_bindings().is_none())
|
|
{
|
|
if is_cranelift_backend() {
|
|
emit_warning(
|
|
"Cranelift codegen backend detected. Using universal_no_u1 bindings.",
|
|
);
|
|
}
|
|
if target_has_prefixed_symbols() {
|
|
emit_rustc_cfg("universal-no-u1-prefixed");
|
|
} else {
|
|
emit_rustc_cfg("universal-no-u1");
|
|
}
|
|
} else if target_has_prefixed_symbols() {
|
|
emit_rustc_cfg("universal-prefixed");
|
|
} else {
|
|
emit_rustc_cfg("universal");
|
|
}
|
|
unsafe {
|
|
PREGENERATED = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn is_bindgen_required() -> bool {
|
|
is_no_prefix()
|
|
|| is_pregenerating_bindings()
|
|
|| is_external_bindgen_requested().unwrap_or(false)
|
|
|| has_bindgen_feature()
|
|
|| !has_pregenerated()
|
|
}
|
|
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
fn internal_bindgen_supported() -> bool {
|
|
let cv = bindgen::clang_version();
|
|
emit_warning(format!("Clang version: {}", cv.full));
|
|
true
|
|
}
|
|
|
|
fn is_no_prefix() -> bool {
|
|
unsafe { SYS_NO_PREFIX }
|
|
}
|
|
|
|
fn is_pregenerating_bindings() -> bool {
|
|
unsafe { SYS_PREGENERATING_BINDINGS }
|
|
}
|
|
|
|
fn is_external_bindgen_requested() -> Option<bool> {
|
|
unsafe { SYS_EXTERNAL_BINDGEN }
|
|
}
|
|
|
|
fn is_no_asm() -> bool {
|
|
unsafe { SYS_NO_ASM }
|
|
}
|
|
|
|
fn is_cmake_builder() -> Option<bool> {
|
|
if is_no_pregenerated_src() {
|
|
Some(true)
|
|
} else {
|
|
unsafe { SYS_CMAKE_BUILDER }
|
|
}
|
|
}
|
|
|
|
fn is_no_pregenerated_src() -> bool {
|
|
unsafe { SYS_NO_PREGENERATED_SRC }
|
|
}
|
|
|
|
fn disable_jitter_entropy() -> Option<bool> {
|
|
unsafe { SYS_NO_JITTER_ENTROPY }
|
|
}
|
|
|
|
fn use_no_u1_bindings() -> Option<bool> {
|
|
unsafe { SYS_NO_U1_BINDINGS }
|
|
}
|
|
|
|
fn get_crate_cc() -> Option<String> {
|
|
optional_env_optional_crate_target("TARGET_CC").or(optional_env_optional_crate_target("CC"))
|
|
}
|
|
|
|
fn get_crate_cxx() -> Option<String> {
|
|
optional_env_optional_crate_target("TARGET_CXX").or(optional_env_optional_crate_target("CXX"))
|
|
}
|
|
|
|
fn get_crate_cflags() -> Option<String> {
|
|
optional_env_optional_crate_target("TARGET_CFLAGS")
|
|
.or(optional_env_optional_crate_target("CFLAGS"))
|
|
}
|
|
|
|
fn use_prebuilt_nasm() -> bool {
|
|
target_os() == "windows"
|
|
&& target_arch() == "x86_64"
|
|
&& !is_no_asm()
|
|
&& !test_nasm_command() // NASM not found in environment
|
|
&& Some(false) != allow_prebuilt_nasm() // not prevented by environment
|
|
&& !is_disable_prebuilt_nasm() // not prevented by feature
|
|
// permitted by environment or by feature
|
|
&& (Some(true) == allow_prebuilt_nasm() || is_prebuilt_nasm())
|
|
}
|
|
|
|
fn allow_prebuilt_nasm() -> Option<bool> {
|
|
unsafe { SYS_PREBUILT_NASM }
|
|
}
|
|
|
|
fn requested_c_std() -> CStdRequested {
|
|
unsafe { SYS_C_STD }
|
|
}
|
|
|
|
fn has_bindgen_feature() -> bool {
|
|
cfg!(feature = "bindgen")
|
|
}
|
|
|
|
fn has_pregenerated() -> bool {
|
|
unsafe { PREGENERATED }
|
|
}
|
|
|
|
fn test_nasm_command() -> bool {
|
|
let status = execute_command("nasm".as_ref(), &["-version".as_ref()]).status;
|
|
if !status {
|
|
emit_warning("NASM command not found or failed to execute.");
|
|
}
|
|
status
|
|
}
|
|
|
|
fn test_clang_cl_command() -> bool {
|
|
execute_command("clang-cl".as_ref(), &["--version".as_ref()]).status
|
|
}
|
|
|
|
fn prepare_cargo_cfg() {
|
|
if cfg!(clippy) {
|
|
println!("cargo:rustc-check-cfg=cfg(use_bindgen_pregenerated)");
|
|
println!("cargo:rustc-check-cfg=cfg(aarch64_linux_android)");
|
|
println!("cargo:rustc-check-cfg=cfg(aarch64_apple_darwin)");
|
|
println!("cargo:rustc-check-cfg=cfg(aarch64_pc_windows_msvc)");
|
|
println!("cargo:rustc-check-cfg=cfg(aarch64_unknown_linux_gnu)");
|
|
println!("cargo:rustc-check-cfg=cfg(aarch64_unknown_linux_musl)");
|
|
println!("cargo:rustc-check-cfg=cfg(cpu_jitter_entropy)");
|
|
println!("cargo:rustc-check-cfg=cfg(i686_pc_windows_msvc)");
|
|
println!("cargo:rustc-check-cfg=cfg(i686_unknown_linux_gnu)");
|
|
println!("cargo:rustc-check-cfg=cfg(riscv64gc_unknown_linux_gnu)");
|
|
println!("cargo:rustc-check-cfg=cfg(x86_64_apple_darwin)");
|
|
println!("cargo:rustc-check-cfg=cfg(x86_64_pc_windows_gnu)");
|
|
println!("cargo:rustc-check-cfg=cfg(x86_64_pc_windows_msvc)");
|
|
println!("cargo:rustc-check-cfg=cfg(x86_64_unknown_linux_gnu)");
|
|
println!("cargo:rustc-check-cfg=cfg(x86_64_unknown_linux_musl)");
|
|
println!("cargo:rustc-check-cfg=cfg(universal)");
|
|
println!("cargo:rustc-check-cfg=cfg(universal_no_u1)");
|
|
println!("cargo:rustc-check-cfg=cfg(universal_no_u1_prefixed)");
|
|
println!("cargo:rustc-check-cfg=cfg(universal_prefixed)");
|
|
}
|
|
}
|
|
|
|
fn is_crt_static() -> bool {
|
|
let features = cargo_env("CARGO_CFG_TARGET_FEATURE");
|
|
features.contains("crt-static")
|
|
}
|
|
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
fn handle_bindgen(manifest_dir: &Path, prefix: &Option<String>) -> bool {
|
|
if internal_bindgen_supported() && !is_external_bindgen_requested().unwrap_or(false) {
|
|
emit_warning(format!(
|
|
"Generating bindings - internal bindgen. Platform: {}",
|
|
effective_target()
|
|
));
|
|
let gen_bindings_path = out_dir().join("bindings.rs");
|
|
generate_bindings(manifest_dir, prefix, &gen_bindings_path);
|
|
emit_rustc_cfg("use_bindgen_pregenerated");
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
#[cfg(not(any(feature = "bindgen", feature = "fips")))]
|
|
fn handle_bindgen(_manifest_dir: &Path, _prefix: &Option<String>) -> bool {
|
|
false
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
fn main() {
|
|
initialize();
|
|
prepare_cargo_cfg();
|
|
|
|
let manifest_dir = current_dir();
|
|
let manifest_dir = dunce::canonicalize(Path::new(&manifest_dir)).unwrap();
|
|
let prefix_str = prefix_string();
|
|
let prefix = if is_no_prefix() {
|
|
None
|
|
} else {
|
|
Some(prefix_str)
|
|
};
|
|
|
|
let builder = get_builder(&prefix, &manifest_dir, &out_dir());
|
|
emit_warning(format!("Building with: {}", builder.name()));
|
|
emit_warning(format!("Symbol Prefix: {:?}", &prefix));
|
|
|
|
builder.check_dependencies().unwrap();
|
|
|
|
#[allow(unused_assignments)]
|
|
let mut bindings_available = false;
|
|
emit_warning(format!("Target platform: '{}'", target()));
|
|
if is_pregenerating_bindings() {
|
|
#[cfg(any(feature = "bindgen", feature = "fips"))]
|
|
{
|
|
let src_bindings_path = Path::new(&manifest_dir)
|
|
.join("src")
|
|
.join(format!("{}.rs", target_platform_prefix("crypto")));
|
|
if is_external_bindgen_requested().unwrap_or(false) {
|
|
assert!(
|
|
!is_pregenerating_bindings(),
|
|
"Pregenerated bindings not supported using external bindgen.",
|
|
);
|
|
invoke_external_bindgen(&manifest_dir, &prefix, &src_bindings_path).unwrap();
|
|
} else {
|
|
generate_src_bindings(&manifest_dir, &prefix, &src_bindings_path);
|
|
}
|
|
bindings_available = true;
|
|
}
|
|
} else if is_bindgen_required() {
|
|
assert!(
|
|
use_no_u1_bindings() != Some(true),
|
|
"Bindgen currently cannot generate prefixed bindings w/o the \\x01 prefix.",
|
|
);
|
|
emit_warning("######");
|
|
emit_warning(
|
|
"If bindgen is unable to locate a header file, use the \
|
|
BINDGEN_EXTRA_CLANG_ARGS environment variable to specify additional include paths.",
|
|
);
|
|
emit_warning("See: https://github.com/rust-lang/rust-bindgen?tab=readme-ov-file#environment-variables");
|
|
emit_warning("######");
|
|
let aws_lc_crypto_dir = Path::new(&manifest_dir).join("aws-lc").join("crypto");
|
|
if !aws_lc_crypto_dir.exists() {
|
|
emit_warning("######");
|
|
emit_warning("###### WARNING: MISSING GIT SUBMODULE ######");
|
|
emit_warning(format!(
|
|
" -- Did you initialize the repo's git submodules? Unable to find crypto directory: {}.",
|
|
&aws_lc_crypto_dir.display()
|
|
));
|
|
emit_warning(" -- run 'git submodule update --init --recursive' to initialize.");
|
|
emit_warning("######");
|
|
emit_warning("######");
|
|
}
|
|
bindings_available = handle_bindgen(&manifest_dir, &prefix);
|
|
} else {
|
|
bindings_available = true;
|
|
}
|
|
|
|
if !bindings_available {
|
|
if cfg!(feature = "ssl") {
|
|
emit_warning(
|
|
"External bindgen required, but external bindgen unable to produce SSL bindings.",
|
|
);
|
|
} else {
|
|
assert!(
|
|
use_no_u1_bindings() != Some(true),
|
|
"Bindgen currently cannot generate prefixed bindings w/o the \\x01 prefix.",
|
|
);
|
|
let gen_bindings_path = out_dir().join("bindings.rs");
|
|
let result = invoke_external_bindgen(&manifest_dir, &prefix, &gen_bindings_path);
|
|
match result {
|
|
Ok(()) => {
|
|
emit_rustc_cfg("use_bindgen_pregenerated");
|
|
bindings_available = true;
|
|
}
|
|
Err(msg) => eprintln!("Failure invoking external bindgen! {msg}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
assert!(
|
|
bindings_available,
|
|
"aws-lc-sys build failed. Please enable the 'bindgen' feature on aws-lc-rs or aws-lc-sys.\
|
|
For more information, see the aws-lc-rs User Guide: https://aws.github.io/aws-lc-rs/index.html"
|
|
);
|
|
builder.build().unwrap();
|
|
|
|
println!(
|
|
"cargo:include={}",
|
|
setup_include_paths(&out_dir(), &manifest_dir).display()
|
|
);
|
|
|
|
// export the artifact names
|
|
println!("cargo:libcrypto={}_crypto", prefix_string());
|
|
if cfg!(feature = "ssl") {
|
|
println!("cargo:libssl={}_ssl", prefix_string());
|
|
}
|
|
|
|
println!("cargo:conf={}", OSSL_CONF_DEFINES.join(","));
|
|
|
|
println!("cargo:rerun-if-changed=builder/");
|
|
println!("cargo:rerun-if-changed=aws-lc/");
|
|
}
|
|
|
|
fn setup_include_paths(out_dir: &Path, manifest_dir: &Path) -> PathBuf {
|
|
let mut include_paths = vec![
|
|
get_rust_include_path(manifest_dir),
|
|
get_generated_include_path(manifest_dir),
|
|
get_aws_lc_include_path(manifest_dir),
|
|
];
|
|
|
|
if let Some(extra_paths) = get_env_includes_path() {
|
|
include_paths.extend(extra_paths);
|
|
}
|
|
|
|
let include_dir = out_dir.join("include");
|
|
std::fs::create_dir_all(&include_dir).unwrap();
|
|
|
|
// iterate over all the include paths and copy them into the final output
|
|
for path in include_paths {
|
|
for child in std::fs::read_dir(path).into_iter().flatten().flatten() {
|
|
if child.file_type().map_or(false, |t| t.is_file()) {
|
|
std::fs::copy(
|
|
child.path(),
|
|
include_dir.join(child.path().file_name().unwrap()),
|
|
)
|
|
.expect("Failed to copy include file during build setup");
|
|
continue;
|
|
}
|
|
|
|
// prefer the earliest paths
|
|
let options = fs_extra::dir::CopyOptions::new()
|
|
.skip_exist(true)
|
|
.copy_inside(true);
|
|
fs_extra::dir::copy(child.path(), &include_dir, &options)
|
|
.expect("Failed to copy include directory during build setup");
|
|
}
|
|
}
|
|
|
|
include_dir
|
|
}
|
|
|
|
#[derive(Default)]
|
|
#[allow(dead_code)]
|
|
pub(crate) struct BindingOptions {
|
|
pub build_prefix: Option<String>,
|
|
pub include_ssl: bool,
|
|
pub disable_prelude: bool,
|
|
}
|
|
|
|
impl Debug for BindingOptions {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("BindingOptions")
|
|
.field("build_prefix", &self.build_prefix)
|
|
.field("include_ssl", &self.include_ssl)
|
|
.field("disable_prelude", &self.disable_prelude)
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
fn verify_bindgen() -> Result<(), String> {
|
|
if !is_external_bindgen_requested().unwrap_or(true) {
|
|
return Err("external bindgen usage prevented by SYS_EXTERNAL_BINDGEN=0".to_string());
|
|
}
|
|
|
|
let result = execute_command("bindgen".as_ref(), &["--version".as_ref()]);
|
|
if !result.status {
|
|
if result.executed {
|
|
eprintln!(
|
|
"bindgen-cli exited with an error status:\nSTDOUT: {}\n\nSTDERR: {}",
|
|
result.stdout, result.stderr
|
|
);
|
|
} else {
|
|
eprintln!(
|
|
"Consider installing the bindgen-cli: \
|
|
`cargo install --force --locked bindgen-cli`\
|
|
\n\
|
|
See our User Guide for more information about bindgen:\
|
|
https://aws.github.io/aws-lc-rs/index.html"
|
|
);
|
|
}
|
|
return Err("External bindgen command failed.".to_string());
|
|
}
|
|
let mut major_version: u32 = 0;
|
|
let mut minor_version: u32 = 0;
|
|
let mut patch_version: u32 = 0;
|
|
let bindgen_version = result.stdout.split(' ').nth(1);
|
|
if let Some(version) = bindgen_version {
|
|
let version_parts: Vec<&str> = version.trim().split('.').collect();
|
|
if version_parts.len() == 3 {
|
|
major_version = version_parts[0].parse::<u32>().unwrap_or(0);
|
|
minor_version = version_parts[1].parse::<u32>().unwrap_or(0);
|
|
patch_version = version_parts[2].parse::<u32>().unwrap_or(0);
|
|
}
|
|
}
|
|
// We currently expect to support all bindgen versions >= 0.69.5
|
|
if major_version == 0 && (minor_version < 69 || (minor_version == 69 && patch_version < 5)) {
|
|
eprintln!(
|
|
"bindgen-cli was used. Detected version was: \
|
|
{major_version}.{minor_version}.{patch_version} \n\
|
|
Consider upgrading : \
|
|
`cargo install --force --locked bindgen-cli`\
|
|
\n\
|
|
See our User Guide for more information about bindgen:\
|
|
https://aws.github.io/aws-lc-rs/index.html"
|
|
);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
const PRELUDE: &str = r"
|
|
#![allow(
|
|
clippy::cast_lossless,
|
|
clippy::cast_possible_truncation,
|
|
clippy::cast_possible_wrap,
|
|
clippy::default_trait_access,
|
|
clippy::doc_markdown,
|
|
clippy::missing_safety_doc,
|
|
clippy::must_use_candidate,
|
|
clippy::not_unsafe_ptr_arg_deref,
|
|
clippy::ptr_as_ptr,
|
|
clippy::ptr_offset_with_cast,
|
|
clippy::pub_underscore_fields,
|
|
clippy::semicolon_if_nothing_returned,
|
|
clippy::too_many_lines,
|
|
clippy::unreadable_literal,
|
|
clippy::used_underscore_binding,
|
|
clippy::useless_transmute,
|
|
dead_code,
|
|
improper_ctypes,
|
|
non_camel_case_types,
|
|
non_snake_case,
|
|
non_upper_case_globals,
|
|
unpredictable_function_pointer_comparisons,
|
|
unused_imports
|
|
)]
|
|
";
|
|
|
|
fn invoke_external_bindgen(
|
|
manifest_dir: &Path,
|
|
prefix: &Option<String>,
|
|
gen_bindings_path: &Path,
|
|
) -> Result<(), String> {
|
|
verify_bindgen()?;
|
|
|
|
emit_warning(format!(
|
|
"Generating bindings - external bindgen. Platform: {}",
|
|
effective_target()
|
|
));
|
|
|
|
let _guard_target = EnvGuard::new("TARGET", effective_target());
|
|
|
|
let options = BindingOptions {
|
|
// We collect the symbols w/o the prefix added
|
|
build_prefix: None,
|
|
include_ssl: false,
|
|
disable_prelude: true,
|
|
};
|
|
|
|
let clang_args = prepare_clang_args(manifest_dir, &options);
|
|
let header = get_rust_include_path(manifest_dir)
|
|
.join("rust_wrapper.h")
|
|
.display()
|
|
.to_string();
|
|
|
|
let sym_prefix: String;
|
|
let mut bindgen_params = vec![];
|
|
if let Some(prefix_str) = prefix {
|
|
sym_prefix = if target_os().to_lowercase() == "macos"
|
|
|| target_os().to_lowercase() == "ios"
|
|
|| target_os().to_lowercase() == "tvos"
|
|
|| (target_os().to_lowercase() == "windows" && target_arch() == "x86")
|
|
{
|
|
format!("_{prefix_str}_")
|
|
} else {
|
|
format!("{prefix_str}_")
|
|
};
|
|
bindgen_params.extend(vec!["--prefix-link-name", sym_prefix.as_str()]);
|
|
}
|
|
|
|
// These flags needs to be kept in sync with the setup in bindgen::prepare_bindings_builder
|
|
// If `bindgen-cli` makes backwards incompatible changes, we will update the parameters below
|
|
// to conform with the most recent release. We will guide consumers to likewise use the
|
|
// latest version of bindgen-cli.
|
|
bindgen_params.extend(vec![
|
|
"--allowlist-file",
|
|
r".*(/|\\)openssl((/|\\)[^/\\]+)+\.h",
|
|
"--allowlist-file",
|
|
r".*(/|\\)rust_wrapper\.h",
|
|
"--rustified-enum",
|
|
r"point_conversion_form_t",
|
|
"--default-macro-constant-type",
|
|
r"signed",
|
|
"--with-derive-default",
|
|
"--with-derive-partialeq",
|
|
"--with-derive-eq",
|
|
"--raw-line",
|
|
COPYRIGHT,
|
|
"--generate",
|
|
"functions,types,vars,methods,constructors,destructors",
|
|
header.as_str(),
|
|
"--rust-target",
|
|
r"1.70",
|
|
"--output",
|
|
gen_bindings_path.to_str().unwrap(),
|
|
"--formatter",
|
|
r"rustfmt",
|
|
]);
|
|
if !options.disable_prelude {
|
|
bindgen_params.extend(["--raw-line", PRELUDE]);
|
|
}
|
|
bindgen_params.push("--");
|
|
|
|
for x in &clang_args {
|
|
bindgen_params.push(x.as_str());
|
|
}
|
|
let cmd_params: Vec<OsString> = bindgen_params.iter().map(OsString::from).collect();
|
|
let cmd_params: Vec<&OsStr> = cmd_params.iter().map(OsString::as_os_str).collect();
|
|
|
|
let result = execute_command("bindgen".as_ref(), cmd_params.as_ref());
|
|
if !result.status {
|
|
return Err(format!(
|
|
"\n\n\
|
|
bindgen-PARAMS: {}\n\
|
|
bindgen-STDOUT: {}\n\
|
|
bindgen-STDERR: {}",
|
|
bindgen_params.join(" "),
|
|
result.stdout.as_ref(),
|
|
result.stderr.as_ref()
|
|
));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn add_header_include_path(args: &mut Vec<String>, path: String) {
|
|
args.push("-I".to_string());
|
|
args.push(path);
|
|
}
|
|
|
|
fn prepare_clang_args(manifest_dir: &Path, options: &BindingOptions) -> Vec<String> {
|
|
let mut clang_args: Vec<String> = Vec::new();
|
|
|
|
add_header_include_path(
|
|
&mut clang_args,
|
|
get_rust_include_path(manifest_dir).display().to_string(),
|
|
);
|
|
|
|
if options.build_prefix.is_some() {
|
|
// NOTE: It's possible that the prefix embedded in the header files doesn't match the prefix
|
|
// specified. This only happens when the version number as changed in Cargo.toml, but the
|
|
// new headers have not yet been generated.
|
|
add_header_include_path(
|
|
&mut clang_args,
|
|
get_generated_include_path(manifest_dir)
|
|
.display()
|
|
.to_string(),
|
|
);
|
|
}
|
|
|
|
add_header_include_path(
|
|
&mut clang_args,
|
|
get_aws_lc_include_path(manifest_dir).display().to_string(),
|
|
);
|
|
|
|
if let Some(include_paths) = get_env_includes_path() {
|
|
for path in include_paths {
|
|
add_header_include_path(&mut clang_args, path.display().to_string());
|
|
}
|
|
}
|
|
|
|
clang_args
|
|
}
|
|
|
|
const COPYRIGHT: &str = r"
|
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0 OR ISC
|
|
";
|
|
|
|
// =============================================================================
|
|
// Tests - run via: rustc --test builder/main.rs --edition 2021 -o /tmp/builder_test && /tmp/builder_test
|
|
// Or via the Makefile target: make test-builder
|
|
// =============================================================================
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
// -------------------------------------------------------------------------
|
|
// parse_to_bool tests
|
|
// -------------------------------------------------------------------------
|
|
|
|
#[test]
|
|
fn test_parse_to_bool_true_values() {
|
|
assert_eq!(parse_to_bool("1"), Some(true));
|
|
assert_eq!(parse_to_bool("2"), Some(true));
|
|
assert_eq!(parse_to_bool("9"), Some(true));
|
|
assert_eq!(parse_to_bool("ON"), Some(true));
|
|
assert_eq!(parse_to_bool("on"), Some(true));
|
|
assert_eq!(parse_to_bool("On"), Some(true));
|
|
assert_eq!(parse_to_bool("YES"), Some(true));
|
|
assert_eq!(parse_to_bool("yes"), Some(true));
|
|
assert_eq!(parse_to_bool("TRUE"), Some(true));
|
|
assert_eq!(parse_to_bool("true"), Some(true));
|
|
assert_eq!(parse_to_bool("y"), Some(true));
|
|
assert_eq!(parse_to_bool("Y"), Some(true));
|
|
assert_eq!(parse_to_bool("t"), Some(true));
|
|
assert_eq!(parse_to_bool("T"), Some(true));
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_to_bool_false_values() {
|
|
assert_eq!(parse_to_bool("0"), Some(false));
|
|
assert_eq!(parse_to_bool("OFF"), Some(false));
|
|
assert_eq!(parse_to_bool("off"), Some(false));
|
|
assert_eq!(parse_to_bool("NO"), Some(false));
|
|
assert_eq!(parse_to_bool("no"), Some(false));
|
|
assert_eq!(parse_to_bool("FALSE"), Some(false));
|
|
assert_eq!(parse_to_bool("false"), Some(false));
|
|
assert_eq!(parse_to_bool("n"), Some(false));
|
|
assert_eq!(parse_to_bool("N"), Some(false));
|
|
assert_eq!(parse_to_bool("f"), Some(false));
|
|
assert_eq!(parse_to_bool("F"), Some(false));
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_to_bool_none_values() {
|
|
assert_eq!(parse_to_bool(""), None);
|
|
assert_eq!(parse_to_bool("invalid"), None);
|
|
assert_eq!(parse_to_bool("maybe"), None);
|
|
assert_eq!(parse_to_bool(" "), None);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// OutputLib tests
|
|
// -------------------------------------------------------------------------
|
|
|
|
#[test]
|
|
fn test_output_lib_crypto_libname_with_prefix() {
|
|
let prefix = Some("test_prefix".to_string());
|
|
let name = OutputLib::Crypto.libname(&prefix);
|
|
assert_eq!(name, "test_prefix_crypto");
|
|
}
|
|
|
|
#[test]
|
|
fn test_output_lib_crypto_libname_without_prefix() {
|
|
let name = OutputLib::Crypto.libname(&None);
|
|
assert_eq!(name, "crypto");
|
|
}
|
|
|
|
#[test]
|
|
fn test_output_lib_ssl_libname_with_prefix() {
|
|
let prefix = Some("my_prefix".to_string());
|
|
let name = OutputLib::Ssl.libname(&prefix);
|
|
assert_eq!(name, "my_prefix_ssl");
|
|
}
|
|
|
|
#[test]
|
|
fn test_output_lib_ssl_libname_without_prefix() {
|
|
let name = OutputLib::Ssl.libname(&None);
|
|
assert_eq!(name, "ssl");
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// OutputLibType tests
|
|
// -------------------------------------------------------------------------
|
|
|
|
#[test]
|
|
fn test_output_lib_type_rust_lib_type() {
|
|
assert_eq!(OutputLibType::Static.rust_lib_type(), "static");
|
|
assert_eq!(OutputLibType::Dynamic.rust_lib_type(), "dylib");
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Version/Prefix tests
|
|
// -------------------------------------------------------------------------
|
|
|
|
#[test]
|
|
fn test_version_constant_exists() {
|
|
assert!(!VERSION.is_empty(), "VERSION should not be empty");
|
|
}
|
|
}
|