use crate::system_library::{InstallLayout, SystemLib};
use crate::{
emit_warning, get_system_bindings_path, get_system_skip_version_check, optional_env_target,
use_system,
};
use std::path::{Path, PathBuf};
#[cfg(unix)]
const PKG_CONFIG_MODULES: &[&str] = &["openssl", "aws-lc", "libcrypto", "libcrypto-awslc"];
fn detect_candidate_layouts() -> Vec<InstallLayout> {
let mut candidates = Vec::new();
let openssl_dir = optional_env_target("OPENSSL_DIR").map(PathBuf::from);
if let Some(prefix) = &openssl_dir {
candidates.push(InstallLayout::from_prefix(prefix.clone()));
}
let include_env = optional_env_target("OPENSSL_INCLUDE_DIR").map(PathBuf::from);
let lib_env = optional_env_target("OPENSSL_LIB_DIR").map(PathBuf::from);
if include_env.is_some() || lib_env.is_some() {
let include_dir = include_env.or_else(|| openssl_dir.as_ref().map(|p| p.join("include")));
let lib_dir = lib_env.or_else(|| openssl_dir.as_ref().map(|p| p.join("lib")));
if let (Some(include_dir), Some(lib_dir)) = (include_dir, lib_dir) {
let bindings_prefix = openssl_dir
.clone()
.or_else(|| bindings_prefix_from_include_dir(&include_dir));
candidates.push(InstallLayout::from_paths(
include_dir,
vec![lib_dir],
bindings_prefix,
));
}
}
if candidates.is_empty() {
candidates.extend(pkg_config_candidates());
}
candidates
}
#[cfg(unix)]
fn pkg_config_candidates() -> Vec<InstallLayout> {
PKG_CONFIG_MODULES
.iter()
.filter_map(|module| {
let library = pkg_config::Config::new()
.cargo_metadata(false)
.probe(module)
.ok()?;
let include_dir = library.include_paths.first()?.clone();
let bindings_prefix = bindings_prefix_from_include_dir(&include_dir);
Some(InstallLayout::from_paths(
include_dir,
library.link_paths.clone(),
bindings_prefix,
))
})
.collect()
}
#[cfg(not(unix))]
fn pkg_config_candidates() -> Vec<InstallLayout> {
Vec::new()
}
fn bindings_prefix_from_include_dir(include_dir: &Path) -> Option<PathBuf> {
let parent = include_dir.parent()?;
if include_dir.file_name().and_then(|name| name.to_str()) == Some("aws-lc")
&& parent.file_name().and_then(|name| name.to_str()) == Some("include")
{
return parent.parent().map(Path::to_path_buf);
}
Some(parent.to_path_buf())
}
pub(crate) fn detect_system_awslc(manifest_dir: &Path) -> Option<SystemLib> {
let report_rejection = |message: String| {
if use_system() == Some(true) {
emit_warning(message);
} else {
println!("{message}");
}
};
for layout in detect_candidate_layouts() {
let sys = SystemLib::from_layout(
manifest_dir.to_path_buf(),
layout,
get_system_bindings_path(),
get_system_skip_version_check(),
);
match sys.probe() {
Ok(()) => {
emit_warning(format!(
"Auto-detected system-installed AWS-LC at: {}",
sys.marker_dir().display()
));
return Some(sys);
}
Err(reason) => {
report_rejection(format!(
"Ignoring candidate AWS-LC at {}: {reason}",
sys.marker_dir().display()
));
}
}
}
None
}
#[cfg(test)]
#[path = "system_detect_tests.rs"]
mod tests;