Skip to content

Commit

Permalink
Tidied code and set version to 0.3.2.
Browse files Browse the repository at this point in the history
  • Loading branch information
gmartin82 committed Oct 14, 2024
1 parent 28d99c8 commit 223909b
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cyclors"
version = "0.3.1"
version = "0.3.2"
authors = ["kydos <[email protected]>"]
license = "Apache-2.0"
readme = "README.md"
Expand Down
167 changes: 107 additions & 60 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
extern crate bindgen;

#[allow(unused_imports)]
use std::collections::HashSet;
use std::fs::File;
#[allow(unused_imports)]
use std::io::{LineWriter, Write};
use std::path::{Path, PathBuf};
#[allow(unused_imports)]
use std::process::Command;
use std::{env, fs};

Expand Down Expand Up @@ -147,29 +150,28 @@ fn main() {
.clang_arg(format!("-I{}", cyclocut_include.to_str().unwrap()))
.generate_comments(false);

#[allow(unused_assignments)]
#[allow(unused)]
let mut prefix = String::from("");

// Prefix symbols in Iceoryx, Cyclone DDS and Cyclocut libraries to ensure uniqueness
#[cfg(target_os = "linux")]
// Prefix symbols in Cyclone DDS and Cyclocut libraries to ensure uniqueness
#[cfg(all(target_os = "linux", not(feature = "iceoryx")))]
{
// Prefix = cyclors_<version>_
prefix = env::var("CARGO_PKG_VERSION").unwrap().replace(".", "_");
prefix.insert_str(0, "cyclors_");
prefix.push('_');
println!("Library prefix: {}", prefix);

let mut symbols = HashSet::new();

let cyclone_symbols = get_defined_symbols(&cyclonedds_lib, "libddsc.a")
.expect("Failed to get symbols from libddsc.a!");
symbols.extend(cyclone_symbols);
prefix_symbols(&cyclonedds_lib, "libddsc.a", &prefix, &symbols);
prefix_symbols(&cyclonedds_lib, "libddsc.a", &prefix, &symbols).unwrap();

let cyclocut_symbols = get_defined_symbols(&cyclocut_lib, "libcdds-util.a")
.expect("Failed to get symbols from libcdds-util.a!");
symbols.extend(cyclocut_symbols);
prefix_symbols(&cyclocut_lib, "libcdds-util.a", &prefix, &symbols);
prefix_symbols(&cyclocut_lib, "libcdds-util.a", &prefix, &symbols).unwrap();

#[derive(Debug)]
struct PrefixLinkNameCallback {
Expand All @@ -186,7 +188,6 @@ fn main() {
true => {
let mut prefix = self.prefix.clone();
prefix.push_str(item_info.name);
//println!("bindgen: {prefix}");
Some(prefix)
}
false => None,
Expand All @@ -208,7 +209,7 @@ fn main() {
.blocklist_type("^(.*IMAGE_TLS_DIRECTORY.*)$");

// Set link name prefix on additional wrapStringper functions
generate_template_src(&prefix);
generate_template_src(&prefix, &out_dir).unwrap();

// Generate bindings
let bindings = bindings.generate().expect("Unable to generate bindings");
Expand All @@ -218,79 +219,125 @@ fn main() {
.expect("Couldn't write bindings!");
}

#[cfg(all(target_os = "linux", not(feature = "iceoryx")))]
fn get_defined_symbols(lib_dir: &Path, lib_name: &str) -> Result<HashSet<String>, String> {
let lib_path = lib_dir.to_path_buf().join(lib_name);
println!(
"Getting defined symbols from {}",
lib_path.to_str().unwrap()
);
let output = Command::new("nm")

let rc = Command::new("nm")
.arg("--defined-only")
.arg("--print-file-name")
.arg(lib_path)
.output()
.expect("Failed to run nm");

let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

match stderr.is_empty() {
true => {
let mut result: HashSet<String> = HashSet::new();
for line in stdout.lines() {
let tokens: Vec<&str> = line.split_whitespace().collect();
let symbol = *tokens.last().unwrap();
result.insert(String::from(symbol));
.output();

match rc {
Ok(output) => {
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

match stderr.is_empty() {
true => {
let mut result: HashSet<String> = HashSet::new();
for line in stdout.lines() {
let tokens: Vec<&str> = line.split_whitespace().collect();
let symbol = *tokens.last().unwrap();
result.insert(String::from(symbol));
}
Ok(result)
}
false => Err(format!(
"Failed to run nm on library {} (stderr: {})",
lib_name,
String::from(stderr)
)),
}
Ok(result)
}
false => Err(String::from(stderr)),
Err(_) => Err(format!("Failed to run nm on library {}", lib_name)),
}
}

fn prefix_symbols(lib_dir: &Path, lib_name: &str, prefix: &str, symbols: &HashSet<String>) {
#[cfg(all(target_os = "linux", not(feature = "iceoryx")))]
fn prefix_symbols(
lib_dir: &Path,
lib_name: &str,
prefix: &str,
symbols: &HashSet<String>,
) -> Result<(), String> {
let mut objcopy_file_name = lib_name.to_owned();
objcopy_file_name.push_str(".objcopy");

let lib_file_path = lib_dir.to_path_buf().join(lib_name);
let symbol_file_path = lib_dir.to_path_buf().join(objcopy_file_name);
let symbol_file = File::create(symbol_file_path.clone()).expect("Failed to create symbol file");
let mut symbol_file = LineWriter::new(symbol_file);

for symbol in symbols {
let mut symbol_arg = symbol.clone();
symbol_arg.push(' ');
symbol_arg.push_str(prefix);
symbol_arg.push_str(symbol);
symbol_arg.push('\n');
symbol_file
.write_all(symbol_arg.as_bytes())
.expect("Failed to write symbol file");
}
symbol_file.flush().expect("Failed to flush symbol file");

let arg = format!("--redefine-syms={}", symbol_file_path.to_str().unwrap());
match File::create(symbol_file_path.clone()) {
Ok(symbol_file) => {
let mut symbol_file = LineWriter::new(symbol_file);

for symbol in symbols {
let mut symbol_arg = symbol.clone();
symbol_arg.push(' ');
symbol_arg.push_str(prefix);
symbol_arg.push_str(symbol);
symbol_arg.push('\n');
if symbol_file.write_all(symbol_arg.as_bytes()).is_err() {
return Err(format!(
"Failed to write symbol file for library {}",
lib_name
));
}
}

Command::new("objcopy")
.arg(arg)
.arg(lib_file_path)
.output()
.expect("Failed to run objcopy");
if symbol_file.flush().is_err() {
return Err(format!(
"Failed to write symbol file for library {}",
lib_name
));
}
let arg = format!("--redefine-syms={}", symbol_file_path.to_str().unwrap());
match Command::new("objcopy").arg(arg).arg(lib_file_path).output() {
Ok(_) => Ok(()),
Err(_) => Err(format!("Failed to run objcopy on library {}", lib_name)),
}
}
Err(_) => Err(format!(
"Failed to create symbol file for library {}",
lib_name
)),
}
}

fn generate_template_src(prefix: &str) {
fn generate_template_src(prefix: &str, out_dir: &Path) -> Result<(), String> {
let src_path = Path::new("src/functions.template");
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR not set"));
let dst_path = out_dir.join("functions.rs");

let mut contents = fs::read_to_string(src_path).expect("Failed to read the source file.");
contents = contents.replace("<prefix>", prefix);

let mut file =
File::create(&dst_path).expect("Failed to open the destination file for writing!");
file.write_all(contents.as_bytes())
.expect("Failed to write the modified content to the destination file.");
match fs::read_to_string(src_path) {
Ok(mut contents) => {
contents = contents.replace("<prefix>", prefix);

match File::create(&dst_path) {
Ok(mut file) => {
if file.write_all(contents.as_bytes()).is_err() {
let path = dst_path.to_str().unwrap();
return Err(format!(
"Failed to write the modified content to the destination file {}",
path
));
}

println!("cargo:rerun-if-changed=src/lib.rs");
println!("cargo:rerun-if-changed=src/functions.template");
println!("cargo:rerun-if-changed=src/lib.rs");
println!("cargo:rerun-if-changed=src/functions.template");
Ok(())
}
Err(_) => {
let path = dst_path.to_str().unwrap();
Err(format!(
"Failed to open the destination file ({}) for writing",
path
))
}
}
}
Err(_) => Err(String::from(
"Failed to read the source file src/functions.template",
)),
}
}

0 comments on commit 223909b

Please sign in to comment.