diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index e0cd1b17cf3..264a3539843 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -58,7 +58,7 @@ jobs: run: | ./scripts/run-rustls-integration.sh - sys-crate-tests: + links-crate-tests: if: github.repository == 'aws/aws-lc-rs' name: sys crate tests runs-on: ${{ matrix.os }} @@ -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: @@ -85,10 +85,10 @@ jobs: - name: Install ninja-build tool uses: seanmiddleditch/gha-setup-ninja@v4 - name: Run cargo test - working-directory: ./sys-testing + working-directory: ./links-testing run: cargo test --features ${{ matrix.features }} --no-default-features - name: Run cargo run - working-directory: ./sys-testing + working-directory: ./links-testing run: cargo run --features ${{ matrix.features }} --no-default-features publish-dry-run: diff --git a/Cargo.toml b/Cargo.toml index de7558d872f..d463e2a6ece 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = [ "aws-lc-sys", "aws-lc-fips-sys", "aws-lc-rs-testing", - "sys-testing" + "links-testing" ] resolver = "2" 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..e03b5fee9f6 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_sys" 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/links-testing/Cargo.toml similarity index 59% rename from sys-testing/Cargo.toml rename to links-testing/Cargo.toml index c36a6f76df4..7612c0fcf9c 100644 --- a/sys-testing/Cargo.toml +++ b/links-testing/Cargo.toml @@ -1,15 +1,18 @@ [package] -name = "sys-testing" +name = "links-testing" version = "0.1.0" edition = "2021" 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/links-testing/build.rs b/links-testing/build.rs new file mode 100644 index 00000000000..39c8334bfaf --- /dev/null +++ b/links-testing/build.rs @@ -0,0 +1,62 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +use toml_edit::Document; + +fn main() { + let mut deps = vec![]; + + macro_rules! select_dep { + ($dep:literal) => { + if cfg!(feature = $dep) { + deps.push($dep); + } + }; + } + + 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 dep_links = get_package_links_property(&format!("../{dep}/Cargo.toml")); + let dep_snake_case = dep.replace('-', "_"); + build_and_link(dep_links.as_ref(), &dep_snake_case); +} + +fn build_and_link(links: &str, target_name: &str) { + // ensure that the include path is exported and set up correctly + cc::Build::new() + .include(env(format!("DEP_{}_INCLUDE", links.to_uppercase()))) + .file("src/testing.c") + .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 + 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 { + let cargo_toml = std::fs::read_to_string(cargo_toml_path).unwrap(); + let cargo_toml = cargo_toml.parse::().unwrap(); + + let links = cargo_toml["package"]["links"].as_str().unwrap(); + + String::from(links) +} + +fn env>(s: S) -> String { + let s = s.as_ref(); + println!("cargo:rerun-if-env-changed={s}"); + std::env::var(s).unwrap_or_else(|_| panic!("missing env var {s}")) +} diff --git a/sys-testing/src/main.rs b/links-testing/src/main.rs similarity index 100% rename from sys-testing/src/main.rs rename to links-testing/src/main.rs diff --git a/sys-testing/src/testing.c b/links-testing/src/testing.c similarity index 100% rename from sys-testing/src/testing.c rename to links-testing/src/testing.c diff --git a/sys-testing/build.rs b/sys-testing/build.rs deleted file mode 100644 index f5cdcc928e7..00000000000 --- a/sys-testing/build.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 OR ISC - -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; - } - panic!( - "select a sys crate for testing using --features aws-lc-sys or --features aws-lc-fips-sys" - ) -} - -fn build_and_link(links: &str, target_name: &str) { - // ensure that the include path is exported and set up correctly - cc::Build::new() - .include(env(format!("DEP_{}_INCLUDE", links.to_uppercase()))) - .file("src/testing.c") - .compile(target_name); - - // ensure the libcrypto artifact is linked - println!("cargo:rustc-link-lib={links}_crypto"); -} - -fn get_package_links_property(cargo_toml_path: &str) -> String { - let cargo_toml = std::fs::read_to_string(cargo_toml_path).unwrap(); - let cargo_toml = cargo_toml.parse::().unwrap(); - - let links = cargo_toml["package"]["links"].as_str().unwrap(); - - String::from(links) -} - -fn env>(s: S) -> String { - let s = s.as_ref(); - println!("cargo:rerun-if-env-changed={s}"); - std::env::var(s).unwrap_or_else(|_| panic!("missing env var {s}")) -}