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

Adding CrateId Metadata Hash method for Bazel #365

Merged
merged 17 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 10 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
51 changes: 37 additions & 14 deletions mbedtls/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,55 @@
* option. This file may not be copied, modified, or distributed except
* according to those terms. */

use std::collections::hash_map::DefaultHasher;
use std::collections::{HashMap, HashSet};
use std::env;
use std::hash::{Hash, Hasher};

use rustc_version::Channel;
use std::env;
use std::path::Path;

/// Return the crate hash that Cargo will be passing to `rustc -C metadata=`.
// If there's a panic in this code block, that means Cargo's way of running the
// build script has changed, and this code should be updated to handle the new
// case.
fn get_compilation_metadata_hash() -> String {
/// Retrieves or generates a metadata value used for symbol name mangling to ensure unique C symbols.
/// When building with Cargo, the metadata value is extracted from the OUT_DIR environment variable.
/// For Bazel builds, this method generate the suffix by hashing part of the crate OUT_DIR,
/// which are sufficient for ensuring symbol uniqueness.
Pagten marked this conversation as resolved.
Show resolved Hide resolved
fn get_compilation_symbol_suffix() -> String {
let out_dir: std::path::PathBuf = std::env::var_os("OUT_DIR").unwrap().into();
let out_dir_str = out_dir.to_string_lossy();

let mut out_dir_it = out_dir.iter().rev();
assert_eq!(out_dir_it.next().unwrap(), "out");
let crate_ = out_dir_it.next().unwrap().to_string_lossy();
assert!(crate_.starts_with("mbedtls-"));
crate_[8..].to_owned()
let last_part = out_dir_it.next().unwrap();

if last_part == "out" {
// If Cargo is used as build system.
let crate_ = out_dir_it.next().unwrap().to_string_lossy();
assert!(crate_.starts_with("mbedtls-"), "Expected directory to start with 'mbedtls-'");
return crate_[8..].to_owned(); // Return the part after "mbedtls-"
} else if out_dir_str.contains("bazel-out") {
// If Bazel is used as build system.
let parts_to_hash = out_dir_str
.split("bazel-out")
.nth(1)
.expect("Invalid Bazel out dir structure");

let string_to_hash = format!("bazel-out{}", parts_to_hash);
let mut hasher = DefaultHasher::new();
string_to_hash.hash(&mut hasher);
let hash = hasher.finish();
return format!("{:x}", hash);
} else {
panic!("Unexpected directory structure: {:?}", out_dir_str);
Copy link
Member

@jethrogb jethrogb Sep 9, 2024

Choose a reason for hiding this comment

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

Suggested change
let last_part = out_dir_it.next().unwrap();
if last_part == "out" {
// If Cargo is used as build system.
let crate_ = out_dir_it.next().unwrap().to_string_lossy();
assert!(crate_.starts_with("mbedtls-"), "Expected directory to start with 'mbedtls-'");
return crate_[8..].to_owned(); // Return the part after "mbedtls-"
} else if out_dir_str.contains("bazel-out") {
// If Bazel is used as build system.
let parts_to_hash = out_dir_str
.split("bazel-out")
.nth(1)
.expect("Invalid Bazel out dir structure");
let string_to_hash = format!("bazel-out{}", parts_to_hash);
let mut hasher = DefaultHasher::new();
string_to_hash.hash(&mut hasher);
let hash = hasher.finish();
return format!("{:x}", hash);
} else {
panic!("Unexpected directory structure: {:?}", out_dir_str);
let mut out_dir_it_rev = out_dir.iter().rev();
let mut out_dir_it = out_dir.iter();
if out_dir_it_rev.next().map_or(false, |p| p == "out") {
// If Cargo is used as build system.
let crate_ = out_dir_it_rev.next().unwrap().to_string_lossy();
assert!(crate_.starts_with("mbedtls-"), "Expected directory to start with 'mbedtls-'");
return crate_[8..].to_owned(); // Return the part after "mbedtls-"
} else if out_dir_it.position(|p| p == "bazel-out").is_some() {
// If Bazel is used as build system.
let mut hasher = DefaultHasher::new();
for p in out_dir_it {
p.hash(&mut hasher);
}
let hash = hasher.finish();
return format!("{:016x}", hash);
} else {
panic!("unexpected OUT_DIR format: {}", out_dir.to_string_lossy());

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Much better implementation. Thanks.

# Configuration: c2b2998e956e739e6041daea0eaadcf22e7f68c3e819bfbfc43c92b444190896
# Execution platform: //:docker_image_platform
[237 / 238] Compiling Rust bin service1 (1 files); 0s remote, remote-cache
[237 / 238] Compiling Rust bin service1 (1 files); 10s remote, remote-cache
[237 / 238] Compiling Rust bin service1 (1 files); Downloading service1/service1; 16s remote, remote-cache
INFO: Found 4 targets...
INFO: Elapsed time: 62.137s, Critical Path: 53.13s
INFO: 10 processes: 1 internal, 9 remote.
INFO: Build completed successfully, 10 total actions

}
}

fn main() {
// used for configuring rustdoc attrs for now
if rustc_version::version_meta().is_ok_and(|v| v.channel == Channel::Nightly) {
println!("cargo:rustc-cfg=nightly");
}

let metadata_hash = get_compilation_metadata_hash();
println!("cargo:rustc-env=RUST_MBEDTLS_METADATA_HASH={}", metadata_hash);
let symbol_suffix = get_compilation_symbol_suffix();
println!("cargo:rustc-env=RUST_MBEDTLS_SYMBOL_SUFFIX={}", symbol_suffix);
println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");

let env_components = env::var("DEP_MBEDTLS_PLATFORM_COMPONENTS").unwrap();
let mut sys_platform_components = HashMap::<_, HashSet<_>>::new();
Expand All @@ -46,7 +69,7 @@ fn main() {
b.include(env::var_os("DEP_MBEDTLS_INCLUDE").unwrap());
let config_file = format!(r#""{}""#, env::var("DEP_MBEDTLS_CONFIG_H").unwrap());
b.define("MBEDTLS_CONFIG_FILE", Some(config_file.as_str()));
b.define("RUST_MBEDTLS_METADATA_HASH", Some(metadata_hash.as_str()));
b.define("RUST_MBEDTLS_SYMBOL_SUFFIX", Some(symbol_suffix.as_str()));

b.file("src/mbedtls_malloc.c");
if sys_platform_components
Expand Down
4 changes: 2 additions & 2 deletions mbedtls/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use core::ptr::NonNull;
use mbedtls_sys::types::raw_types::c_void;

extern "C" {
#[link_name = concat!("forward_mbedtls_free_", env!("RUST_MBEDTLS_METADATA_HASH"))]
#[link_name = concat!("forward_mbedtls_free_", env!("RUST_MBEDTLS_SYMBOL_SUFFIX"))]
pub(crate) fn mbedtls_free(n: *mut mbedtls_sys::types::raw_types::c_void);
#[link_name = concat!("forward_mbedtls_calloc_", env!("RUST_MBEDTLS_METADATA_HASH"))]
#[link_name = concat!("forward_mbedtls_calloc_", env!("RUST_MBEDTLS_SYMBOL_SUFFIX"))]
pub(crate) fn mbedtls_calloc(
n: mbedtls_sys::types::size_t,
size: mbedtls_sys::types::size_t,
Expand Down
6 changes: 4 additions & 2 deletions mbedtls/src/mbedtls_malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
#define mbedtls_free free
#endif

// Use several macros to get the preprocessor to actually replace RUST_MBEDTLS_METADATA_HASH
Pagten marked this conversation as resolved.
Show resolved Hide resolved
// This code handles cases where `mbedtls_calloc` and `mbedtls_free` may be macros instead of functions,
// which Bindgen has trouble with. The `APPEND_METADATA_HASH` macro appends a suffix from `RUST_MBEDTLS_SYMBOL_SUFFIX`
// to ensure proper symbol linkage, regardless of whether the original mbedtls functions are macros or symbols.
#define append_macro_inner(a, b) a##_##b
#define append_macro(a, b) append_macro_inner(a, b)
#define APPEND_METADATA_HASH(f) append_macro(f, RUST_MBEDTLS_METADATA_HASH)
#define APPEND_METADATA_HASH(f) append_macro(f, RUST_MBEDTLS_SYMBOL_SUFFIX)

extern void *APPEND_METADATA_HASH(forward_mbedtls_calloc)( size_t n, size_t size ) {
return mbedtls_calloc(n, size);
Expand Down