From 73d448eb696bfa4a4d21705415f93a955992e403 Mon Sep 17 00:00:00 2001 From: David Laseca Perez Date: Tue, 8 Sep 2026 16:39:50 +0200 Subject: [PATCH 1/2] micro-ROS Lyrical patch * micro-ROS changes over dashing * Added and updated security directory (#1) * RCUTILS_NO_FILESYSTEM and RCUTILS_AVOID_DYNAMIC_ALLOCATION (#2) - No filesystem options; default allocators write access - Avoid dynamic allocation and no filesystem on error handling - Error handling template; new allocator approach * Add test_security_directory test from rcl (#3) * Zephyr fixes (#4) * CMake refactor (#5) * Update approach (#6) - Remove target_compile_definitions and refactor flags install - Added RCUTILS_NO_FILESYSTEM on new functions * Updates 17092020 * Fix atomics 64bits (#9) - Add hashing and lock pool * Updates 09102020 * Release micro-ROS Foxy (#8) - Update filesystem; adjust logger level; cleaning * Remove build warning (#10) - avoid not used warnings * Reduce error handling static size (#14) (#15) * Revert "Revert "Install headers to include/${PROJECT_NAME} (#351)"" * Fix atomic 64 b description (#17) (#18) * Add fork checker for humble * Don't link dl library when not needed (#28) * Revert "Set hints to find the python version we actually want. (#451)" * Fix struct tm init * Add PRId64 * Don't export dl library when not used (#33) (#34) * Remove unnecessary folder (#42) * Update CI (backport #43) (#46) - Add CI and nightly for each distro; update git version; skip tests - Change nightly to weekly; change master to rolling in fork checker * Add RCUTILS_NO_PROCESS_SUPPORT option to build without fork/exec/wait (#50) * Update CI (#51) * Fix thread issues added upstream (backport #56) (#57) * Fix weekly CI (backport #58) (#60) Dropped during the rebase as superseded by upstream: * Don't export dl library when not used (#33) (#34) Co-authored-by: Pablo Garrido Co-authored-by: Jose Antonio Moral Co-authored-by: Blazej Sowa Co-authored-by: Anton Casas Co-authored-by: Eugenio Collado Co-authored-by: Carlos Espinoza Curto <148376273+Carlosespicur@users.noreply.github.com> Co-authored-by: Jimmy McElwain Signed-off-by: David Laseca --- .github/workflows/fork_checker.yml | 36 +++++++ .github/workflows/humble-ci.yml | 15 +++ .github/workflows/jazzy-ci.yml | 15 +++ .github/workflows/kilted-ci.yml | 15 +++ .github/workflows/lyrical-ci.yml | 15 +++ .github/workflows/reusable-ci.yml | 54 ++++++++++ .github/workflows/rolling-ci.yml | 15 +++ .github/workflows/weekly-ci.yml | 44 ++++++++ CMakeLists.txt | 59 +++++++---- include/rcutils/allocator.h | 15 +++ include/rcutils/configuration_flags.h.in | 20 ++++ include/rcutils/error_handling.h | 29 +++++- include/rcutils/logging.h | 2 +- include/rcutils/logging_macros.h | 2 +- include/rcutils/macros.h | 6 +- include/rcutils/security_directory.h | 67 +++++++++++++ include/rcutils/testing/fault_injection.h | 13 +++ src/allocator.c | 29 ++++-- src/atomic_64bits.c | 92 +++++++++++++++++ src/error_handling_helpers.h | 4 + src/filesystem.c | 117 ++++++++++++++++++++++ src/process.c | 27 ++++- src/shared_library.c | 40 ++++++++ src/time.c | 13 +++ src/time_unix.c | 2 +- 25 files changed, 712 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/fork_checker.yml create mode 100644 .github/workflows/humble-ci.yml create mode 100644 .github/workflows/jazzy-ci.yml create mode 100644 .github/workflows/kilted-ci.yml create mode 100644 .github/workflows/lyrical-ci.yml create mode 100644 .github/workflows/reusable-ci.yml create mode 100644 .github/workflows/rolling-ci.yml create mode 100644 .github/workflows/weekly-ci.yml create mode 100644 include/rcutils/configuration_flags.h.in create mode 100644 include/rcutils/security_directory.h create mode 100644 src/atomic_64bits.c diff --git a/.github/workflows/fork_checker.yml b/.github/workflows/fork_checker.yml new file mode 100644 index 00000000..565e2ea3 --- /dev/null +++ b/.github/workflows/fork_checker.yml @@ -0,0 +1,36 @@ +name: micro-ROS fork Update Checker +on: + workflow_dispatch: + inputs: + name: + description: "Manual trigger" + schedule: + - cron: '0 4 * * *' + +jobs: + micro_ros_fork_update_check: + runs-on: ubuntu-latest + container: ubuntu:20.04 + strategy: + fail-fast: false + matrix: + branches: [humble, jazzy, kilted, lyrical, rolling] + steps: + - name: Check + id: check + shell: bash + run: | + apt update; apt install -y git + REPO=$(echo ${{ github.repository }} | awk '{split($0,a,"/"); print a[2]}') + git clone -b ${{ matrix.branches }} https://github.com/micro-ros/$REPO + cd $REPO + git remote add ros2 https://github.com/ros2/$REPO + git fetch ros2 + git fetch origin + echo "::set-output name=merge_required::true" + CMP=$(git rev-list --left-right --count ros2/${{ matrix.branches }}...origin/${{ matrix.branches }} | awk '{print $1}') + if [ $CMP = "0" ]; then echo "::set-output name=merge_required::false"; fi + + - name: Alert + if: ${{ steps.check.outputs.merge_required == 'true' }} + run: exit 1 diff --git a/.github/workflows/humble-ci.yml b/.github/workflows/humble-ci.yml new file mode 100644 index 00000000..d7e7b4a9 --- /dev/null +++ b/.github/workflows/humble-ci.yml @@ -0,0 +1,15 @@ +name: rcutils CI Humble + +on: + push: + branches: [ humble ] + pull_request: + branches: [ humble ] + +jobs: + humble-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + os: ubuntu-22.04 + docker-image: ubuntu:jammy + ros-distribution: humble diff --git a/.github/workflows/jazzy-ci.yml b/.github/workflows/jazzy-ci.yml new file mode 100644 index 00000000..434ca7df --- /dev/null +++ b/.github/workflows/jazzy-ci.yml @@ -0,0 +1,15 @@ +name: rcutils CI Jazzy + +on: + push: + branches: [ jazzy ] + pull_request: + branches: [ jazzy ] + +jobs: + jazzy-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + os: ubuntu-24.04 + docker-image: ubuntu:noble + ros-distribution: jazzy diff --git a/.github/workflows/kilted-ci.yml b/.github/workflows/kilted-ci.yml new file mode 100644 index 00000000..ba8f9b36 --- /dev/null +++ b/.github/workflows/kilted-ci.yml @@ -0,0 +1,15 @@ +name: rcutils CI Kilted + +on: + push: + branches: [ kilted ] + pull_request: + branches: [ kilted ] + +jobs: + kilted-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + os: ubuntu-24.04 + docker-image: ubuntu:noble + ros-distribution: kilted diff --git a/.github/workflows/lyrical-ci.yml b/.github/workflows/lyrical-ci.yml new file mode 100644 index 00000000..747d20c4 --- /dev/null +++ b/.github/workflows/lyrical-ci.yml @@ -0,0 +1,15 @@ +name: rcutils CI Lyrical + +on: + push: + branches: [ lyrical ] + pull_request: + branches: [ lyrical ] + +jobs: + lyrical-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + os: ubuntu-26.04 + docker-image: ubuntu:resolute + ros-distribution: lyrical diff --git a/.github/workflows/reusable-ci.yml b/.github/workflows/reusable-ci.yml new file mode 100644 index 00000000..c0106712 --- /dev/null +++ b/.github/workflows/reusable-ci.yml @@ -0,0 +1,54 @@ +name: Reusable rcutils CI + +on: + workflow_call: + inputs: + branch: + description: "The rcutils branch to build. Leave unset for push and pull_request." + required: false + default: "" + type: string + os: + description: "The OS to use for the workflow" + required: true + type: string + docker-image: + description: "The docker image to use for the workflow" + required: true + type: string + ros-distribution: + description: "The ROS distribution to use for the workflow" + required: true + type: string + +jobs: + build: + runs-on: ${{ inputs.os }} + strategy: + fail-fast: false + container: + image: ${{ inputs.docker-image }} + steps: + + - run: | + apt-get update && apt-get install -y git + shell: bash + + - name: Setup ROS 2 + uses: ros-tooling/setup-ros@0.7.19 + with: + required-ros-distributions: ${{ inputs.ros-distribution }} + + - name : Download and install rcutils-dependencies + run: | + apt-get install ros-${{ inputs.ros-distribution }}-mimick-vendor + apt-get -y install ros-${{ inputs.ros-distribution }}-performance-test-fixture + + # This action clones the repository itself, so no checkout step is needed. + # When ref is empty it uses the branch that triggered the run. + - uses : ros-tooling/action-ros-ci@0.4.8 + with: + package-name: "rcutils" + target-ros2-distro: ${{ inputs.ros-distribution }} + ref: ${{ inputs.branch }} + skip-tests: true diff --git a/.github/workflows/rolling-ci.yml b/.github/workflows/rolling-ci.yml new file mode 100644 index 00000000..aef23e0a --- /dev/null +++ b/.github/workflows/rolling-ci.yml @@ -0,0 +1,15 @@ +name: rcutils CI Rolling + +on: + push: + branches: [ rolling ] + pull_request: + branches: [ rolling ] + +jobs: + rolling-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + os: ubuntu-24.04 + docker-image: ubuntu:noble + ros-distribution: rolling diff --git a/.github/workflows/weekly-ci.yml b/.github/workflows/weekly-ci.yml new file mode 100644 index 00000000..99a0a66f --- /dev/null +++ b/.github/workflows/weekly-ci.yml @@ -0,0 +1,44 @@ +name: rcutils weekly CI (all distributions) + +on: + schedule: + # Run once per week to detect broken dependencies. + - cron: '59 23 * * 0' + workflow_dispatch: + +jobs: + humble-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + branch: humble + os: ubuntu-22.04 + docker-image: ubuntu:jammy + ros-distribution: humble + jazzy-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + branch: jazzy + os: ubuntu-24.04 + docker-image: ubuntu:noble + ros-distribution: jazzy + kilted-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + branch: kilted + os: ubuntu-24.04 + docker-image: ubuntu:noble + ros-distribution: kilted + lyrical-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + branch: lyrical + os: ubuntu-26.04 + docker-image: ubuntu:resolute + ros-distribution: lyrical + rolling-ci: + uses: ./.github/workflows/reusable-ci.yml + with: + branch: rolling + os: ubuntu-24.04 + docker-image: ubuntu:noble + ros-distribution: rolling diff --git a/CMakeLists.txt b/CMakeLists.txt index db6c035a..d4584be1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,14 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.12) project(rcutils) +option(RCUTILS_NO_THREAD_SUPPORT "Disable thread support." OFF) +option(RCUTILS_NO_FILESYSTEM "Disable filesystem usage." OFF) +option(RCUTILS_NO_PROCESS_SUPPORT "Disable process support." OFF) +option(RCUTILS_AVOID_DYNAMIC_ALLOCATION "Disable dynamic allocations." OFF) +option(RCUTILS_NO_64_ATOMIC "Enable alternative support for 64 bits atomic operations in platforms with no native support." OFF) +option(RCUTILS_MICROROS "Flag for building micro-ROS." ON) + include(CheckLibraryExists) find_package(ament_cmake REQUIRED) @@ -17,7 +24,7 @@ if(UNIX AND NOT APPLE) endif() endif() -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if(NOT RCUTILS_MICROROS AND (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")) # enables building a static library but later link it into a dynamic library add_compile_options(-fPIC) endif() @@ -38,7 +45,7 @@ endif() set(rcutils_sources src/allocator.c src/array_list.c - src/base64.c + $<$>:src/base64.c> src/char_array.c src/cmdline_parser.c src/env.c @@ -66,6 +73,7 @@ set(rcutils_sources src/time.c ${time_impl_c} src/uint8_array.c + $<$:src/atomic_64bits.c> ) set_source_files_properties( ${rcutils_sources} @@ -76,6 +84,7 @@ add_library( ${rcutils_sources}) target_include_directories(${PROJECT_NAME} PUBLIC "$" + "$" "$") # Causes the visibility macros to use dllexport rather than dllimport, @@ -85,11 +94,17 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE "RCUTILS_BUILDING_DLL") if(BUILD_TESTING AND NOT RCUTILS_DISABLE_FAULT_INJECTION) target_compile_definitions(${PROJECT_NAME} PUBLIC RCUTILS_ENABLE_FAULT_INJECTION) endif() +configure_file( + "${PROJECT_SOURCE_DIR}/include/rcutils/configuration_flags.h.in" + "${PROJECT_BINARY_DIR}/include/rcutils/configuration_flags.h" +) target_link_libraries(${PROJECT_NAME} - ${CMAKE_DL_LIBS} ament_cmake_ros_core::ament_ros_defaults ) +if(NOT RCUTILS_NO_FILESYSTEM) + target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS}) +endif() check_library_exists(atomic __atomic_load_8 "" HAVE_LIBATOMICS) @@ -549,17 +564,19 @@ if(BUILD_TESTING) ) endif() - ament_add_gtest(test_process - test/test_process.cpp - ) - if(TARGET test_process) - target_link_libraries(test_process - ${PROJECT_NAME} - ament_cmake_ros_core::ament_ros_defaults + if(NOT RCUTILS_NO_PROCESS_SUPPORT) + ament_add_gtest(test_process + test/test_process.cpp ) - target_compile_definitions(test_process PRIVATE - "CMAKE_COMMAND=${CMAKE_COMMAND}") - file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/file with space.txt") + if(TARGET test_process) + target_link_libraries(test_process + ${PROJECT_NAME} + ament_cmake_ros_core::ament_ros_defaults + ) + target_compile_definitions(test_process PRIVATE + "CMAKE_COMMAND=${CMAKE_COMMAND}") + file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/file with space.txt") + endif() endif() ament_add_gtest(test_logging_custom_env test/test_logging_custom_env.cpp @@ -676,11 +693,13 @@ if(BUILD_TESTING) target_link_libraries(benchmark_err_handle ${PROJECT_NAME} ament_cmake_ros_core::ament_ros_defaults) endif() - ament_add_gtest(test_base64 - test/test_base64.cpp - ) - if(TARGET test_base64) - target_link_libraries(test_base64 ${PROJECT_NAME} ament_cmake_ros_core::ament_ros_defaults) + if(NOT RCUTILS_MICROROS) + ament_add_gtest(test_base64 + test/test_base64.cpp + ) + if(TARGET test_base64) + target_link_libraries(test_base64 ${PROJECT_NAME} ament_cmake_ros_core::ament_ros_defaults) + endif() endif() endif() @@ -696,5 +715,5 @@ ament_export_dependencies(ament_cmake ament_cmake_ros_core) ament_package() install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION include/${PROJECT_NAME}) diff --git a/include/rcutils/allocator.h b/include/rcutils/allocator.h index b6c76ba6..5547db28 100644 --- a/include/rcutils/allocator.h +++ b/include/rcutils/allocator.h @@ -85,6 +85,21 @@ RCUTILS_WARN_UNUSED rcutils_allocator_t rcutils_get_zero_initialized_allocator(void); +/// Set rcutils default allocators. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + */ +RCUTILS_PUBLIC +RCUTILS_WARN_UNUSED +bool +rcutils_set_default_allocator(rcutils_allocator_t * allocator); + /// Return a properly initialized rcutils_allocator_t with default values. /** * This defaults to: diff --git a/include/rcutils/configuration_flags.h.in b/include/rcutils/configuration_flags.h.in new file mode 100644 index 00000000..a406eb12 --- /dev/null +++ b/include/rcutils/configuration_flags.h.in @@ -0,0 +1,20 @@ + +#ifndef RCUTILS__CONFIGURATION_FLAGS_H_ +#define RCUTILS__CONFIGURATION_FLAGS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#cmakedefine RCUTILS_NO_FILESYSTEM +#cmakedefine RCUTILS_NO_PROCESS_SUPPORT +#cmakedefine RCUTILS_AVOID_DYNAMIC_ALLOCATION +#cmakedefine RCUTILS_NO_THREAD_SUPPORT +#cmakedefine RCUTILS_MICROROS + +#ifdef __cplusplus +} +#endif + +#endif // RCUTILS__CONFIGURATION_FLAGS_H_ \ No newline at end of file diff --git a/include/rcutils/error_handling.h b/include/rcutils/error_handling.h index 6fc6ee37..f6701578 100644 --- a/include/rcutils/error_handling.h +++ b/include/rcutils/error_handling.h @@ -37,7 +37,9 @@ extern "C" #include "rcutils/testing/fault_injection.h" #include "rcutils/types/rcutils_ret.h" #include "rcutils/visibility_control.h" +#include "rcutils/configuration_flags.h" +#ifndef RCUTILS_NO_FILESYSTEM /// Write the given msg out to stderr, limiting the buffer size in the `fwrite`. /** * This ensures that there is an upper bound to a buffer overrun if `msg` is @@ -45,6 +47,9 @@ extern "C" */ #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) \ do {fwrite(msg, sizeof(char), rcutils_strnlen(msg, 4096), stderr);} while (0) +#else + #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) +#endif /// Set the error message to stderr using a format string and format arguments. /** @@ -55,6 +60,8 @@ extern "C" * \param[in] format_string The string to be used as the format of the error message. * \param[in] ... Arguments for the format string. */ + +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) #define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(format_string, ...) \ do { \ char output_msg[RCUTILS_ERROR_MESSAGE_MAX_LENGTH]; \ @@ -66,7 +73,11 @@ extern "C" RCUTILS_SAFE_FWRITE_TO_STDERR(output_msg); \ } \ } while (0) +#else +#define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(format_string, ...) +#endif +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) /// The maximum length a formatted number is allowed to have. #define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH 20 // "18446744073709551615" @@ -93,6 +104,13 @@ extern "C" RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH - \ RCUTILS_ERROR_FORMATTING_CHARACTERS - \ 1) +#else +#define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH 1 +#define RCUTILS_ERROR_FORMATTING_CHARACTERS 1 +#define RCUTILS_ERROR_MESSAGE_MAX_LENGTH 1 +#define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH 1 +#define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH 1 +#endif // RCUTILS_AVOID_DYNAMIC_ALLOCATION /// Struct wrapping a fixed-size c string used for returning the formatted error string. typedef struct rcutils_error_string_s @@ -114,7 +132,7 @@ typedef struct rcutils_error_state_s } rcutils_error_state_t; // make sure our math is right... -#if __STDC_VERSION__ >= 201112L +#if __STDC_VERSION__ >= 201112L && !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) static_assert( sizeof(rcutils_error_string_t) == ( RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH + @@ -226,8 +244,12 @@ rcutils_set_error_state(const char * error_string, const char * file, size_t lin * * \param[in] msg The error message to be set. */ +#ifdef RCUTILS_AVOID_DYNAMIC_ALLOCATION + #define RCUTILS_SET_ERROR_MSG(msg) +#else #define RCUTILS_SET_ERROR_MSG(msg) \ do {rcutils_set_error_state(msg, __FILE__, __LINE__);} while (0) +#endif // RCUTILS_AVOID_DYNAMIC_ALLOCATION /// Set the error message using a format string and format arguments. /** @@ -238,6 +260,9 @@ rcutils_set_error_state(const char * error_string, const char * file, size_t lin * \param[in] format_string The string to be used as the format of the error message. * \param[in] ... Arguments for the format string. */ +#ifdef RCUTILS_AVOID_DYNAMIC_ALLOCATION + #define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, ...) +#else #define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, ...) \ do { \ char output_msg[RCUTILS_ERROR_MESSAGE_MAX_LENGTH]; \ @@ -249,6 +274,8 @@ rcutils_set_error_state(const char * error_string, const char * file, size_t lin RCUTILS_SET_ERROR_MSG(output_msg); \ } \ } while (0) +#endif // RCUTILS_AVOID_DYNAMIC_ALLOCATION + /// Indicate that the function intends to set an error message and return an error value. /** diff --git a/include/rcutils/logging.h b/include/rcutils/logging.h index bc28cb3d..4096f4f1 100644 --- a/include/rcutils/logging.h +++ b/include/rcutils/logging.h @@ -41,7 +41,7 @@ extern "C" * \def RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL * \brief The default severity level of the default logger. */ -#define RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL RCUTILS_LOG_SEVERITY_INFO +#define RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL RCUTILS_LOG_SEVERITY_UNSET /// The flag if the logging system has been initialized. RCUTILS_PUBLIC diff --git a/include/rcutils/logging_macros.h b/include/rcutils/logging_macros.h index 162971fc..b5c39828 100644 --- a/include/rcutils/logging_macros.h +++ b/include/rcutils/logging_macros.h @@ -39,7 +39,7 @@ extern "C" * Use RCUTILS_LOG_MIN_SEVERITY_NONE to compile out all macros. */ #ifndef RCUTILS_LOG_MIN_SEVERITY -#define RCUTILS_LOG_MIN_SEVERITY RCUTILS_LOG_MIN_SEVERITY_DEBUG +#define RCUTILS_LOG_MIN_SEVERITY RCUTILS_LOG_MIN_SEVERITY_NONE #endif /** diff --git a/include/rcutils/macros.h b/include/rcutils/macros.h index 6dad0842..2e42163a 100644 --- a/include/rcutils/macros.h +++ b/include/rcutils/macros.h @@ -22,6 +22,8 @@ extern "C" { #endif +#include "rcutils/configuration_flags.h" + #ifndef _MSC_VER /// A macro to make the compiler warn when the return value of a function is not used. #define RCUTILS_WARN_UNUSED __attribute__((warn_unused_result)) @@ -32,7 +34,9 @@ extern "C" /// \cond Doxygen_Suppress // This block either sets RCUTILS_THREAD_LOCAL or RCUTILS_THREAD_LOCAL_PTHREAD. -#if defined _WIN32 || defined __CYGWIN__ +#if defined(RCUTILS_NO_THREAD_SUPPORT) + #define RCUTILS_THREAD_LOCAL +#elif defined _WIN32 || defined __CYGWIN__ // Windows or Cygwin #define RCUTILS_THREAD_LOCAL __declspec(thread) #elif defined __APPLE__ diff --git a/include/rcutils/security_directory.h b/include/rcutils/security_directory.h new file mode 100644 index 00000000..9d2c6806 --- /dev/null +++ b/include/rcutils/security_directory.h @@ -0,0 +1,67 @@ +// Copyright 2018 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCUTILS__SECURITY_DIRECTORY_H_ +#define RCUTILS__SECURITY_DIRECTORY_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "rcutils/allocator.h" +#include "rcutils/visibility_control.h" + +#ifndef ROS_SECURITY_NODE_DIRECTORY_VAR_NAME + #define ROS_SECURITY_NODE_DIRECTORY_VAR_NAME "ROS_SECURITY_NODE_DIRECTORY" +#endif + +#ifndef ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME + #define ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "ROS_SECURITY_ROOT_DIRECTORY" +#endif + +#ifndef ROS_SECURITY_LOOKUP_TYPE_VAR_NAME + #define ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "ROS_SECURITY_LOOKUP_TYPE" +#endif + +/// Return the secure root directory associated with a node given its validated name and namespace. +/** + * E.g. for a node named "c" in namespace "/a/b", the secure root path will be + * "a/b/c", where the delimiter "/" is native for target file system (e.g. "\\" for _WIN32). + * If no exact match is found for the node name, a best match would be used instead + * (by performing longest-prefix matching). + * + * However, this expansion can be overridden by setting the secure node directory environment + * variable, allowing users to explicitly specify the exact secure root directory to be utilized. + * Such an override is useful for where the FQN of a node is non-deterministic before runtime, + * or when testing and using additional tools that may not otherwise be easily provisioned. + * + * \param[in] node_name validated node name (a single token) + * \param[in] node_namespace validated, absolute namespace (starting with "/") + * \param[in] allocator the allocator to use for allocation + * \returns machine specific (absolute) node secure root path or NULL on failure + * returned pointer must be deallocated by the caller of this function + */ +RCUTILS_PUBLIC +char * rcutils_get_secure_root( + const char * node_name, + const char * node_namespace, + const rcutils_allocator_t * allocator +); + +#ifdef __cplusplus +} +#endif + +#endif // RCUTILS__SECURITY_DIRECTORY_H_ diff --git a/include/rcutils/testing/fault_injection.h b/include/rcutils/testing/fault_injection.h index d397fd74..d74a49bf 100644 --- a/include/rcutils/testing/fault_injection.h +++ b/include/rcutils/testing/fault_injection.h @@ -83,6 +83,8 @@ RCUTILS_WARN_UNUSED int_least64_t _rcutils_fault_injection_maybe_fail(void); +#ifdef RCUTILS_ENABLE_FAULT_INJECTION + /** * \def RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR * \brief This macro checks and decrements a static global variable atomic counter and returns @@ -199,6 +201,17 @@ _rcutils_fault_injection_maybe_fail(void); rcutils_fault_injection_set_count(no_fault_injection_count); \ } while (0) +#else + +// Mocks for micro-ROS when fault injection not enabled + +#define RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR(return_value_on_error) +#define RCUTILS_FAULT_INJECTION_MAYBE_FAIL(failure_code) +#define RCUTILS_FAULT_INJECTION_TEST(code) +#define RCUTILS_NO_FAULT_INJECTION(code) + +#endif + #ifdef __cplusplus } #endif diff --git a/src/allocator.c b/src/allocator.c index d364bded..90cbf0d9 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -69,19 +69,34 @@ rcutils_get_zero_initialized_allocator(void) return zero_allocator; } +static rcutils_allocator_t default_allocator = { + .allocate = __default_allocate, + .deallocate = __default_deallocate, + .reallocate = __default_reallocate, + .zero_allocate = __default_zero_allocate, + .state = NULL, +}; + rcutils_allocator_t rcutils_get_default_allocator(void) { - static rcutils_allocator_t default_allocator = { - .allocate = __default_allocate, - .deallocate = __default_deallocate, - .reallocate = __default_reallocate, - .zero_allocate = __default_zero_allocate, - .state = NULL, - }; return default_allocator; } +bool +rcutils_set_default_allocator(rcutils_allocator_t * allocator){ + if (rcutils_allocator_is_valid(allocator)) + { + default_allocator.allocate = allocator->allocate; + default_allocator.deallocate = allocator->deallocate; + default_allocator.reallocate = allocator->reallocate; + default_allocator.zero_allocate = allocator->zero_allocate; + default_allocator.state = NULL; + return true; + } + return false; +} + bool rcutils_allocator_is_valid(const rcutils_allocator_t * allocator) { diff --git a/src/atomic_64bits.c b/src/atomic_64bits.c new file mode 100644 index 00000000..f11a39da --- /dev/null +++ b/src/atomic_64bits.c @@ -0,0 +1,92 @@ +// Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#define FLAGS_LEN 23 + +static bool * get_memory_lock(void *address) +{ + static bool memory_locks[FLAGS_LEN] = { 0 }; + uintptr_t a = (uintptr_t)(address); + + // Public domain hash function taken from http://burtleburtle.net/bob/hash/integer.html + a = (a ^ 61) ^ (a >> 16); + a = a + (a << 3); + a = a ^ (a >> 4); + a = a * 0x27d4eb2d; + a = a ^ (a >> 15); + + a = a % FLAGS_LEN; + return memory_locks + a; +} + +void lock_memory(uint64_t *address){ + bool * memory_lock = get_memory_lock(address); + + while (__atomic_test_and_set(memory_lock, __ATOMIC_ACQUIRE) == 1); +} + +void unlock_memory(uint64_t *address){ + bool * memory_lock = get_memory_lock(address); + + __atomic_clear(memory_lock, __ATOMIC_RELEASE); +} + +uint64_t __atomic_load_8(uint64_t *mem, int model) { + (void) model; + + lock_memory(mem); + uint64_t ret = *mem; + unlock_memory(mem); + return ret; +} + +void __atomic_store_8(uint64_t *mem, uint64_t val, int model) { + (void) model; + + lock_memory(mem); + *mem = val; + unlock_memory(mem); +} + +uint64_t __atomic_exchange_8(uint64_t *mem, uint64_t val, int model) { + (void) model; + + lock_memory(mem); + uint64_t ret = *mem; + *mem = val; + unlock_memory(mem); + return ret; +} + +uint64_t __atomic_fetch_add_8(uint64_t *mem, uint64_t val, int model) { + (void) model; + + lock_memory(mem); + uint64_t ret = *mem; + *mem += val; + unlock_memory(mem); + return ret; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/error_handling_helpers.h b/src/error_handling_helpers.h index 70bdff24..71d77f4e 100644 --- a/src/error_handling_helpers.h +++ b/src/error_handling_helpers.h @@ -109,6 +109,7 @@ static void __rcutils_convert_uint64_t_into_c_str(uint64_t number, char * buffer, size_t buffer_size) { +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) assert(buffer != NULL); assert(buffer_size >= 21); (void)buffer_size; // prevent warning in release builds where there is no assert(...) @@ -132,6 +133,7 @@ __rcutils_convert_uint64_t_into_c_str(uint64_t number, char * buffer, size_t buf // reverse the string in place __rcutils_reverse_str(buffer, rcutils_strnlen(buffer, 21)); +#endif } // do not use externally, internal function which is only to be used by error_handling.c @@ -141,6 +143,7 @@ __rcutils_format_error_string( rcutils_error_string_t * error_string, const rcutils_error_state_t * error_state) { +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) assert(error_string != NULL); assert(error_state != NULL); static const char format_1[] = ", at "; @@ -174,6 +177,7 @@ __rcutils_format_error_string( written = __rcutils_copy_string(offset, bytes_left, line_number_buffer); offset += written; offset[0] = '\0'; +#endif } #ifdef __cplusplus diff --git a/src/filesystem.c b/src/filesystem.c index c617ac2f..1a50d788 100644 --- a/src/filesystem.c +++ b/src/filesystem.c @@ -18,9 +18,13 @@ #include #include #include +#ifndef RCUTILS_NO_FILESYSTEM #include +#endif #ifndef _WIN32 +#ifndef RCUTILS_NO_FILESYSTEM #include +#endif #include #else // When building with MSVC 19.28.29333.0 on Windows 10 (as of 2020-11-11), @@ -50,6 +54,10 @@ # define RCUTILS_PATH_DELIMITER "/" #endif // _WIN32 +#ifdef RCUTILS_NO_FILESYSTEM +typedef int DIR; +#endif // _RCUTILS_NO_FILESYSTEM + typedef struct rcutils_dir_iter_state_s { #ifdef _WIN32 @@ -63,6 +71,12 @@ typedef struct rcutils_dir_iter_state_s bool rcutils_get_cwd(char * buffer, size_t max_length) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) buffer; + (void) max_length; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else if (NULL == buffer || max_length == 0) { return false; } @@ -76,11 +90,17 @@ rcutils_get_cwd(char * buffer, size_t max_length) } #endif // _WIN32 return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_directory(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -90,11 +110,17 @@ rcutils_is_directory(const char * abs_path) #else return S_ISDIR(buf.st_mode); #endif // _WIN32 +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_file(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -104,21 +130,33 @@ rcutils_is_file(const char * abs_path) #else return S_ISREG(buf.st_mode); #endif // _WIN32 +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_exists(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_readable(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -131,11 +169,17 @@ rcutils_is_readable(const char * abs_path) return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_writable(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -148,11 +192,17 @@ rcutils_is_writable(const char * abs_path) return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_readable_and_writable(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -167,6 +217,7 @@ rcutils_is_readable_and_writable(const char * abs_path) return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } char * @@ -175,6 +226,13 @@ rcutils_join_path( const char * right_hand_path, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) left_hand_path; + (void) right_hand_path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else if (NULL == left_hand_path) { return NULL; } @@ -186,6 +244,7 @@ rcutils_join_path( allocator, "%s%s%s", left_hand_path, RCUTILS_PATH_DELIMITER, right_hand_path); +#endif // _RCUTILS_NO_FILESYSTEM } char * @@ -193,16 +252,29 @@ rcutils_to_native_path( const char * path, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else if (NULL == path) { return NULL; } return rcutils_repl_str(path, "/", RCUTILS_PATH_DELIMITER, &allocator); +#endif // _RCUTILS_NO_FILESYSTEM } char * rcutils_expand_user(const char * path, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else if (NULL == path) { return NULL; } @@ -221,11 +293,17 @@ rcutils_expand_user(const char * path, rcutils_allocator_t allocator) "%s%s", homedir, path + 1); +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_mkdir(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else if (NULL == abs_path) { return false; } @@ -253,6 +331,7 @@ rcutils_mkdir(const char * abs_path) } return success; +#endif // _RCUTILS_NO_FILESYSTEM } rcutils_ret_t @@ -271,6 +350,7 @@ typedef struct dir_list_t struct dir_list_t * next; } dir_list_t; +#ifndef RCUTILS_NO_FILESYSTEM static void free_dir_list(dir_list_t * dir_list, rcutils_allocator_t allocator) { dir_list_t * next_dir; @@ -333,6 +413,7 @@ static rcutils_ret_t check_and_calculate_size( return RCUTILS_RET_OK; } +#endif // _RCUTILS_NO_FILESYSTEM rcutils_ret_t rcutils_calculate_directory_size_with_recursion( @@ -341,6 +422,14 @@ rcutils_calculate_directory_size_with_recursion( uint64_t * size, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) directory_path; + (void) max_depth; + (void) size; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return RCUTILS_RET_ERROR; +#else dir_list_t * dir_list = NULL; rcutils_ret_t ret = RCUTILS_RET_OK; rcutils_dir_iter_t * iter = NULL; @@ -355,6 +444,8 @@ rcutils_calculate_directory_size_with_recursion( return RCUTILS_RET_INVALID_ARGUMENT; } + size_t dir_size = 0; + if (!rcutils_is_directory(directory_path)) { RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING( "Path is not a directory: %s\n", directory_path); @@ -404,11 +495,18 @@ rcutils_calculate_directory_size_with_recursion( rcutils_dir_iter_end(iter); free_dir_list(dir_list, allocator); return ret; +#endif // _RCUTILS_NO_FILESYSTEM } rcutils_dir_iter_t * rcutils_dir_iter_start(const char * directory_path, const rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) directory_path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(directory_path, NULL); RCUTILS_CHECK_ALLOCATOR_WITH_MSG( &allocator, "allocator is invalid", return NULL); @@ -469,11 +567,17 @@ rcutils_dir_iter_start(const char * directory_path, const rcutils_allocator_t al rcutils_dir_iter_start_fail: rcutils_dir_iter_end(iter); return NULL; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_dir_iter_next(rcutils_dir_iter_t * iter) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) iter; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(iter, false); RCUTILS_CHECK_FOR_NULL_WITH_MSG(iter->state, "iter is invalid", return false); @@ -492,11 +596,16 @@ rcutils_dir_iter_next(rcutils_dir_iter_t * iter) iter->entry_name = NULL; return false; +#endif // _RCUTILS_NO_FILESYSTEM } void rcutils_dir_iter_end(rcutils_dir_iter_t * iter) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) iter; + RCUTILS_SET_ERROR_MSG("not available filesystem"); +#else if (NULL == iter) { return; } @@ -518,11 +627,18 @@ rcutils_dir_iter_end(rcutils_dir_iter_t * iter) } allocator.deallocate(iter, allocator.state); +#endif // _RCUTILS_NO_FILESYSTEM } size_t rcutils_get_file_size(const char * file_path) { + +#ifdef RCUTILS_NO_FILESYSTEM + (void) file_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return 0; +#else if (!rcutils_is_file(file_path)) { RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING( "Path is not a file: %s\n", file_path); @@ -532,4 +648,5 @@ rcutils_get_file_size(const char * file_path) struct stat stat_buffer; int rc = stat(file_path, &stat_buffer); return rc == 0 ? (size_t)(stat_buffer.st_size) : 0; +#endif // _RCUTILS_NO_FILESYSTEM } diff --git a/src/process.c b/src/process.c index d62c3295..2d8717ae 100644 --- a/src/process.c +++ b/src/process.c @@ -17,6 +17,8 @@ extern "C" { #endif +#include "rcutils/process.h" + #include #include #include @@ -36,14 +38,15 @@ extern "C" #pragma warning(pop) #else #include +#ifndef RCUTILS_NO_PROCESS_SUPPORT #include +#endif #include #endif #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/join.h" -#include "rcutils/process.h" #include "rcutils/strdup.h" int rcutils_get_pid(void) @@ -63,7 +66,13 @@ char * rcutils_get_executable_name(rcutils_allocator_t allocator) #if defined __APPLE__ || defined __FreeBSD__ || (defined __ANDROID__ && __ANDROID_API__ >= 21) const char * appname = getprogname(); #elif (defined __GNUC__ && !defined(__MINGW64__)) && !defined(__QNXNTO__) && !defined(__OHOS__) - const char * appname = program_invocation_name; + #if defined __linux__ || defined __linux || defined __gnu_linux__ || defined linux + const char * appname = program_invocation_name; + #else + // Some embedded OS compile with __GNUC__ but are not quite conformant with GNU-specific extensions. + // They may fake to have a GLIBC in their custom C library implementation. + const char * appname = ""; + #endif #elif defined _WIN32 || defined __CYGWIN__ char appname[MAX_PATH]; int32_t size = GetModuleFileNameA(NULL, appname, MAX_PATH); @@ -227,6 +236,12 @@ rcutils_start_process( const rcutils_string_array_t * args, rcutils_allocator_t * allocator) { +#ifdef RCUTILS_NO_PROCESS_SUPPORT + (void)args; + (void)allocator; + RCUTILS_SET_ERROR_MSG("process support is disabled (RCUTILS_NO_PROCESS_SUPPORT)"); + return NULL; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(args, NULL); RCUTILS_CHECK_ARGUMENT_FOR_NULL(allocator, NULL); if (args->size < 1) { @@ -312,6 +327,7 @@ rcutils_start_process( allocator->deallocate(argv, &allocator->state); exit(127); #endif +#endif // RCUTILS_NO_PROCESS_SUPPORT } void @@ -335,6 +351,12 @@ rcutils_process_close(rcutils_process_t * process) rcutils_ret_t rcutils_process_wait(const rcutils_process_t * process, int * exit_code) { +#ifdef RCUTILS_NO_PROCESS_SUPPORT + (void)process; + (void)exit_code; + RCUTILS_SET_ERROR_MSG("process support is disabled (RCUTILS_NO_PROCESS_SUPPORT)"); + return RCUTILS_RET_ERROR; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(process, RCUTILS_RET_INVALID_ARGUMENT); #if defined _WIN32 || defined __CYGWIN__ @@ -375,6 +397,7 @@ rcutils_process_wait(const rcutils_process_t * process, int * exit_code) #endif return RCUTILS_RET_OK; +#endif // RCUTILS_NO_PROCESS_SUPPORT } #ifdef __cplusplus diff --git a/src/shared_library.c b/src/shared_library.c index 077478f7..202ad8aa 100644 --- a/src/shared_library.c +++ b/src/shared_library.c @@ -19,6 +19,10 @@ extern "C" #include #include +#include "rcutils/configuration_flags.h" + +#ifndef RCUTILS_NO_FILESYSTEM + #ifndef _WIN32 #if defined(__APPLE__) #include @@ -48,6 +52,8 @@ C_ASSERT(sizeof(void *) == sizeof(HINSTANCE)); C_ASSERT(sizeof(char) == sizeof(TCHAR)); #endif // _WIN32 +#endif //RCUTILS_NO_FILESYSTEM + #include "rcutils/error_handling.h" #include "rcutils/macros.h" #include "rcutils/shared_library.h" @@ -66,6 +72,7 @@ rcutils_load_shared_library( const char * library_path, rcutils_allocator_t allocator) { +#ifndef RCUTILS_NO_FILESYSTEM RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCUTILS_RET_BAD_ALLOC); RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCUTILS_RET_ERROR); @@ -192,11 +199,20 @@ rcutils_load_shared_library( } return ret; #endif // _WIN32 + +#else + (void) lib; + (void) library_path; + (void) allocator; + return RCUTILS_RET_ERROR; +#endif //RCUTILS_NO_FILESYSTEM + } void * rcutils_get_symbol(const rcutils_shared_library_t * lib, const char * symbol_name) { +#ifndef RCUTILS_NO_FILESYSTEM if (!lib || !lib->lib_pointer || (symbol_name == NULL)) { RCUTILS_SET_ERROR_MSG("invalid inputs arguments"); return NULL; @@ -227,11 +243,17 @@ rcutils_get_symbol(const rcutils_shared_library_t * lib, const char * symbol_nam return NULL; } return lib_symbol; +#else + (void) lib; + (void) symbol_name; + return NULL; +#endif //RCUTILS_NO_FILESYSTEM } bool rcutils_has_symbol(const rcutils_shared_library_t * lib, const char * symbol_name) { +#ifndef RCUTILS_NO_FILESYSTEM if (!lib || !lib->lib_pointer || symbol_name == NULL) { return false; } @@ -247,11 +269,17 @@ rcutils_has_symbol(const rcutils_shared_library_t * lib, const char * symbol_nam void * lib_symbol = GetProcAddress((HINSTANCE)(lib->lib_pointer), symbol_name); return lib_symbol != NULL; #endif // _WIN32 +#else + (void) lib; + (void) symbol_name; + return false; +#endif //RCUTILS_NO_FILESYSTEM } rcutils_ret_t rcutils_unload_shared_library(rcutils_shared_library_t * lib) { +#ifndef RCUTILS_NO_FILESYSTEM RCUTILS_CHECK_ARGUMENT_FOR_NULL(lib, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(lib->lib_pointer, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(lib->library_path, RCUTILS_RET_INVALID_ARGUMENT); @@ -277,6 +305,10 @@ rcutils_unload_shared_library(rcutils_shared_library_t * lib) lib->lib_pointer = NULL; lib->allocator = rcutils_get_zero_initialized_allocator(); return ret; +#else + (void) lib; + return RCUTILS_RET_ERROR; +#endif //RCUTILS_NO_FILESYSTEM } rcutils_ret_t @@ -286,6 +318,7 @@ rcutils_get_platform_library_name( unsigned int buffer_size, bool debug) { +#ifndef RCUTILS_NO_FILESYSTEM RCUTILS_CHECK_ARGUMENT_FOR_NULL(library_name, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(library_name_platform, RCUTILS_RET_INVALID_ARGUMENT); @@ -349,6 +382,13 @@ rcutils_get_platform_library_name( return RCUTILS_RET_ERROR; } return RCUTILS_RET_OK; +#else + (void) library_name; + (void) library_name_platform; + (void) buffer_size; + (void) debug; + return RCUTILS_RET_ERROR; +#endif //RCUTILS_NO_FILESYSTEM } bool diff --git a/src/time.c b/src/time.c index 882c9d98..df337b83 100644 --- a/src/time.c +++ b/src/time.c @@ -28,6 +28,11 @@ extern "C" #include "rcutils/error_handling.h" #include "rcutils/snprintf.h" +// Define PRId64 for platforms that don't have it +#ifndef PRId64 +#define PRId64 "lld" +#endif + rcutils_ret_t rcutils_time_point_value_as_nanoseconds_string( const rcutils_time_point_value_t * time_point, @@ -52,6 +57,13 @@ rcutils_time_point_value_as_date_string( char * str, size_t str_size) { +#ifdef RCUTILS_MICROROS + (void)time_point; + (void)str; + (void)str_size; + + return RCUTILS_RET_ERROR; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(time_point, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(str, RCUTILS_RET_INVALID_ARGUMENT); if (0 == str_size) { @@ -99,6 +111,7 @@ rcutils_time_point_value_as_date_string( } return RCUTILS_RET_OK; +#endif // RCUTILS_MICROROS } rcutils_ret_t diff --git a/src/time_unix.c b/src/time_unix.c index fdd49bc6..4facc692 100644 --- a/src/time_unix.c +++ b/src/time_unix.c @@ -46,7 +46,7 @@ // This is an appropriate check for clock_gettime() according to: // http://man7.org/linux/man-pages/man2/clock_gettime.2.html # if !defined(_POSIX_TIMERS) || !_POSIX_TIMERS -# error no monotonic clock function available +# warning no monotonic clock function available # endif // !defined(_POSIX_TIMERS) || !_POSIX_TIMERS #endif // !defined(__MACH__) && !defined(__APPLE__) From f2cbed6ffba664f836b972ed329dda6386cf8f68 Mon Sep 17 00:00:00 2001 From: David Laseca Perez Date: Mon, 14 Sep 2026 15:46:10 +0200 Subject: [PATCH 2/2] Export Threads dependency (#63) Signed-off-by: David Laseca Perez (cherry picked from commit 97cb03a293e6b3e44e24294996570775a7d80253) --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4584be1..4af613a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -712,6 +712,11 @@ ament_export_targets(${PROJECT_NAME}) ament_export_dependencies(ament_cmake ament_cmake_ros_core) +if (NOT RCUTILS_NO_THREAD_SUPPORT) + # Needed because micro-ROS is built statically + ament_export_dependencies(Threads) +endif() + ament_package() install(