diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index e0cd1b17cf3..86af791cd92 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -66,7 +66,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, macos-12, macos-13-xlarge, windows-latest ] - features: [ aws-lc-sys, aws-lc-fips-sys ] + features: [ aws-lc-rs, aws-lc-rs-fips, aws-lc-sys, aws-lc-fips-sys ] steps: - uses: actions/checkout@v3 with: diff --git a/aws-lc-fips-sys/builder/main.rs b/aws-lc-fips-sys/builder/main.rs index 03520dbe8d9..0b0aafe89ba 100644 --- a/aws-lc-fips-sys/builder/main.rs +++ b/aws-lc-fips-sys/builder/main.rs @@ -296,6 +296,12 @@ fn main() { 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:rerun-if-changed=builder/"); println!("cargo:rerun-if-changed=aws-lc/"); println!("cargo:rerun-if-env-changed=AWS_LC_FIPS_SYS_STATIC"); diff --git a/aws-lc-rs/Cargo.toml b/aws-lc-rs/Cargo.toml index 3368affd0e8..15bccf00dbc 100644 --- a/aws-lc-rs/Cargo.toml +++ b/aws-lc-rs/Cargo.toml @@ -2,6 +2,8 @@ name = "aws-lc-rs" authors = ["AWS-LibCrypto"] version = "1.6.1" +# this crate re-exports whatever sys crate that was selected +links = "aws_lc_rs_1_6_1" edition = "2021" rust-version = "1.60" keywords = ["crypto", "cryptography", "security"] diff --git a/aws-lc-rs/build.rs b/aws-lc-rs/build.rs index 0675b5d876d..e34a7a37334 100644 --- a/aws-lc-rs/build.rs +++ b/aws-lc-rs/build.rs @@ -2,28 +2,74 @@ // SPDX-License-Identifier: Apache-2.0 OR ISC fn main() { - let mutually_exclusives_count = [cfg!(feature = "non-fips"), cfg!(feature = "fips")] - .iter() - .filter(|x| **x) - .count(); - - if mutually_exclusives_count > 1 { - eprint!("fips and non-fips are mutually exclusive crate features."); - std::process::exit(1); - } + let has_mutually_exclusive_features = cfg!(feature = "non-fips") && cfg!(feature = "fips"); + assert!( + !has_mutually_exclusive_features, + "`fips` and `non-fips` are mutually exclusive crate features." + ); // This appears asymmetric, but it reflects the `cfg` statements in lib.rs that // require `aws-lc-sys` to be present when "fips" is not enabled. - let at_least_one_count = [cfg!(feature = "aws-lc-sys"), cfg!(feature = "fips")] - .iter() - .filter(|x| **x) - .count(); - - if at_least_one_count < 1 { - eprint!( - "one of the following features must be specified: \ - aws-lc-sys, non-fips, or fips." + // if `fips` is enabled, then use that + let sys_crate = if cfg!(feature = "fips") { + "aws-lc-fips-sys" + } else if cfg!(feature = "aws-lc-sys") { + "aws-lc-sys" + } else { + panic!( + "one of the following features must be specified: `aws-lc-sys`, `non-fips`, or `fips`." ); - std::process::exit(1); + }; + + export_sys_vars(sys_crate); +} + +fn export_sys_vars(sys_crate: &str) { + let prefix = if sys_crate == "aws-lc-fips-sys" { + "DEP_AWS_LC_FIPS_" + } else { + "DEP_AWS_LC_" + }; + + let mut selected = String::default(); + let mut candidates = vec![]; + + // search through the DEP vars and find the selected sys crate version + for (name, value) in std::env::vars() { + // if we've selected a prefix then we can go straight to exporting it + if !selected.is_empty() { + try_export_var(&selected, &name, &value); + continue; + } + + // we're still looking for a selected prefix + if let Some(version) = name.strip_prefix(prefix) { + if let Some(version) = version.strip_suffix("_INCLUDE") { + // we've found the selected version so update it and export it + selected = format!("{prefix}{version}_"); + try_export_var(&selected, &name, &value); + } else { + // it started with the expected prefix, but we don't know what the version is yet + // so save it for later + candidates.push((name, value)); + } + } + } + + assert!(!selected.is_empty(), "missing {prefix} include"); + + // process all of the remaining candidates + for (name, value) in candidates { + try_export_var(&selected, &name, &value); + } +} + +fn try_export_var(selected: &str, name: &str, value: &str) { + assert!(!selected.is_empty(), "missing selected prefix"); + + if let Some(var) = name.strip_prefix(selected) { + eprintln!("cargo:rerun-if-env-changed={name}"); + let var = var.to_lowercase(); + println!("cargo:{var}={value}"); } } diff --git a/aws-lc-sys/builder/main.rs b/aws-lc-sys/builder/main.rs index a65c1eddadb..f642c7c5f9d 100644 --- a/aws-lc-sys/builder/main.rs +++ b/aws-lc-sys/builder/main.rs @@ -294,6 +294,12 @@ fn main() { 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:rerun-if-changed=builder/"); println!("cargo:rerun-if-changed=aws-lc/"); println!("cargo:rerun-if-env-changed=AWS_LC_SYS_STATIC"); diff --git a/sys-testing/Cargo.toml b/sys-testing/Cargo.toml index c36a6f76df4..f7ae821898a 100644 --- a/sys-testing/Cargo.toml +++ b/sys-testing/Cargo.toml @@ -6,10 +6,13 @@ publish = false [features] default = ["aws-lc-sys"] +aws-lc-rs = ["dep:aws-lc-rs"] +aws-lc-rs-fips = ["aws-lc-rs", "aws-lc-rs/fips"] aws-lc-sys = ["dep:aws-lc-sys"] aws-lc-fips-sys = ["dep:aws-lc-fips-sys"] [dependencies] +aws-lc-rs = { path = "../aws-lc-rs", optional = true } aws-lc-sys = { path = "../aws-lc-sys", optional = true } aws-lc-fips-sys = { path = "../aws-lc-fips-sys", optional = true } @@ -18,4 +21,4 @@ cc = "1" toml_edit = "0.21" [package.metadata.cargo-udeps.ignore] -normal = [ "aws-lc-sys", "aws-lc-fips-sys" ] # the sys crate is only used through a C library build +normal = [ "aws-lc-rs", "aws-lc-sys", "aws-lc-fips-sys" ] # the sys crate is only used through a C library build diff --git a/sys-testing/build.rs b/sys-testing/build.rs index f5cdcc928e7..90bd8ad9d00 100644 --- a/sys-testing/build.rs +++ b/sys-testing/build.rs @@ -4,20 +4,30 @@ use toml_edit::Document; fn main() { - if cfg!(all(feature = "aws-lc-sys", feature = "aws-lc-fips-sys")) { - panic!("only one sys crate can be built at a time") - } else if cfg!(feature = "aws-lc-sys") { - let aws_lc_sys_links = get_package_links_property("../aws-lc-sys/Cargo.toml"); - build_and_link(aws_lc_sys_links.as_ref(), "aws_lc_sys"); - return; - } else if cfg!(feature = "aws-lc-fips-sys") { - let aws_lc_fips_sys_links = get_package_links_property("../aws-lc-fips-sys/Cargo.toml"); - build_and_link(aws_lc_fips_sys_links.as_ref(), "aws_lc_fips"); - return; + let mut deps = vec![]; + + macro_rules! select_dep { + ($dep:literal) => { + if cfg!(feature = $dep) { + deps.push($dep); + } + }; } - panic!( - "select a sys crate for testing using --features aws-lc-sys or --features aws-lc-fips-sys" - ) + + select_dep!("aws-lc-rs"); + select_dep!("aws-lc-sys"); + select_dep!("aws-lc-fips-sys"); + + assert_eq!( + deps.len(), + 1, + "exactly one dependency is allowed at a time, got {deps:?}" + ); + + let dep = deps.pop().unwrap(); + let aws_lc_sys_links = get_package_links_property(&format!("../{dep}/Cargo.toml")); + let dep_snake_case = dep.replace('-', "_"); + build_and_link(aws_lc_sys_links.as_ref(), &dep_snake_case); } fn build_and_link(links: &str, target_name: &str) { @@ -25,10 +35,15 @@ fn build_and_link(links: &str, target_name: &str) { cc::Build::new() .include(env(format!("DEP_{}_INCLUDE", links.to_uppercase()))) .file("src/testing.c") - .compile(target_name); + .compile(&format!("testing_{target_name}")); + + // make sure the root was exported + let root = env(format!("DEP_{}_ROOT", links.to_uppercase())); + println!("cargo:rustc-link-search={root}"); // ensure the libcrypto artifact is linked - println!("cargo:rustc-link-lib={links}_crypto"); + let libcrypto = env(format!("DEP_{}_LIBCRYPTO", links.to_uppercase())); + println!("cargo:rustc-link-lib={libcrypto}"); } fn get_package_links_property(cargo_toml_path: &str) -> String {