From 469cba155524556ac3d68983a504d4edfe1872dd Mon Sep 17 00:00:00 2001 From: Bartosz Burda Date: Fri, 27 Feb 2026 10:16:47 +0100 Subject: [PATCH 1/4] feat(cmake): add medkit_target_dependencies() compat shim for Rolling --- cmake/ROS2MedkitCompat.cmake | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cmake/ROS2MedkitCompat.cmake b/cmake/ROS2MedkitCompat.cmake index 4f0b5f7c..549b1e54 100644 --- a/cmake/ROS2MedkitCompat.cmake +++ b/cmake/ROS2MedkitCompat.cmake @@ -28,6 +28,7 @@ # medkit_find_cpp_httplib() — Find cpp-httplib, create cpp_httplib_target alias # medkit_detect_compat_defs() — Detect rclcpp/rosbag2 versions, set compat variables # medkit_apply_compat_defs(target) — Apply compile definitions to a target +# medkit_target_dependencies(target ...) - Drop-in ament_target_dependencies replacement # # Variables set by medkit_detect_compat_defs(): # MEDKIT_RCLCPP_VERSION_MAJOR — integer (e.g., 16 for Humble, 28 for Jazzy) @@ -159,3 +160,37 @@ function(medkit_apply_compat_defs target) target_compile_definitions(${target} PRIVATE ROSBAG2_USE_OLD_TIMESTAMP_FIELD) endif() endfunction() + +# --------------------------------------------------------------------------- +# medkit_target_dependencies(target [PUBLIC|PRIVATE|INTERFACE] dep1 dep2 ...) +# --------------------------------------------------------------------------- +# Drop-in replacement for ament_target_dependencies that works on Rolling +# (where ament_target_dependencies was removed from ament_cmake). +# +# On Humble/Jazzy: delegates to ament_target_dependencies (available). +# On Rolling: uses target_link_libraries with ${dep_TARGETS}. +# +# Special cases: +# yaml_cpp_vendor - vendor package, no _TARGETS; links yaml-cpp::yaml-cpp +# (must call medkit_find_yaml_cpp() first) +# --------------------------------------------------------------------------- +macro(medkit_target_dependencies target) + if(COMMAND ament_target_dependencies) + ament_target_dependencies(${target} ${ARGN}) + else() + set(_mtd_visibility "") + foreach(_mtd_arg ${ARGN}) + if(_mtd_arg STREQUAL "PUBLIC" OR _mtd_arg STREQUAL "PRIVATE" OR _mtd_arg STREQUAL "INTERFACE") + set(_mtd_visibility ${_mtd_arg}) + elseif(_mtd_arg STREQUAL "yaml_cpp_vendor") + # yaml_cpp_vendor is a wrapper package - link the real target + target_link_libraries(${target} ${_mtd_visibility} yaml-cpp::yaml-cpp) + else() + # Standard ament package - use exported targets + target_link_libraries(${target} ${_mtd_visibility} ${${_mtd_arg}_TARGETS}) + endif() + endforeach() + unset(_mtd_visibility) + unset(_mtd_arg) + endif() +endmacro() From ba9a07e4389adbf52893ce33dffb6ff054c31a89 Mon Sep 17 00:00:00 2001 From: Bartosz Burda Date: Fri, 27 Feb 2026 10:22:18 +0100 Subject: [PATCH 2/4] fix(cmake): migrate all ament_target_dependencies to medkit_target_dependencies --- .../CMakeLists.txt | 11 ++++++--- src/ros2_medkit_fault_manager/CMakeLists.txt | 10 ++++---- src/ros2_medkit_fault_reporter/CMakeLists.txt | 9 ++++++-- src/ros2_medkit_gateway/CMakeLists.txt | 14 +++++------ .../CMakeLists.txt | 23 +++++++++++-------- src/ros2_medkit_serialization/CMakeLists.txt | 8 +++---- 6 files changed, 45 insertions(+), 30 deletions(-) diff --git a/src/ros2_medkit_diagnostic_bridge/CMakeLists.txt b/src/ros2_medkit_diagnostic_bridge/CMakeLists.txt index c19f01bc..3899734d 100644 --- a/src/ros2_medkit_diagnostic_bridge/CMakeLists.txt +++ b/src/ros2_medkit_diagnostic_bridge/CMakeLists.txt @@ -32,6 +32,11 @@ if(ENABLE_COVERAGE) endif() find_package(ament_cmake REQUIRED) + +# Multi-distro compatibility (Humble / Jazzy / Rolling) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake") +include(ROS2MedkitCompat) + find_package(rclcpp REQUIRED) find_package(diagnostic_msgs REQUIRED) find_package(ros2_medkit_msgs REQUIRED) @@ -47,7 +52,7 @@ target_include_directories(diagnostic_bridge_lib PUBLIC $ ) -ament_target_dependencies(diagnostic_bridge_lib +medkit_target_dependencies(diagnostic_bridge_lib rclcpp diagnostic_msgs ros2_medkit_msgs @@ -57,7 +62,7 @@ ament_target_dependencies(diagnostic_bridge_lib # Executable add_executable(diagnostic_bridge_node src/main.cpp) target_link_libraries(diagnostic_bridge_node diagnostic_bridge_lib) -ament_target_dependencies(diagnostic_bridge_node rclcpp) +medkit_target_dependencies(diagnostic_bridge_node rclcpp) # Install executable install(TARGETS diagnostic_bridge_node @@ -100,7 +105,7 @@ if(BUILD_TESTING) # Unit tests ament_add_gtest(test_diagnostic_bridge test/test_diagnostic_bridge.cpp) target_link_libraries(test_diagnostic_bridge diagnostic_bridge_lib) - ament_target_dependencies(test_diagnostic_bridge rclcpp diagnostic_msgs ros2_medkit_msgs) + medkit_target_dependencies(test_diagnostic_bridge rclcpp diagnostic_msgs ros2_medkit_msgs) if(ENABLE_COVERAGE) target_compile_options(test_diagnostic_bridge PRIVATE --coverage -O0 -g) diff --git a/src/ros2_medkit_fault_manager/CMakeLists.txt b/src/ros2_medkit_fault_manager/CMakeLists.txt index 0aeb4274..6b49ce5d 100644 --- a/src/ros2_medkit_fault_manager/CMakeLists.txt +++ b/src/ros2_medkit_fault_manager/CMakeLists.txt @@ -67,7 +67,7 @@ target_include_directories(fault_manager_lib PUBLIC $ ) -ament_target_dependencies(fault_manager_lib PUBLIC +medkit_target_dependencies(fault_manager_lib PUBLIC rclcpp ros2_medkit_msgs ros2_medkit_serialization @@ -125,22 +125,22 @@ if(BUILD_TESTING) # Unit tests ament_add_gtest(test_fault_manager test/test_fault_manager.cpp) target_link_libraries(test_fault_manager fault_manager_lib) - ament_target_dependencies(test_fault_manager rclcpp ros2_medkit_msgs) + medkit_target_dependencies(test_fault_manager rclcpp ros2_medkit_msgs) # SQLite storage tests ament_add_gtest(test_sqlite_storage test/test_sqlite_storage.cpp) target_link_libraries(test_sqlite_storage fault_manager_lib) - ament_target_dependencies(test_sqlite_storage rclcpp ros2_medkit_msgs) + medkit_target_dependencies(test_sqlite_storage rclcpp ros2_medkit_msgs) # Snapshot capture tests ament_add_gtest(test_snapshot_capture test/test_snapshot_capture.cpp) target_link_libraries(test_snapshot_capture fault_manager_lib) - ament_target_dependencies(test_snapshot_capture rclcpp ros2_medkit_msgs) + medkit_target_dependencies(test_snapshot_capture rclcpp ros2_medkit_msgs) # Rosbag capture tests ament_add_gtest(test_rosbag_capture test/test_rosbag_capture.cpp) target_link_libraries(test_rosbag_capture fault_manager_lib) - ament_target_dependencies(test_rosbag_capture rclcpp ros2_medkit_msgs) + medkit_target_dependencies(test_rosbag_capture rclcpp ros2_medkit_msgs) # Correlation config parser tests ament_add_gtest(test_correlation_config_parser test/test_correlation_config_parser.cpp) diff --git a/src/ros2_medkit_fault_reporter/CMakeLists.txt b/src/ros2_medkit_fault_reporter/CMakeLists.txt index dd7159da..66debb79 100644 --- a/src/ros2_medkit_fault_reporter/CMakeLists.txt +++ b/src/ros2_medkit_fault_reporter/CMakeLists.txt @@ -32,6 +32,11 @@ if(ENABLE_COVERAGE) endif() find_package(ament_cmake REQUIRED) + +# Multi-distro compatibility (Humble / Jazzy / Rolling) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake") +include(ROS2MedkitCompat) + find_package(rclcpp REQUIRED) find_package(ros2_medkit_msgs REQUIRED) @@ -46,7 +51,7 @@ target_include_directories(fault_reporter_lib PUBLIC $ ) -ament_target_dependencies(fault_reporter_lib +medkit_target_dependencies(fault_reporter_lib rclcpp ros2_medkit_msgs ) @@ -87,7 +92,7 @@ if(BUILD_TESTING) # Unit tests ament_add_gtest(test_local_filter test/test_local_filter.cpp) target_link_libraries(test_local_filter fault_reporter_lib) - ament_target_dependencies(test_local_filter rclcpp ros2_medkit_msgs) + medkit_target_dependencies(test_local_filter rclcpp ros2_medkit_msgs) if(ENABLE_COVERAGE) target_compile_options(test_local_filter PRIVATE --coverage -O0 -g) diff --git a/src/ros2_medkit_gateway/CMakeLists.txt b/src/ros2_medkit_gateway/CMakeLists.txt index f50dab2f..3010a408 100644 --- a/src/ros2_medkit_gateway/CMakeLists.txt +++ b/src/ros2_medkit_gateway/CMakeLists.txt @@ -138,7 +138,7 @@ add_library(gateway_lib STATIC src/plugins/plugin_manager.cpp ) -ament_target_dependencies(gateway_lib +medkit_target_dependencies(gateway_lib rclcpp std_msgs std_srvs @@ -264,7 +264,7 @@ if(BUILD_TESTING) ament_add_gtest(test_generic_client_compat test/test_generic_client_compat.cpp) target_link_libraries(test_generic_client_compat gateway_lib) - ament_target_dependencies(test_generic_client_compat rclcpp std_srvs) + medkit_target_dependencies(test_generic_client_compat rclcpp std_srvs) ament_add_gtest(test_operation_manager test/test_operation_manager.cpp) target_link_libraries(test_operation_manager gateway_lib) @@ -276,12 +276,12 @@ if(BUILD_TESTING) find_package(std_msgs REQUIRED) ament_add_gtest(test_native_topic_sampler test/test_native_topic_sampler.cpp) target_link_libraries(test_native_topic_sampler gateway_lib) - ament_target_dependencies(test_native_topic_sampler std_msgs) + medkit_target_dependencies(test_native_topic_sampler std_msgs) # Add DiscoveryManager tests ament_add_gtest(test_discovery_manager test/test_discovery_manager.cpp) target_link_libraries(test_discovery_manager gateway_lib) - ament_target_dependencies(test_discovery_manager std_msgs) + medkit_target_dependencies(test_discovery_manager std_msgs) # Add TLS configuration tests ament_add_gtest(test_tls_config test/test_tls_config.cpp) @@ -290,7 +290,7 @@ if(BUILD_TESTING) # Add FaultManager tests ament_add_gtest(test_fault_manager test/test_fault_manager.cpp) target_link_libraries(test_fault_manager gateway_lib) - ament_target_dependencies(test_fault_manager rclcpp ros2_medkit_msgs) + medkit_target_dependencies(test_fault_manager rclcpp ros2_medkit_msgs) # Add discovery models tests ament_add_gtest(test_discovery_models test/test_discovery_models.cpp) @@ -335,7 +335,7 @@ if(BUILD_TESTING) # Add data access manager tests ament_add_gtest(test_data_access_manager test/test_data_access_manager.cpp) target_link_libraries(test_data_access_manager gateway_lib) - ament_target_dependencies(test_data_access_manager rclcpp std_msgs) + medkit_target_dependencies(test_data_access_manager rclcpp std_msgs) # Add entity resource model tests ament_add_gtest(test_entity_resource_model test/test_entity_resource_model.cpp) @@ -425,7 +425,7 @@ if(BUILD_TESTING) # Add plugin loader tests ament_add_gtest(test_plugin_loader test/test_plugin_loader.cpp) target_link_libraries(test_plugin_loader gateway_lib) - ament_target_dependencies(test_plugin_loader ament_index_cpp) + medkit_target_dependencies(test_plugin_loader ament_index_cpp) # Plugin manager tests ament_add_gtest(test_plugin_manager test/test_plugin_manager.cpp) diff --git a/src/ros2_medkit_integration_tests/CMakeLists.txt b/src/ros2_medkit_integration_tests/CMakeLists.txt index 79f67650..a6d80497 100644 --- a/src/ros2_medkit_integration_tests/CMakeLists.txt +++ b/src/ros2_medkit_integration_tests/CMakeLists.txt @@ -9,6 +9,11 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() find_package(ament_cmake REQUIRED) + +# Multi-distro compatibility (Humble / Jazzy / Rolling) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake") +include(ROS2MedkitCompat) + find_package(ament_cmake_python REQUIRED) find_package(rclcpp REQUIRED) find_package(rclcpp_action REQUIRED) @@ -22,31 +27,31 @@ find_package(ros2_medkit_msgs REQUIRED) # === Demo node executables === add_executable(demo_engine_temp_sensor demo_nodes/engine_temp_sensor.cpp) -ament_target_dependencies(demo_engine_temp_sensor rclcpp rcl_interfaces sensor_msgs) +medkit_target_dependencies(demo_engine_temp_sensor rclcpp rcl_interfaces sensor_msgs) add_executable(demo_rpm_sensor demo_nodes/rpm_sensor.cpp) -ament_target_dependencies(demo_rpm_sensor rclcpp std_msgs) +medkit_target_dependencies(demo_rpm_sensor rclcpp std_msgs) add_executable(demo_brake_pressure_sensor demo_nodes/brake_pressure_sensor.cpp) -ament_target_dependencies(demo_brake_pressure_sensor rclcpp std_msgs) +medkit_target_dependencies(demo_brake_pressure_sensor rclcpp std_msgs) add_executable(demo_door_status_sensor demo_nodes/door_status_sensor.cpp) -ament_target_dependencies(demo_door_status_sensor rclcpp std_msgs) +medkit_target_dependencies(demo_door_status_sensor rclcpp std_msgs) add_executable(demo_brake_actuator demo_nodes/brake_actuator.cpp) -ament_target_dependencies(demo_brake_actuator rclcpp std_msgs) +medkit_target_dependencies(demo_brake_actuator rclcpp std_msgs) add_executable(demo_light_controller demo_nodes/light_controller.cpp) -ament_target_dependencies(demo_light_controller rclcpp std_msgs) +medkit_target_dependencies(demo_light_controller rclcpp std_msgs) add_executable(demo_calibration_service demo_nodes/calibration_service.cpp) -ament_target_dependencies(demo_calibration_service rclcpp std_srvs) +medkit_target_dependencies(demo_calibration_service rclcpp std_srvs) add_executable(demo_long_calibration_action demo_nodes/long_calibration_action.cpp) -ament_target_dependencies(demo_long_calibration_action rclcpp rclcpp_action example_interfaces) +medkit_target_dependencies(demo_long_calibration_action rclcpp rclcpp_action example_interfaces) add_executable(demo_lidar_sensor demo_nodes/lidar_sensor.cpp) -ament_target_dependencies(demo_lidar_sensor rclcpp rcl_interfaces sensor_msgs std_srvs ros2_medkit_msgs) +medkit_target_dependencies(demo_lidar_sensor rclcpp rcl_interfaces sensor_msgs std_srvs ros2_medkit_msgs) install(TARGETS demo_engine_temp_sensor diff --git a/src/ros2_medkit_serialization/CMakeLists.txt b/src/ros2_medkit_serialization/CMakeLists.txt index 4c340096..654d49e4 100644 --- a/src/ros2_medkit_serialization/CMakeLists.txt +++ b/src/ros2_medkit_serialization/CMakeLists.txt @@ -54,7 +54,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ ) -ament_target_dependencies(${PROJECT_NAME} +medkit_target_dependencies(${PROJECT_NAME} rclcpp rcutils rosidl_runtime_c @@ -152,15 +152,15 @@ if(BUILD_TESTING) # Unit tests ament_add_gtest(test_type_cache test/test_type_cache.cpp) target_link_libraries(test_type_cache ${PROJECT_NAME}) - ament_target_dependencies(test_type_cache std_msgs std_srvs) + medkit_target_dependencies(test_type_cache std_msgs std_srvs) ament_add_gtest(test_json_serializer test/test_json_serializer.cpp) target_link_libraries(test_json_serializer ${PROJECT_NAME}) - ament_target_dependencies(test_json_serializer std_msgs std_srvs geometry_msgs sensor_msgs test_msgs) + medkit_target_dependencies(test_json_serializer std_msgs std_srvs geometry_msgs sensor_msgs test_msgs) ament_add_gtest(test_service_action_types test/test_service_action_types.cpp) target_link_libraries(test_service_action_types ${PROJECT_NAME}) - ament_target_dependencies(test_service_action_types std_srvs) + medkit_target_dependencies(test_service_action_types std_srvs) # Apply coverage flags to test targets if(ENABLE_COVERAGE) From 31d84aae4b0a7d9bc8684a891a8a71b46a12f00c Mon Sep 17 00:00:00 2001 From: Bartosz Burda Date: Fri, 27 Feb 2026 12:11:45 +0100 Subject: [PATCH 3/4] fix(cmake): harden medkit_target_dependencies Rolling fallback Buffer deps per-visibility to avoid mixing target_link_libraries signatures. Add fallback to dep::dep imported targets and FATAL_ERROR when a dependency cannot be resolved. --- cmake/ROS2MedkitCompat.cmake | 52 +++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/cmake/ROS2MedkitCompat.cmake b/cmake/ROS2MedkitCompat.cmake index 549b1e54..9efa9ff9 100644 --- a/cmake/ROS2MedkitCompat.cmake +++ b/cmake/ROS2MedkitCompat.cmake @@ -178,19 +178,59 @@ macro(medkit_target_dependencies target) if(COMMAND ament_target_dependencies) ament_target_dependencies(${target} ${ARGN}) else() + # Rolling fallback: resolve dependency targets explicitly and buffer per-visibility set(_mtd_visibility "") + set(_mtd_public_deps) + set(_mtd_private_deps) + set(_mtd_interface_deps) foreach(_mtd_arg ${ARGN}) if(_mtd_arg STREQUAL "PUBLIC" OR _mtd_arg STREQUAL "PRIVATE" OR _mtd_arg STREQUAL "INTERFACE") set(_mtd_visibility ${_mtd_arg}) - elseif(_mtd_arg STREQUAL "yaml_cpp_vendor") - # yaml_cpp_vendor is a wrapper package - link the real target - target_link_libraries(${target} ${_mtd_visibility} yaml-cpp::yaml-cpp) else() - # Standard ament package - use exported targets - target_link_libraries(${target} ${_mtd_visibility} ${${_mtd_arg}_TARGETS}) + # Resolve dependency to concrete CMake targets + set(_mtd_dep_targets) + if(_mtd_arg STREQUAL "yaml_cpp_vendor") + # yaml_cpp_vendor is a wrapper package - link the real target + list(APPEND _mtd_dep_targets yaml-cpp::yaml-cpp) + else() + # Standard ament package - prefer exported _TARGETS, fall back to :: + set(_mtd_targets_var "${_mtd_arg}_TARGETS") + if(DEFINED ${_mtd_targets_var} AND NOT "${${_mtd_targets_var}}" STREQUAL "") + list(APPEND _mtd_dep_targets ${${_mtd_targets_var}}) + elseif(TARGET ${_mtd_arg}::${_mtd_arg}) + list(APPEND _mtd_dep_targets ${_mtd_arg}::${_mtd_arg}) + else() + message(FATAL_ERROR + "[MedkitCompat] medkit_target_dependencies: could not resolve dependency '${_mtd_arg}' " + "for target '${target}'. Expected variable ${_mtd_arg}_TARGETS or imported target " + "${_mtd_arg}::${_mtd_arg}") + endif() + unset(_mtd_targets_var) + endif() + # Buffer resolved targets per visibility to avoid mixing target_link_libraries signatures + if(_mtd_visibility STREQUAL "PRIVATE") + list(APPEND _mtd_private_deps ${_mtd_dep_targets}) + elseif(_mtd_visibility STREQUAL "INTERFACE") + list(APPEND _mtd_interface_deps ${_mtd_dep_targets}) + else() + # Default to PUBLIC when no explicit visibility has been set + list(APPEND _mtd_public_deps ${_mtd_dep_targets}) + endif() + unset(_mtd_dep_targets) endif() endforeach() + if(_mtd_public_deps) + target_link_libraries(${target} PUBLIC ${_mtd_public_deps}) + endif() + if(_mtd_private_deps) + target_link_libraries(${target} PRIVATE ${_mtd_private_deps}) + endif() + if(_mtd_interface_deps) + target_link_libraries(${target} INTERFACE ${_mtd_interface_deps}) + endif() unset(_mtd_visibility) - unset(_mtd_arg) + unset(_mtd_public_deps) + unset(_mtd_private_deps) + unset(_mtd_interface_deps) endif() endmacro() From f5d2c654eca91689254007548b947c51ed028838 Mon Sep 17 00:00:00 2001 From: Bartosz Burda Date: Fri, 27 Feb 2026 15:09:16 +0100 Subject: [PATCH 4/4] Fix Rolling build: use plain target_link_libraries when no visibility specified On Rolling, ament_add_gtest_executable uses the plain signature for target_link_libraries. Our medkit_target_dependencies macro was unconditionally using the keyword signature (PUBLIC), causing CMake to error with "all uses must be either all-keyword or all-plain". Now the macro uses the plain signature when no visibility keyword is passed, and only uses keyword form when explicitly requested (e.g. medkit_target_dependencies(target PUBLIC dep1 dep2)). --- cmake/ROS2MedkitCompat.cmake | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/cmake/ROS2MedkitCompat.cmake b/cmake/ROS2MedkitCompat.cmake index 9efa9ff9..123cc238 100644 --- a/cmake/ROS2MedkitCompat.cmake +++ b/cmake/ROS2MedkitCompat.cmake @@ -170,6 +170,11 @@ endfunction() # On Humble/Jazzy: delegates to ament_target_dependencies (available). # On Rolling: uses target_link_libraries with ${dep_TARGETS}. # +# When no visibility keyword (PUBLIC/PRIVATE/INTERFACE) is passed, the macro +# uses the plain target_link_libraries signature. This avoids conflicts with +# ament_add_gtest_executable, which also uses the plain signature internally. +# When an explicit visibility keyword IS passed, the keyword signature is used. +# # Special cases: # yaml_cpp_vendor - vendor package, no _TARGETS; links yaml-cpp::yaml-cpp # (must call medkit_find_yaml_cpp() first) @@ -178,13 +183,22 @@ macro(medkit_target_dependencies target) if(COMMAND ament_target_dependencies) ament_target_dependencies(${target} ${ARGN}) else() - # Rolling fallback: resolve dependency targets explicitly and buffer per-visibility + # Rolling fallback: resolve dependency targets explicitly. + # + # CMake forbids mixing the "plain" and "keyword" (PUBLIC/PRIVATE/INTERFACE) + # signatures of target_link_libraries on the same target. + # ament_add_gtest_executable uses the plain signature internally, so we must + # also use the plain signature when no explicit visibility is requested. + # When the caller passes PUBLIC/PRIVATE/INTERFACE, we honour it (keyword form). + set(_mtd_has_visibility FALSE) set(_mtd_visibility "") + set(_mtd_plain_deps) set(_mtd_public_deps) set(_mtd_private_deps) set(_mtd_interface_deps) foreach(_mtd_arg ${ARGN}) if(_mtd_arg STREQUAL "PUBLIC" OR _mtd_arg STREQUAL "PRIVATE" OR _mtd_arg STREQUAL "INTERFACE") + set(_mtd_has_visibility TRUE) set(_mtd_visibility ${_mtd_arg}) else() # Resolve dependency to concrete CMake targets @@ -207,18 +221,26 @@ macro(medkit_target_dependencies target) endif() unset(_mtd_targets_var) endif() - # Buffer resolved targets per visibility to avoid mixing target_link_libraries signatures + # Buffer resolved targets per visibility bucket if(_mtd_visibility STREQUAL "PRIVATE") list(APPEND _mtd_private_deps ${_mtd_dep_targets}) elseif(_mtd_visibility STREQUAL "INTERFACE") list(APPEND _mtd_interface_deps ${_mtd_dep_targets}) - else() - # Default to PUBLIC when no explicit visibility has been set + elseif(_mtd_visibility STREQUAL "PUBLIC") list(APPEND _mtd_public_deps ${_mtd_dep_targets}) + else() + # No visibility keyword seen yet - use plain signature + list(APPEND _mtd_plain_deps ${_mtd_dep_targets}) endif() unset(_mtd_dep_targets) endif() endforeach() + # Plain deps (no visibility keyword) - use plain signature to stay compatible + # with ament_add_gtest_executable and other plain target_link_libraries calls + if(_mtd_plain_deps) + target_link_libraries(${target} ${_mtd_plain_deps}) + endif() + # Keyword deps - only emitted when caller explicitly specified visibility if(_mtd_public_deps) target_link_libraries(${target} PUBLIC ${_mtd_public_deps}) endif() @@ -228,7 +250,9 @@ macro(medkit_target_dependencies target) if(_mtd_interface_deps) target_link_libraries(${target} INTERFACE ${_mtd_interface_deps}) endif() + unset(_mtd_has_visibility) unset(_mtd_visibility) + unset(_mtd_plain_deps) unset(_mtd_public_deps) unset(_mtd_private_deps) unset(_mtd_interface_deps)