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 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);

View File

@ -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::<Vec<_>>();
let mut includes = cmake_includes.split(split_char).collect::<Vec<_>>();
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,8 +178,26 @@ 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 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)
@ -167,23 +206,30 @@ pub fn print_cargo_link_search() {
}
}
}
}
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") {
// 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::<Vec<_>>();
get_ros_msgs_files(&dirs)
} else {
// Else we look for all msgs we can find using the ament prefix path.
if !cfg!(target_os = "windows") {
if let Ok(ament_prefix_var) = env::var("AMENT_PREFIX_PATH") {
let paths = ament_prefix_var
.split(':')
.split(split_char)
.map(Path::new)
.collect::<Vec<_>>();
@ -191,6 +237,33 @@ pub fn get_wanted_messages() -> Vec<RosMsg> {
} else {
vec![]
}
} else {
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![],
}
}
};
let msgs = parse_msgs(&msgs);
@ -346,7 +419,7 @@ pub fn get_ros_msgs_files(paths: &[&Path]) -> Vec<String> {
pub fn parse_msgs(msgs: &[String]) -> Vec<RosMsg> {
let v: Vec<Vec<&str>> = 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");
}
}

View File

@ -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;

View File

@ -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);