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 16 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
47 changes: 32 additions & 15 deletions mbedtls/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,49 @@
* 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;

/// 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 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 mut out_dir_it_rev = out_dir.iter().rev();
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()
.expect("Expected OUT_DIR to have at least 2 components")
.to_str()
.expect("Expected second to last component of OUT_DIR to be a valid UTF-8 string");
assert!(crate_.starts_with("mbedtls-"), "Expected second to last component of OUT_DIR to start with 'mbedtls-'");
return crate_[8..].to_owned(); // Return the part after "mbedtls-"
} else if out_dir.iter().rfind(|p| *p == "bazel-out").is_some() {
// If Bazel is used as build system.
let mut hasher = DefaultHasher::new();
// Reverse the iterator and hash until we find "bazel-out"
for p in out_dir.iter().rev().take_while(|p| *p != "bazel-out") {
p.hash(&mut hasher);
}
return format!("{:016x}", hasher.finish());
} else {
panic!("unexpected OUT_DIR format: {}", out_dir.display());
}
}

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 +63,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
7 changes: 5 additions & 2 deletions mbedtls/src/mbedtls_malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
#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
// Use several macros to get the preprocessor to actually replace RUST_MBEDTLS_SYMBOL_SUFFIX.
// 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
Loading