Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor sys-crate Cmake build logic #301

Merged
merged 3 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions aws-lc-fips-sys/builder/cmake_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

use crate::OutputLib::{Crypto, RustWrapper, Ssl};
use crate::{target, target_arch, target_os, target_vendor, test_command, OutputLibType};
use std::env;
use std::ffi::OsStr;
use std::path::PathBuf;

pub(crate) struct CmakeBuilder {
manifest_dir: PathBuf,
out_dir: PathBuf,
build_prefix: Option<String>,
output_lib_type: OutputLibType,
}

fn test_perl_command() -> bool {
test_command("perl".as_ref(), &["--version".as_ref()])
}

fn test_go_command() -> bool {
test_command("go".as_ref(), &["version".as_ref()])
Comment on lines +17 to +22

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to enforce minimum versions here?

i suppose similar question applies to non-fips

}

fn find_cmake_command() -> Option<&'static OsStr> {
if test_command("cmake3".as_ref(), &["--version".as_ref()]) {
Some("cmake3".as_ref())
} else if test_command("cmake".as_ref(), &["--version".as_ref()]) {
Some("cmake".as_ref())
} else {
None
}
}

fn get_platform_output_path() -> PathBuf {
PathBuf::new()
}

impl CmakeBuilder {
pub(crate) fn new(
manifest_dir: PathBuf,
out_dir: PathBuf,
build_prefix: Option<String>,
output_lib_type: OutputLibType,
) -> Self {
Self {
manifest_dir,
out_dir,
build_prefix,
output_lib_type,
}
}

fn artifact_output_dir(&self) -> PathBuf {
self.out_dir
.join("build")
.join("artifacts")
.join(get_platform_output_path())
}

fn get_cmake_config(&self) -> cmake::Config {
cmake::Config::new(&self.manifest_dir)
}

fn prepare_cmake_build(&self) -> cmake::Config {
let mut cmake_cfg = self.get_cmake_config();

if ["powerpc64", "powerpc"]
.iter()
.any(|arch| target_arch().eq_ignore_ascii_case(arch))
{
cmake_cfg.define("ENABLE_EXPERIMENTAL_BIG_ENDIAN_SUPPORT", "1");
}

if OutputLibType::default() == OutputLibType::Dynamic {
cmake_cfg.define("BUILD_SHARED_LIBS", "1");
} else {
cmake_cfg.define("BUILD_SHARED_LIBS", "0");
}

let opt_level = env::var("OPT_LEVEL").unwrap_or_else(|_| "0".to_string());
if opt_level.ne("0") {
if opt_level.eq("1") || opt_level.eq("2") {
cmake_cfg.define("CMAKE_BUILD_TYPE", "relwithdebinfo");
} else {
cmake_cfg.define("CMAKE_BUILD_TYPE", "release");
}
} else if target_os() != "windows" {
// The Windows/FIPS build rejects "debug" profile
// https://github.com/aws/aws-lc/blob/main/CMakeLists.txt#L656
cmake_cfg.define("CMAKE_BUILD_TYPE", "debug");
}

if let Some(prefix) = &self.build_prefix {
cmake_cfg.define("BORINGSSL_PREFIX", format!("{prefix}_"));
let include_path = self.manifest_dir.join("generated-include");
cmake_cfg.define(
"BORINGSSL_PREFIX_HEADERS",
include_path.display().to_string(),
);
}

// Build flags that minimize our crate size.
cmake_cfg.define("BUILD_TESTING", "OFF");
if cfg!(feature = "ssl") {
cmake_cfg.define("BUILD_LIBSSL", "ON");
} else {
cmake_cfg.define("BUILD_LIBSSL", "OFF");
}

if target_vendor() == "apple" {
if target_os().trim() == "ios" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to .trim() on other calls to target_os() (e.g. L88)?

i suppose similar question applies to non-fips

cmake_cfg.define("CMAKE_SYSTEM_NAME", "iOS");
if target().trim().ends_with("-ios-sim") {
cmake_cfg.define("CMAKE_OSX_SYSROOT", "iphonesimulator");
}
}
if target_arch().trim() == "aarch64" {
cmake_cfg.define("CMAKE_OSX_ARCHITECTURES", "arm64");
}
}
cmake_cfg.define("FIPS", "1");

if cfg!(feature = "asan") {
env::set_var("CC", "clang");
env::set_var("CXX", "clang++");
env::set_var("ASM", "clang");

cmake_cfg.define("ASAN", "1");
}

cmake_cfg
}

fn build_rust_wrapper(&self) -> PathBuf {
self.prepare_cmake_build()
.configure_arg("--no-warn-unused-cli")
.build()
}
}

impl crate::Builder for CmakeBuilder {
fn check_dependencies(&self) -> Result<(), String> {
let mut missing_dependency = false;
if !test_go_command() {
eprintln!("Missing dependency: Go is required for FIPS.");
missing_dependency = true;
}
if !test_perl_command() {
eprintln!("Missing dependency: perl is required for FIPS.");
missing_dependency = true;
}
if let Some(cmake_cmd) = find_cmake_command() {
env::set_var("CMAKE", cmake_cmd);
} else {
eprintln!("Missing dependency: cmake");
missing_dependency = true;
};

if missing_dependency {
return Err("Required build dependency is missing. Halting build.".to_owned());
}

Ok(())
}
fn build(&self) -> Result<(), String> {
self.build_rust_wrapper();

println!(
"cargo:rustc-link-search=native={}",
self.artifact_output_dir().display()
);

println!(
"cargo:rustc-link-lib={}={}",
self.output_lib_type.rust_lib_type(),
Crypto.libname(&self.build_prefix)
);

if cfg!(feature = "ssl") {
println!(
"cargo:rustc-link-lib={}={}",
self.output_lib_type.rust_lib_type(),
Ssl.libname(&self.build_prefix)
);
}

println!(
"cargo:rustc-link-lib={}={}",
self.output_lib_type.rust_lib_type(),
RustWrapper.libname(&self.build_prefix)
);

Ok(())
}
}
Loading
Loading