add windows support + use cmake_path to have colcon-cargo working

correctly
This commit is contained in:
Nadhmi JAZI 2023-09-14 12:21:18 +02:00 committed by Martin Dahl
parent 29404f1982
commit 64bc6af718
4 changed files with 126 additions and 29 deletions

View File

@ -1,5 +1,6 @@
use r2r_rcl::*; use r2r_rcl::*;
use std::ffi::CString; use std::ffi::CString;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Mutex, MutexGuard}; use std::sync::{Mutex, MutexGuard};
use lazy_static::lazy_static; use lazy_static::lazy_static;
@ -12,12 +13,24 @@ pub(crate) fn log_guard() -> MutexGuard<'static, ()> {
LOG_GUARD.lock().unwrap() 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. /// Don't call this directly, use the logging macros instead.
#[doc(hidden)] #[doc(hidden)]
pub fn log(msg: &str, logger_name: &str, file: &str, line: u32, severity: LogSeverity) { pub fn log(msg: &str, logger_name: &str, file: &str, line: u32, severity: LogSeverity) {
let _guard = log_guard(); 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 !is_init {
if cfg!(target_os = "windows") {
IS_INIT.store(true, Ordering::Relaxed);
}
let ret = unsafe { rcutils_logging_initialize() }; let ret = unsafe { rcutils_logging_initialize() };
if ret != RCL_RET_OK as i32 { if ret != RCL_RET_OK as i32 {
log::error!("could not create logging system (Err: {})", ret); log::error!("could not create logging system (Err: {})", ret);

View File

@ -1,18 +1,19 @@
use itertools::Itertools; use itertools::Itertools;
use os_str_bytes::RawOsString; use os_str_bytes::RawOsString;
use regex::*;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::Read; use std::io::Read;
use std::path::Path; use std::path::Path;
use regex::*;
#[cfg(not(feature = "doc-only"))] #[cfg(not(feature = "doc-only"))]
const SUPPORTED_ROS_DISTROS: &[&str] = &["foxy", "galactic", "humble", "rolling"]; const SUPPORTED_ROS_DISTROS: &[&str] = &["foxy", "galactic", "humble", "rolling"];
const WATCHED_ENV_VARS: &[&str] = &[ const WATCHED_ENV_VARS: &[&str] = &[
"AMENT_PREFIX_PATH", "AMENT_PREFIX_PATH",
"CMAKE_PREFIX_PATH",
"CMAKE_INCLUDE_DIRS", "CMAKE_INCLUDE_DIRS",
"CMAKE_LIBRARIES", "CMAKE_LIBRARIES",
"CMAKE_IDL_PACKAGES", "CMAKE_IDL_PACKAGES",
@ -49,10 +50,14 @@ pub fn setup_bindgen_builder() -> bindgen::Builder {
.default_enum_style(bindgen::EnumVariation::Rust { .default_enum_style(bindgen::EnumVariation::Rust {
non_exhaustive: false, non_exhaustive: false,
}); });
let split_char = if cfg!(target_os = "windows") {
';'
} else {
':'
};
if let Ok(cmake_includes) = env::var("CMAKE_INCLUDE_DIRS") { if let Ok(cmake_includes) = env::var("CMAKE_INCLUDE_DIRS") {
// we are running from cmake, do special thing. // we are running from cmake, do special thing.
let mut includes = cmake_includes.split(':').collect::<Vec<_>>(); let mut includes = cmake_includes.split(split_char).collect::<Vec<_>>();
includes.sort_unstable(); includes.sort_unstable();
includes.dedup(); includes.dedup();
@ -63,10 +68,17 @@ pub fn setup_bindgen_builder() -> bindgen::Builder {
} }
} else if !cfg!(feature = "doc-only") { } else if !cfg!(feature = "doc-only") {
let ament_prefix_var_name = "AMENT_PREFIX_PATH"; let ament_prefix_var_name = "AMENT_PREFIX_PATH";
let ament_prefix_var = let ament_prefix_var = if !cfg!(target_os = "windows") {
RawOsString::new(env::var_os(ament_prefix_var_name).expect("Source your ROS!")); RawOsString::new(env::var_os(ament_prefix_var_name).expect("Source your ROS!"))
} else {
for p in ament_prefix_var.split(":") { 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 path = Path::new(&p.to_os_str()).join("include");
let entries = std::fs::read_dir(path.clone()); let entries = std::fs::read_dir(path.clone());
@ -138,13 +150,22 @@ pub fn print_cargo_ros_distro() {
} }
pub fn print_cargo_link_search() { 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 env::var_os("CMAKE_INCLUDE_DIRS").is_some() {
if let Some(paths) = env::var_os("CMAKE_LIBRARIES") { if let Some(paths) = env::var_os("CMAKE_LIBRARIES") {
let paths = RawOsString::new(paths); let paths = RawOsString::new(paths);
paths paths
.split(":") .split(split_char)
.filter(|s| s.contains(".so") || s.contains(".dylib")) .filter(|s| {
s.contains(".so")
|| s.contains(".dylib")
|| s.contains(".dll")
|| s.contains(".lib")
})
.filter_map(|l| { .filter_map(|l| {
let l = l.to_os_str(); let l = l.to_os_str();
let parent = Path::new(&l).parent()?; let parent = Path::new(&l).parent()?;
@ -157,11 +178,30 @@ pub fn print_cargo_link_search() {
} else { } else {
let ament_prefix_var_name = "AMENT_PREFIX_PATH"; let ament_prefix_var_name = "AMENT_PREFIX_PATH";
if let Some(paths) = env::var_os(ament_prefix_var_name) { if let Some(paths) = env::var_os(ament_prefix_var_name) {
let paths = RawOsString::new(paths); let paths = if !cfg!(target_os = "windows") {
for path in paths.split(":") { RawOsString::new(paths)
let lib_path = Path::new(&path.to_os_str()).join("lib"); } else if let Some(cmake_prefix_var) = env::var_os("CMAKE_PREFIX_PATH") {
if let Some(s) = lib_path.to_str() { let mut cmake_paths = paths;
println!("cargo:rustc-link-search=native={}", s) 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<RosMsg> { pub fn get_wanted_messages() -> Vec<RosMsg> {
let split_char = if cfg!(target_os = "windows") {
';'
} else {
':'
};
let msgs = if let Ok(cmake_package_dirs) = env::var("CMAKE_IDL_PACKAGES") { let msgs = if let Ok(cmake_package_dirs) = env::var("CMAKE_IDL_PACKAGES") {
// CMAKE_PACKAGE_DIRS should be a (cmake) list of "cmake" dirs // 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 // 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/ // we can traverse back and then look for .msg files in msg/ srv/ action/
let dirs = cmake_package_dirs let dirs = cmake_package_dirs
.split(':') .split(split_char)
.flat_map(|i| Path::new(i).parent()) .flat_map(|i| Path::new(i).parent())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
get_ros_msgs_files(&dirs) get_ros_msgs_files(&dirs)
} else { } else {
// Else we look for all msgs we can find using the ament prefix path. // 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") { if !cfg!(target_os = "windows") {
let paths = ament_prefix_var if let Ok(ament_prefix_var) = env::var("AMENT_PREFIX_PATH") {
.split(':') let paths = ament_prefix_var
.map(Path::new) .split(split_char)
.collect::<Vec<_>>(); .map(Path::new)
.collect::<Vec<_>>();
get_ros_msgs(&paths) get_ros_msgs(&paths)
} else {
vec![]
}
} else { } 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::<Vec<_>>();
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::<Vec<_>>();
get_ros_msgs(&paths)
}
(_, Ok(cmake_prefix_var)) => {
let paths = cmake_prefix_var
.split(split_char)
.map(Path::new)
.collect::<Vec<_>>();
get_ros_msgs(&paths)
}
_ => vec![],
}
} }
}; };
@ -346,7 +419,7 @@ pub fn get_ros_msgs_files(paths: &[&Path]) -> Vec<String> {
pub fn parse_msgs(msgs: &[String]) -> Vec<RosMsg> { pub fn parse_msgs(msgs: &[String]) -> Vec<RosMsg> {
let v: Vec<Vec<&str>> = msgs let v: Vec<Vec<&str>> = msgs
.iter() .iter()
.map(|l| l.split('/').into_iter().take(3).collect()) .map(|l| l.split('/').take(3).collect())
.collect(); .collect();
// hack because I don't have time to find out the root cause of this at the moment. // 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() { fn test_camel_to_snake_case() {
assert_eq!(camel_to_snake("AB01CD02"), "ab01_cd02"); assert_eq!(camel_to_snake("AB01CD02"), "ab01_cd02");
assert_eq!(camel_to_snake("UnboundedSequences"), "unbounded_sequences"); 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"); assert_eq!(camel_to_snake("WStrings"), "w_strings");
} }
} }

View File

@ -5,7 +5,7 @@ use itertools::Either;
use itertools::Itertools; use itertools::Itertools;
use quote::format_ident; use quote::format_ident;
use quote::quote; use quote::quote;
use r2r_common::{RosMsg, camel_to_snake}; use r2r_common::{camel_to_snake, RosMsg};
use rayon::prelude::*; use rayon::prelude::*;
use std::fs::File; use std::fs::File;
use std::fs::OpenOptions; use std::fs::OpenOptions;

View File

@ -125,10 +125,18 @@ macro_rules! primitive_sequence {
primitive_sequence!(rosidl_runtime_c__float32, f32); primitive_sequence!(rosidl_runtime_c__float32, f32);
primitive_sequence!(rosidl_runtime_c__float64, f64); 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); 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__long_double, u128);
primitive_sequence!(rosidl_runtime_c__char, i8); primitive_sequence!(rosidl_runtime_c__char, i8);