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

This comment has been minimized.

Copy link

@guru-florida 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

This comment has been minimized.

Copy link

@guru-florida 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

This comment has been minimized.

Copy link
Owner Author

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

This comment has been minimized.

Copy link

@guru-florida 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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Owner Author

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Owner Author

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

This comment has been minimized.

Copy link

@lingxd lingxd commented May 25, 2021

@rotu Thank you! This worked great.

@sardanian

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Owner Author

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

This comment has been minimized.

Copy link

@MagicRUBICK MagicRUBICK commented Jul 14, 2021

how to support the custom package by find_pakcage api?

find_package(${custom_package} REQUIRED)
@rotu

This comment has been minimized.

Copy link
Owner Author

@rotu rotu commented Jul 19, 2021

@MagicRUBICK

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

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