diff --git a/r2r/src/utils.rs b/r2r/src/utils.rs index 72e30f9..cb418cc 100644 --- a/r2r/src/utils.rs +++ b/r2r/src/utils.rs @@ -1,5 +1,6 @@ use r2r_rcl::*; use std::ffi::CString; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Mutex, MutexGuard}; use lazy_static::lazy_static; @@ -12,12 +13,24 @@ pub(crate) fn log_guard() -> MutexGuard<'static, ()> { LOG_GUARD.lock().unwrap() } +// for some hidden reason g_rcutils_logging_initialized +// is not found on windows even when rcutils.lib is linked +// as a work around using onwned is_init +static IS_INIT: AtomicBool = AtomicBool::new(false); + /// Don't call this directly, use the logging macros instead. #[doc(hidden)] pub fn log(msg: &str, logger_name: &str, file: &str, line: u32, severity: LogSeverity) { let _guard = log_guard(); - let is_init = unsafe { g_rcutils_logging_initialized }; + let is_init = if cfg!(target_os = "windows") { + IS_INIT.load(Ordering::Relaxed) + } else { + unsafe { g_rcutils_logging_initialized } + }; if !is_init { + if cfg!(target_os = "windows") { + IS_INIT.store(true, Ordering::Relaxed); + } let ret = unsafe { rcutils_logging_initialize() }; if ret != RCL_RET_OK as i32 { log::error!("could not create logging system (Err: {})", ret); diff --git a/r2r_common/src/lib.rs b/r2r_common/src/lib.rs index 3f7edca..ea97718 100644 --- a/r2r_common/src/lib.rs +++ b/r2r_common/src/lib.rs @@ -1,18 +1,19 @@ use itertools::Itertools; use os_str_bytes::RawOsString; +use regex::*; use sha2::{Digest, Sha256}; use std::collections::HashMap; use std::env; use std::fs::{self, File}; use std::io::Read; use std::path::Path; -use regex::*; #[cfg(not(feature = "doc-only"))] const SUPPORTED_ROS_DISTROS: &[&str] = &["foxy", "galactic", "humble", "rolling"]; const WATCHED_ENV_VARS: &[&str] = &[ "AMENT_PREFIX_PATH", + "CMAKE_PREFIX_PATH", "CMAKE_INCLUDE_DIRS", "CMAKE_LIBRARIES", "CMAKE_IDL_PACKAGES", @@ -49,10 +50,14 @@ pub fn setup_bindgen_builder() -> bindgen::Builder { .default_enum_style(bindgen::EnumVariation::Rust { non_exhaustive: false, }); - + let split_char = if cfg!(target_os = "windows") { + ';' + } else { + ':' + }; if let Ok(cmake_includes) = env::var("CMAKE_INCLUDE_DIRS") { // we are running from cmake, do special thing. - let mut includes = cmake_includes.split(':').collect::>(); + let mut includes = cmake_includes.split(split_char).collect::>(); includes.sort_unstable(); includes.dedup(); @@ -63,10 +68,17 @@ pub fn setup_bindgen_builder() -> bindgen::Builder { } } else if !cfg!(feature = "doc-only") { let ament_prefix_var_name = "AMENT_PREFIX_PATH"; - let ament_prefix_var = - RawOsString::new(env::var_os(ament_prefix_var_name).expect("Source your ROS!")); - - for p in ament_prefix_var.split(":") { + let ament_prefix_var = if !cfg!(target_os = "windows") { + RawOsString::new(env::var_os(ament_prefix_var_name).expect("Source your ROS!")) + } else { + let mut ament_str = env::var_os(ament_prefix_var_name).expect("Source your ROS!"); + if let Some(cmake_prefix_var) = env::var_os("CMAKE_PREFIX_PATH") { + ament_str.push(";"); + ament_str.push(cmake_prefix_var); + } + RawOsString::new(ament_str) + }; + for p in ament_prefix_var.split(split_char) { let path = Path::new(&p.to_os_str()).join("include"); let entries = std::fs::read_dir(path.clone()); @@ -138,13 +150,22 @@ pub fn print_cargo_ros_distro() { } pub fn print_cargo_link_search() { + let split_char = if cfg!(target_os = "windows") { + ';' + } else { + ':' + }; if env::var_os("CMAKE_INCLUDE_DIRS").is_some() { if let Some(paths) = env::var_os("CMAKE_LIBRARIES") { let paths = RawOsString::new(paths); - paths - .split(":") - .filter(|s| s.contains(".so") || s.contains(".dylib")) + .split(split_char) + .filter(|s| { + s.contains(".so") + || s.contains(".dylib") + || s.contains(".dll") + || s.contains(".lib") + }) .filter_map(|l| { let l = l.to_os_str(); let parent = Path::new(&l).parent()?; @@ -157,11 +178,30 @@ pub fn print_cargo_link_search() { } else { let ament_prefix_var_name = "AMENT_PREFIX_PATH"; if let Some(paths) = env::var_os(ament_prefix_var_name) { - let paths = RawOsString::new(paths); - for path in paths.split(":") { - let lib_path = Path::new(&path.to_os_str()).join("lib"); - if let Some(s) = lib_path.to_str() { - println!("cargo:rustc-link-search=native={}", s) + let paths = if !cfg!(target_os = "windows") { + RawOsString::new(paths) + } else if let Some(cmake_prefix_var) = env::var_os("CMAKE_PREFIX_PATH") { + let mut cmake_paths = paths; + cmake_paths.push(";"); + cmake_paths.push(cmake_prefix_var); + RawOsString::new(cmake_paths) + } else { + RawOsString::new(paths) + }; + for path in paths.split(split_char) { + if cfg!(target_os = "windows") { + let lib_path = Path::new(&path.to_os_str()).join("Lib"); + if !lib_path.exists() { + continue; + } + if let Some(s) = lib_path.to_str() { + println!("cargo:rustc-link-search={}", s); + } + } else { + let lib_path = Path::new(&path.to_os_str()).join("lib"); + if let Some(s) = lib_path.to_str() { + println!("cargo:rustc-link-search=native={}", s) + } } } } @@ -169,27 +209,60 @@ pub fn print_cargo_link_search() { } pub fn get_wanted_messages() -> Vec { + let split_char = if cfg!(target_os = "windows") { + ';' + } else { + ':' + }; let msgs = if let Ok(cmake_package_dirs) = env::var("CMAKE_IDL_PACKAGES") { // CMAKE_PACKAGE_DIRS should be a (cmake) list of "cmake" dirs // e.g. For each dir install/r2r_minimal_node_msgs/share/r2r_minimal_node_msgs/cmake // we can traverse back and then look for .msg files in msg/ srv/ action/ let dirs = cmake_package_dirs - .split(':') + .split(split_char) .flat_map(|i| Path::new(i).parent()) .collect::>(); get_ros_msgs_files(&dirs) } else { // Else we look for all msgs we can find using the ament prefix path. - if let Ok(ament_prefix_var) = env::var("AMENT_PREFIX_PATH") { - let paths = ament_prefix_var - .split(':') - .map(Path::new) - .collect::>(); + if !cfg!(target_os = "windows") { + if let Ok(ament_prefix_var) = env::var("AMENT_PREFIX_PATH") { + let paths = ament_prefix_var + .split(split_char) + .map(Path::new) + .collect::>(); - get_ros_msgs(&paths) + get_ros_msgs(&paths) + } else { + vec![] + } } else { - vec![] + match (env::var("AMENT_PREFIX_PATH"), env::var("CMAKE_PREFIX_PATH")) { + (Ok(ament_prefix_var), Ok(cmake_prefix_var)) => { + let mut paths = ament_prefix_var + .split(split_char) + .map(Path::new) + .collect::>(); + paths.extend(cmake_prefix_var.split(split_char).map(Path::new)); + get_ros_msgs(&paths) + } + (Ok(ament_prefix_var), _) => { + let paths = ament_prefix_var + .split(split_char) + .map(Path::new) + .collect::>(); + get_ros_msgs(&paths) + } + (_, Ok(cmake_prefix_var)) => { + let paths = cmake_prefix_var + .split(split_char) + .map(Path::new) + .collect::>(); + get_ros_msgs(&paths) + } + _ => vec![], + } } }; @@ -346,7 +419,7 @@ pub fn get_ros_msgs_files(paths: &[&Path]) -> Vec { pub fn parse_msgs(msgs: &[String]) -> Vec { let v: Vec> = msgs .iter() - .map(|l| l.split('/').into_iter().take(3).collect()) + .map(|l| l.split('/').take(3).collect()) .collect(); // hack because I don't have time to find out the root cause of this at the moment. @@ -431,7 +504,10 @@ std_msgs/msg/String fn test_camel_to_snake_case() { assert_eq!(camel_to_snake("AB01CD02"), "ab01_cd02"); assert_eq!(camel_to_snake("UnboundedSequences"), "unbounded_sequences"); - assert_eq!(camel_to_snake("BoundedPlainUnboundedSequences"), "bounded_plain_unbounded_sequences"); + assert_eq!( + camel_to_snake("BoundedPlainUnboundedSequences"), + "bounded_plain_unbounded_sequences" + ); assert_eq!(camel_to_snake("WStrings"), "w_strings"); } } diff --git a/r2r_msg_gen/build.rs b/r2r_msg_gen/build.rs index 7ccefa8..33803a2 100644 --- a/r2r_msg_gen/build.rs +++ b/r2r_msg_gen/build.rs @@ -5,7 +5,7 @@ use itertools::Either; use itertools::Itertools; use quote::format_ident; use quote::quote; -use r2r_common::{RosMsg, camel_to_snake}; +use r2r_common::{camel_to_snake, RosMsg}; use rayon::prelude::*; use std::fs::File; use std::fs::OpenOptions; diff --git a/r2r_rcl/src/lib.rs b/r2r_rcl/src/lib.rs index 0c13ba5..4ebdb4f 100644 --- a/r2r_rcl/src/lib.rs +++ b/r2r_rcl/src/lib.rs @@ -125,10 +125,18 @@ macro_rules! primitive_sequence { primitive_sequence!(rosidl_runtime_c__float32, f32); primitive_sequence!(rosidl_runtime_c__float64, f64); -#[cfg(any(all(target_os = "macos", target_arch = "aarch64"), target_arch = "arm"))] +#[cfg(any( + all(target_os = "macos", target_arch = "aarch64"), + target_arch = "arm", + target_os = "windows" +))] primitive_sequence!(rosidl_runtime_c__long_double, f64); -#[cfg(not(any(all(target_os = "macos", target_arch = "aarch64"), target_arch = "arm")))] +#[cfg(not(any( + all(target_os = "macos", target_arch = "aarch64"), + target_arch = "arm", + target_os = "windows" +)))] primitive_sequence!(rosidl_runtime_c__long_double, u128); primitive_sequence!(rosidl_runtime_c__char, i8);