Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
CLion top level ROS2 Workspace CMakeLists
cmake_minimum_required(VERSION 3.14)
project("ROS2 Master")
# usually I put this in a separate file include("/opt/ros/_common/Colcon.cmake")
function(colcon_add_subdirectories)
cmake_parse_arguments(PARSE_ARGV 0 "ARG" "" "BUILD_BASE;BASE_PATHS" "")
message("search criteria: ${ARGV}")
execute_process(COMMAND colcon list
--paths-only
--base-paths ${ARG_BASE_PATHS}
--topological-order
${ARG_UNPARSED_ARGUMENTS}
OUTPUT_VARIABLE paths)
string(STRIP "${paths}" paths)
string(REPLACE "\n" ";" paths "${paths}")
MESSAGE("colcon shows paths ${paths}")
foreach(path IN LISTS paths)
message("...examining ${path}")
# if(EXISTS "${path}/CMakeLists.txt")
execute_process(COMMAND colcon info --paths "${path}" OUTPUT_VARIABLE package_info)
if(NOT "${package_info}" MATCHES "type:[ \t]+(cmake|ros.ament_cmake|ros.cmake)")
message("skipping non-cmake project")
elseif(NOT "${package_info}" MATCHES "name:[ \t]+([^ \r\n\t]*)")
message(WARNING "could not identify package at ${path}")
else()
set(name "${CMAKE_MATCH_1}")
message("...adding package ${name} from path ${path}")
MESSAGE("package info: ${package_info}")
get_filename_component(BUILD_PATH "${name}" ABSOLUTE BASE_DIR "${ARG_BUILD_BASE}")
add_subdirectory("${path}" "${BUILD_PATH}")
endif()
endforeach()
endfunction()
colcon_add_subdirectories(
BUILD_BASE "${PROJECT_SOURCE_DIR}/build"
BASE_PATHS "${PROJECT_SOURCE_DIR}/src/"
--packages-select rmw_cyclonedds_cpp performance_test
)
@guru-florida
Copy link

guru-florida commented Dec 31, 2019

Thank you! This worked great. I wasn't sure about line 44 (package-select) but a bit of digging and I figured out it was a way to limit the packages included in the cmake project. Cool.

@guru-florida
Copy link

guru-florida commented Dec 31, 2019

How did you bring in the ament build environment variables? Or do you run clion after doing all the ROS workspace overlay sourcing? I wrote a quick bash script to echo required ENV lines after sourcing and then copy these into CLion for CMake settings and in the run targets ENV config. Did you find a better way?

    ros_env="AMENT_PREFIX_PATH CMAKE_PREFIX_PATH COLCON_PREFIX_PATH PKG_CONFIG_PATH PYTHONPATH LD_LIBRARY_PATH PATH ROS_DISTRO ROS_PYTHON_VERSION ROS_LOCALHOST_ONLY ROS_VERSION"
    for e in ${ros_env}; do
        echo "$e=${!e}"
    done

@rotu
Copy link
Author

rotu commented Dec 31, 2019

:-D Glad it helped. Yes, it's totally to limit the packages.

In CLion, I have configured the environment variables:
File -> Settings -> Build, Execution, Deployment -> CMake -> Environment

On that settings pane, I also set the Generation path to something like build\clion.

@guru-florida
Copy link

guru-florida commented Dec 31, 2019

Ok, thanks, I did it the same way. Also, I got full remote build/debugging of nodes on remote targets such as RPi using CLion. CLion can use ssh and it will rsync code to the target and use gdb over ssh. Very cool and slick for developing hardware-related nodes directly on the RPi but from your desktop CLion.

I followed this tutorial.
https://www.jetbrains.com/help/clion/remote-projects-support.html
Then copy ENV settings like you said, but ENV settings must come from target not desktop. So I do ROS sourcing on RPi and copy over.

@maxlein
Copy link

maxlein commented Jan 28, 2020

Should this only show me all the packages in clion or should it also be possible to compile all the packages?
Because I only see the packages but can't build, jump to declarations, etc ...

@rotu
Copy link
Author

rotu commented Jan 28, 2020

@maxlein It should just show a limited subset of packages. Edit the line --packages-select rmw_cyclonedds_cpp performance_test to choose which packages. (I tried selecting all packages but it didn’t work. You do need to filter it down if you’re building all of ROS from source but if you just have a few packages in your workspace you can just comment out that line)

@lingxd
Copy link

lingxd commented May 24, 2021


CMake Error at src/cpp_srvcli/CMakeLists.txt:19 (find_package):
  By not providing "Findament_cmake.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "ament_cmake", but CMake did not find one.

  Could not find a package configuration file provided by "ament_cmake" with
  any of the following names:

    ament_cmakeConfig.cmake
    ament_cmake-config.cmake

  Add the installation prefix of "ament_cmake" to CMAKE_PREFIX_PATH or set
  "ament_cmake_DIR" to a directory containing one of the above files.  If
  "ament_cmake" provides a separate development package or SDK, be sure it
  has been installed.

in Clion is erro

but terimal is ok. why?

@rotu
Copy link
Author

rotu commented May 24, 2021

@lingxd I think you may need to configure environment variables.

The easy way to check/work around:
Source setup.py then launch clion from the same shell. If that resolves the CMake error, you know it's the environment variables.

To make this work without launching CLion this way:
Check out what your setup script is doing with env -i bash -c "source setup.sh; env". There are probably some variables there to add to your CMake Environment. (File -> Settings -> Build, Execution, Deployment -> CMake -> Environment)

@lingxd
Copy link

lingxd commented May 25, 2021

@rotu Thank you! This worked great.

@sardanian
Copy link

sardanian commented Jun 14, 2021

This works for me when I use only a single package, but I get the following error when I use more than one package. I get this error for all the additional packages I build.

Any thoughts on how I could fix this if I wanted to be able to build multiple packages.

CMake Error at /opt/ros/dashing/share/ament_cmake_core/cmake/ament_cmake_uninstall_target-extras.cmake:35 (add_custom_target):
add_custom_target cannot create target "uninstall" because another target
with the same name already exists. The existing target is a custom target
created in source directory
"/home/user/colcon_ws/src/DynamixelSDK/dynamixel_sdk". See documentation
for policy CMP0002 for more details.

@rotu
Copy link
Author

rotu commented Jun 14, 2021

Any thoughts on how I could fix this if I wanted to be able to build multiple packages.

The problem here is that multiple projects are creating a target named uninstall. I'd set AMENT_CMAKE_UNINSTALL_TARGET to OFF. The uninstall target is pretty useless but I got pushback when trying to remove it in ament/ament_cmake#205.

@MagicRUBICK
Copy link

MagicRUBICK commented Jul 14, 2021

how to support the custom package by find_pakcage api?

find_package(${custom_package} REQUIRED)

@rotu
Copy link
Author

rotu commented Jul 19, 2021

@MagicRUBICK

find_package should work the same as it usually does. Maybe clarify what you're trying to do?

@janklatte
Copy link

janklatte commented Jun 27, 2022

Thanks this works great for building packages! I am running into problems however when I try to run a node in a debugger:

'Type support not from this implementation. Got:
Handle's typesupport identifier (rosidl_typesupport_cpp) is not supported by this library, at ./src/type_support_dispatch.hpp:111
Could not load library libsba_interfaces__rosidl_typesupport_fastrtps_cpp.so: dlopen error: libsba_interfaces__rosidl_typesupport_fastrtps_cpp.so: cannot open shared object file: No such file or directory, at ./src/shared_library.c:99, at ./src/type_support_dispatch.hpp:76
while fetching it, at ./src/subscription.cpp:117, at ./src/rcl/subscription.c:108'

with this new error message:

'invalid allocator, at ./src/rcl/subscription.c:218'

Did you add any modifications to your run/debug config?

@guru-florida
Copy link

guru-florida commented Jun 27, 2022

@janklatte That looks like you might be mixing Ros installations? Notice that first line. Could your env variables configured in your clion be pointing to a binary pkg installation perhaps? The warning "type support not from this implementation" indicates this, then it looks like maybe a linker error with invalid allocator since you have a mixed implementation (if this is in fact the case).

This could be a difference in ENV variables between your CLion toolchain setup, and your debug/runtime profile ENV setup.

Perhaps start your configuration fresh. new bash with clear env, source the Ros installation you want, then see my post above with the little for loop script to pull out the ros2 variables and copy/paste into CLion again. Two place, both under toolchain setup (for compilation) and under your debug profile (runtime). Before pasting in new env vars, clear out the previous stuff, especially PATH. In Clion Env dialog clearing out the top is easy, but the System vars in the bottom list you have to scroll through and look for the bolded lines that indicate system overriden ones. Then paste into the user ones and Apply.

@janklatte
Copy link

janklatte commented Jun 27, 2022

yes that was it thank you @guru-florida! Under my Toolchain configuration I added the setup.bash as environment file in previous attempts to get it working but forgot to remove it again. Now with just the copied environment variables in the cmake configuration it is working!

@janklatte
Copy link

janklatte commented Jun 27, 2022

Another smaller issue I have is that the linter/intellisense doesn't find the rclcpp/rclcpp.hpp header. Other ros2 headers are found (e.g. #include "message_filters/subscriber.h" or #include "nav_msgs/msg/grid_cells.hpp"). Might be an issue with the CMakeLists.txt but in case anyone already has an idea let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment