Ask Your Question
1

Trying to compile a ROS 2 Eloquent package depending on a pure cmake package using colcon [closed]

asked 2020-02-17 23:38:23 -0500

Marc Testier gravatar image

Hello there,

I have been fighting for some time with CMakeLists trying to compile a ROS 2 Eloquent package (bar) depending on a pure cmake package (foo) using colcon but I get the following error:

<...>/bar.hpp:5:10: fatal error: foo/foo.hpp: No such file or directory #include "foo/foo.hpp"

I've made a minimal repo showing my problem here: https://github.com/MarcTestier/ros2_c....

The install folder of the cmake package (foo) seems somewhat normal though, its folder tree looks like this:

install/foo/  
├── include  
│   └── foo  
│       ├── foo.hpp  
│       └── foo_export.h  
├── lib  
│   └── libfoo.so  
└── share  
    ├── colcon-core  
    │   └── packages  
    │       └── foo  
    └── foo  
        ├── cmake  
        │   ├── fooConfig.cmake  
        │   ├── fooConfigVersion.cmake  
        │   ├── fooTargets-noconfig.cmake  
        │   └── fooTargets.cmake  
        ├── hook  
        │   ├── cmake_prefix_path.dsv  
        │   ├── cmake_prefix_path.ps1  
        │   ├── cmake_prefix_path.sh  
        │   ├── ld_library_path_lib.dsv  
        │   ├── ld_library_path_lib.ps1  
        │   ├── ld_library_path_lib.sh  
        │   ├── pkg_config_path.dsv  
        │   ├── pkg_config_path.ps1  
        │   ├── pkg_config_path.sh  
        │   ├── pkg_config_path_multiarch.dsv  
        │   ├── pkg_config_path_multiarch.ps1  
        │   └── pkg_config_path_multiarch.sh  
        ├── package.bash  
        ├── package.dsv  
        ├── package.ps1  
        ├── package.sh  
        └── package.zsh

It seems like the ROS 2 package (bar) has trouble finding the cmake package (foo) library and headers but find_package(foo) works.

I found an ugly solution (available in the repo here) which consists of 2 steps:

1.Manually add the include directory

get_filename_component(INSTALL_DIR ${CMAKE_INSTALL_PREFIX} DIRECTORY)
include_directories(${INSTALL_DIR}/foo/include/)

If I only perform step 1, I can find the header files but I get an error: /usr/bin/ld: cannot find -lfoo which I guess means that even though I do the following:

target_link_libraries(Bar foo)

Bar still can't properly find the foo library.

2.If on top of the first step I link directly against the .so file:

target_link_libraries(Bar "${INSTALL_DIR}/foo/lib/libfoo.so")

Now the packages can compile but the solution seems a bit ugly.

I'm out of idea and I can't tell if the problem comes from a pure cmake problem, colcon moving/linking stuff around or anything else so any suggestions are welcomed, thanks.

edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by Marc Testier
close date 2020-02-18 18:21:01.449900

1 Answer

Sort by » oldest newest most voted
4

answered 2020-02-18 10:33:08 -0500

sloretz gravatar image

updated 2020-02-18 10:38:37 -0500

Package foo is exporting the library target foo in the foo:: namespace.

# Export targets.
set(export_targets ${export_targets};${PROJECT_NAME})
export(
  EXPORT export_${PROJECT_NAME}
  FILE "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Targets.cmake"
  NAMESPACE ${PROJECT_NAME}::
)

But package bar is trying to link against exported library target foo with no namespace.

## Declare a cpp executable
add_executable(Bar src/bar.cpp)
ament_target_dependencies(Bar rclcpp)
target_link_libraries(Bar foo)

Change it to foo::foo to match what package foo is exporting

target_link_libraries(Bar foo::foo)

In case you see this again, when debugging CMake packages not finding another package's headers I find it's helpful to use CMAKE_VERBOSE_MAKEFILE.

colcon build --event-handlers console_direct+ --cmake-args -DCMAKE_VERBOSE_MAKEFILE=TRUE

That showed foo's include directory wasn't being passed to the compiler, which suggested I should look at pure CMake issues first.

[ 50%] Building CXX object CMakeFiles/Bar.dir/src/bar.cpp.o
/usr/bin/c++   -I/tmp/ros2_cmake_test/bar/include -I/opt/ros/eloquent/include  -Wall -Wextra -Wpedantic -std=gnu++14 -o CMakeFiles/Bar.dir/src/bar.cpp.o -c /tmp/ros2_cmake_test/bar/src/bar.cpp

After fixing the target name, foo's include directory is correctly passed to the compiler and the build succeeds.

[ 50%] Building CXX object CMakeFiles/Bar.dir/src/bar.cpp.o
/usr/bin/c++   -I/tmp/ros2_cmake_test/bar/include -I/opt/ros/eloquent/include -isystem /tmp/ros2_cmake_test/install/foo/include  -Wall -Wextra -Wpedantic -std=gnu++14 -o CMakeFiles/Bar.dir/src/bar.cpp.o -c /tmp/ros2_cmake_test/bar/src/bar.cpp
edit flag offensive delete link more

Comments

It works, thank you for the help!!

Marc Testier gravatar image Marc Testier  ( 2020-02-18 18:20:26 -0500 )edit

Saved me too. Thanks @sloretz!

Thomas D gravatar image Thomas D  ( 2020-10-29 10:10:49 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2020-02-17 23:38:23 -0500

Seen: 530 times

Last updated: Feb 18 '20