From 017f5dea0cb16ec550e629d25c37698194810443 Mon Sep 17 00:00:00 2001 From: Geoff Martin Date: Thu, 31 Oct 2024 10:05:32 +0000 Subject: [PATCH 1/4] Added support for mangling C library symbols on Windows. --- Cross.toml | 17 +++++ build.rs | 144 +++++++++++++++++++++++++++++++++++------ nm/CMakeLists.txt | 8 ++- objcopy/CMakeLists.txt | 8 ++- 4 files changed, 152 insertions(+), 25 deletions(-) create mode 100644 Cross.toml diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 0000000..8f0ad31 --- /dev/null +++ b/Cross.toml @@ -0,0 +1,17 @@ +[target.x86_64-unknown-linux-musl] +image = "jenoch/rust-cross:x86_64-unknown-linux-musl" + +[target.arm-unknown-linux-gnueabi] +image = "jenoch/rust-cross:arm-unknown-linux-gnueabi" + +[target.arm-unknown-linux-gnueabihf] +image = "jenoch/rust-cross:arm-unknown-linux-gnueabihf" + +[target.armv7-unknown-linux-gnueabihf] +image = "jenoch/rust-cross:armv7-unknown-linux-gnueabihf" + +[target.aarch64-unknown-linux-gnu] +image = "jenoch/rust-cross:aarch64-unknown-linux-gnu" + +[target.aarch64-unknown-linux-musl] +image = "jenoch/rust-cross:aarch64-unknown-linux-musl" diff --git a/build.rs b/build.rs index af0e5bf..d3682f6 100644 --- a/build.rs +++ b/build.rs @@ -15,11 +15,27 @@ fn main() { let mut dir_builder = std::fs::DirBuilder::new(); dir_builder.recursive(true); + // Symbol Prefix to add to C symbols + #[allow(unused)] + let mut prefix = String::new(); + #[cfg(all( + any(target_os = "linux", target_os = "windows"), + not(feature = "iceoryx") + ))] + { + // Prefix = cyclors_ + prefix = env::var("CARGO_PKG_VERSION").unwrap().replace('.', "_"); + prefix.insert_str(0, "cyclors_"); + prefix.push('_'); + } + + let cyclonedds_src_dir = prepare_cyclonedds_src("cyclonedds", &out_dir, &prefix); + // Create Cyclone DDS build directory and initial config let cyclonedds_dir = out_dir.join("cyclonedds-build"); dir_builder.create(&cyclonedds_dir).unwrap(); - let mut cyclonedds = cmake::Config::new("cyclonedds"); + let mut cyclonedds = cmake::Config::new(cyclonedds_src_dir); let mut cyclonedds = cyclonedds.out_dir(cyclonedds_dir); // Create initial bindings builder @@ -150,28 +166,21 @@ fn main() { .clang_arg(format!("-I{}", cyclocut_include.to_str().unwrap())) .generate_comments(false); - #[allow(unused)] - let mut prefix = String::from(""); - // Prefix symbols in Cyclone DDS and Cyclocut libraries to ensure uniqueness - #[cfg(all(target_os = "linux", not(feature = "iceoryx")))] - { - // Prefix = cyclors_ - prefix = env::var("CARGO_PKG_VERSION").unwrap().replace('.', "_"); - prefix.insert_str(0, "cyclors_"); - prefix.push('_'); - + if !prefix.is_empty() { let mut symbols = HashSet::new(); + let ddsc_lib_name = get_library_name("ddsc").unwrap(); + let cdds_lib_name = get_library_name("cdds-util").unwrap(); - let cyclone_symbols = get_defined_symbols(&cyclonedds_lib, "libddsc.a") - .expect("Failed to get symbols from libddsc.a!"); + let cyclone_symbols = get_defined_symbols(&cyclonedds_lib, &ddsc_lib_name) + .expect("Failed to get symbols from ddsc library!"); symbols.extend(cyclone_symbols); - prefix_symbols(&cyclonedds_lib, "libddsc.a", &prefix, &symbols).unwrap(); + prefix_symbols(&cyclonedds_lib, &ddsc_lib_name, &prefix, &symbols).unwrap(); - let cyclocut_symbols = get_defined_symbols(&cyclocut_lib, "libcdds-util.a") - .expect("Failed to get symbols from libcdds-util.a!"); + let cyclocut_symbols = get_defined_symbols(&cyclocut_lib, &cdds_lib_name) + .expect("Failed to get symbols from cdds-util library!"); symbols.extend(cyclocut_symbols); - prefix_symbols(&cyclocut_lib, "libcdds-util.a", &prefix, &symbols).unwrap(); + prefix_symbols(&cyclocut_lib, &cdds_lib_name, &prefix, &symbols).unwrap(); #[derive(Debug)] struct PrefixLinkNameCallback { @@ -219,7 +228,96 @@ fn main() { .expect("Couldn't write bindings!"); } -#[cfg(all(target_os = "linux", not(feature = "iceoryx")))] +#[allow(unused_variables)] +fn prepare_cyclonedds_src(src_dir: &str, out_dir: &Path, prefix: &str) -> PathBuf { + #[cfg(target_os = "windows")] + if !prefix.is_empty() { + let mut dst_dir = src_dir.to_string(); + dst_dir.push_str("-src"); + let dst_dir = out_dir.join(dst_dir); + + // Delete copied source directory if it already exists + if dst_dir.exists() { + fs::remove_dir_all(dst_dir.clone()).unwrap(); + } + copy_dir_recursive(&PathBuf::from(src_dir), &dst_dir).unwrap(); + + // Prefix tls_callback_func in cyclonedds-src/src/ddsrt/src/cdtors.c + let mut prefixed_func = prefix.to_string(); + prefixed_func.push_str("tls_callback_func"); + let cdtors = dst_dir + .join("src") + .join("ddsrt") + .join("src") + .join("cdtors.c"); + replace_in_file(&cdtors, "tls_callback_func", &prefixed_func).unwrap(); + + return dst_dir; + } + PathBuf::from(src_dir) +} + +#[allow(unused)] +fn copy_dir_recursive(src: &Path, dst: &Path) -> std::io::Result<()> { + println!( + "src = {}, dir = {}", + src.to_str().unwrap(), + dst.to_str().unwrap() + ); + if !dst.exists() { + fs::create_dir_all(dst)?; + } + + for entry in fs::read_dir(src)? { + let entry = entry?; + let path = entry.path(); + let dest_path = dst.join(entry.file_name()); + + if path.is_dir() { + copy_dir_recursive(&path, &dest_path)?; + } else { + fs::copy(&path, &dest_path)?; + } + } + Ok(()) +} + +#[allow(unused)] +fn replace_in_file(file_path: &Path, from: &str, to: &str) -> std::io::Result<()> { + // Read the file content into a string + let content = fs::read_to_string(file_path)?; + + // Replace all occurrences of `from` with `to` + let new_content = content.replace(from, to); + + // Write the modified content back to the file + let mut file = fs::OpenOptions::new() + .write(true) + .truncate(true) // Clear the file before writing + .open(file_path)?; + + file.write_all(new_content.as_bytes())?; + Ok(()) +} + +fn get_library_name(lib_name: &str) -> Option { + #[cfg(target_os = "linux")] + { + let mut file_name = String::from("lib"); + file_name.push_str(lib_name); + file_name.push_str(".a"); + Some(file_name) + } + #[cfg(target_os = "windows")] + { + let mut file_name = String::from(lib_name); + file_name.push_str(".lib"); + Some(file_name) + } + #[cfg(not(any(target_os = "linux", target_os = "windows")))] + None +} + fn get_defined_symbols(lib_dir: &Path, lib_name: &str) -> Result, String> { use std::io::{BufRead, BufReader}; @@ -229,7 +327,7 @@ fn get_defined_symbols(lib_dir: &Path, lib_name: &str) -> Result let symbol_file_path = lib_dir.to_path_buf().join(nm_file_name); let mut nm = cmake::Config::new("nm"); - nm.build_target("all") + nm.build_target("read_symbols") .define("LIB_PATH", lib_path.clone()) .build(); @@ -243,6 +341,11 @@ fn get_defined_symbols(lib_dir: &Path, lib_name: &str) -> Result Ok(line) => { let tokens: Vec<&str> = line.split_whitespace().collect(); let symbol = *tokens.last().unwrap(); + #[cfg(target_os = "windows")] + if !symbol.ends_with("tls_callback_func") { + result.insert(String::from(symbol)); + } + #[cfg(not(target_os = "windows"))] result.insert(String::from(symbol)); } Err(_) => return Err(format!("Failed to run nm on library {}", lib_name)), @@ -260,7 +363,6 @@ fn get_defined_symbols(lib_dir: &Path, lib_name: &str) -> Result } } -#[cfg(all(target_os = "linux", not(feature = "iceoryx")))] fn prefix_symbols( lib_dir: &Path, lib_name: &str, @@ -300,7 +402,7 @@ fn prefix_symbols( let mut objcopy = cmake::Config::new("objcopy"); objcopy - .build_target("all") + .build_target("mangle_library") .define("LIB_PATH", lib_file_path.clone()) .define("SYMBOL_FILE_PATH", symbol_file_path.clone()) .build(); diff --git a/nm/CMakeLists.txt b/nm/CMakeLists.txt index 300d5ce..f47d634 100644 --- a/nm/CMakeLists.txt +++ b/nm/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required(VERSION 3.12) project(NM) -# Include the CMakeFindBinUtils module to find nm -include(CMakeFindBinUtils) +if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + # Include the CMakeFindBinUtils module to find nm + include(CMakeFindBinUtils) +else() + find_program(CMAKE_NM llvm-nm) +endif() # Ensure nm is available if(NOT CMAKE_NM) diff --git a/objcopy/CMakeLists.txt b/objcopy/CMakeLists.txt index 5589699..86f7de8 100644 --- a/objcopy/CMakeLists.txt +++ b/objcopy/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required(VERSION 3.12) project(Objcopy) -# Include the CMakeFindBinUtils module to find objcopy -include(CMakeFindBinUtils) +if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + # Include the CMakeFindBinUtils module to find objcopy + include(CMakeFindBinUtils) +else() + find_program(CMAKE_OBJCOPY llvm-objcopy) +endif() # Ensure objcopy is available if(NOT CMAKE_OBJCOPY) From 7650eb28c900d1f13303c9784cf5e6739d67d823 Mon Sep 17 00:00:00 2001 From: Geoff Martin Date: Thu, 31 Oct 2024 10:08:50 +0000 Subject: [PATCH 2/4] Allow unused variables in get_library_name(). --- build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build.rs b/build.rs index d3682f6..4be1adc 100644 --- a/build.rs +++ b/build.rs @@ -300,6 +300,7 @@ fn replace_in_file(file_path: &Path, from: &str, to: &str) -> std::io::Result<() Ok(()) } +#[allow(unused_variables)] fn get_library_name(lib_name: &str) -> Option { #[cfg(target_os = "linux")] { From b34e3822fbc3fda679fd3dbde755106b7aa4a534 Mon Sep 17 00:00:00 2001 From: Geoff Martin Date: Thu, 31 Oct 2024 10:50:35 +0000 Subject: [PATCH 3/4] Bumping version number to 0.3.4. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 947cfc2..e2f6c78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyclors" -version = "0.3.3" +version = "0.3.4" authors = ["kydos "] license = "Apache-2.0" readme = "README.md" From 3ca4682016b260d9bdda828e0ab6bff99dbc72a3 Mon Sep 17 00:00:00 2001 From: Geoff Martin Date: Mon, 4 Nov 2024 10:47:24 +0000 Subject: [PATCH 4/4] Installing Rust toolchain as part of CI run to ensure fmt is available. --- .github/workflows/rust.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ab3f9c3..5376b12 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -24,6 +24,10 @@ jobs: - name: Install ACL if: startsWith(matrix.os,'ubuntu') run: sudo apt-get -y install acl-dev + - name: Install Rust toolchain + run: | + rustup show + rustup component add rustfmt clippy - name: Code format check uses: actions-rs/cargo@v1 with: