Packaging protobuf files using ament_cmake for ROS2
I'm trying to create an ament package for some protobuf files. Currently I have the cmake in my protobuf related package invoking protoc to generate the C++ and header files. However I feel like I'm missing something wrt exporting these autogenerated files with ament, as when I attempt to use the library elsewhere in another package, cmake fails to find the header files that I can verify are installed in the install/my_protobuf/include/proto
directory. I've provided a minimal example here:
https://github.com/ruffsl/ros2_docker...
For brevity, I'll post the two major cmake files here,
but you can build the accompanying dockerfile in the PR to reproduce the issue.
my_bridge
cmake_minimum_required(VERSION 3.5)
project(my_bridge)
find_package(ament_cmake REQUIRED)
find_package(example_interfaces
REQUIRED) find_package(my_common
REQUIRED) find_package(my_protobuf
REQUIRED) find_package(rclcpp
REQUIRED) find_package(std_msgs
REQUIRED)
my_package()
file(GLOB_RECURSE ALL_LIBRARY_HDRS
"include/*.hpp") file(GLOB_RECURSE
ALL_LIBRARY_SRCS "src/*.cpp")
file(GLOB_RECURSE ALL_EXECUTABLES
"src/*_main.cpp") list(REMOVE_ITEM
ALL_LIBRARY_SRCS ${ALL_EXECUTABLES})
list(APPEND ALL_LIBRARY_HDRS
${ALL_PROTO_HDRS}) list(APPEND
ALL_LIBRARY_SRCS ${ALL_PROTO_SRCS})
set(dependencies example_interfaces
my_protobuf rclcpp std_msgs )
include_directories(
include )
set(library_name ${PROJECT_NAME})
add_library(${library_name} SHARED
${ALL_LIBRARY_HDRS}
${ALL_LIBRARY_SRCS} )
ament_target_dependencies(${library_name}
${dependencies} )
set(executable_name
${library_name}_main)
add_executable(${executable_name}
src/my_bridge/bridge_main.cpp )
ament_target_dependencies(${executable_name}
${dependencies} )
target_link_libraries(${executable_name}
${library_name} )
install(TARGETS ${library_name}
${executable_name} ARCHIVE
DESTINATION lib LIBRARY DESTINATION
lib RUNTIME DESTINATION
lib/${PROJECT_NAME} )
install(DIRECTORY include/
DESTINATION include/ )
ament_export_include_directories(include)
ament_export_libraries(${library_name})
ament_export_dependencies(${dependencies})
ament_package()
my_protobuf
cmake_minimum_required(VERSION 3.5)
project(my_protobuf)
find_package(ament_cmake REQUIRED)
find_package(my_common REQUIRED)
find_package(Protobuf 3.0.0 REQUIRED)
my_package()
file(GLOB_RECURSE ALL_PROTOS
"*.proto") set(ALL_PROTO_SRCS)
set(ALL_PROTO_HDRS) foreach(ABS_FIL
${ALL_PROTOS}) file(RELATIVE_PATH
REL_FIL ${PROJECT_SOURCE_DIR}
${ABS_FIL})
get_filename_component(DIR ${REL_FIL}
DIRECTORY)
get_filename_component(FIL_WE
${REL_FIL} NAME_WE)
list(APPEND ALL_PROTO_SRCS
"${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.cc")
list(APPEND ALL_PROTO_HDRS
"${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.h")
file(MAKE_DIRECTORY
${PROJECT_BINARY_DIR}/${DIR})
add_custom_command(
OUTPUT
"${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.cc"
"${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.h"
COMMAND
"${PROTOBUF_PROTOC_EXECUTABLE}"
ARGS
--cpp_out ${PROJECT_BINARY_DIR}/${DIR}
--proto_path ${PROJECT_SOURCE_DIR}/${DIR}
${ABS_FIL}
DEPENDS
${ABS_FIL}
COMMENT
"Running C++ protocol buffer compiler on ${ABS_FIL}"
VERBATIM ) endforeach() set_source_files_properties(${ALL_PROTO_SRCS}
${ALL_PROTO_HDRS} PROPERTIES GENERATED
TRUE)
set(dependencies Protobuf )
set(library_name my_protobuf)
include_directories(
${PROJECT_BINARY_DIR} )
add_library(${library_name} SHARED
${ALL_PROTO_HDRS} ${ALL_PROTO_SRCS}
)
ament_target_dependencies(${library_name}
${dependencies} )
install(TARGETS ${library_name}
ARCHIVE DESTINATION lib LIBRARY
DESTINATION lib RUNTIME DESTINATION
lib/${PROJECT_NAME} ) foreach(HDR
${ALL_PROTO_HDRS})
file(RELATIVE_PATH REL_FIL
${PROJECT_BINARY_DIR} ${HDR})
get_filename_component(DIR ${REL_FIL}
DIRECTORY) install(
FILES ${HDR}
DESTINATION include/${DIR} ) endforeach()
ament_export_include_directories(include)
ament_export_libraries(${library_name})
ament_export_dependencies(${dependencies})
ament_package()
Error
--- stderr: my_bridge
/opt/ros_ws/src/my_bridge/src/my_bridge/bridge_node.cpp:20:10: fatal error: my_protobuf/proto/transform.pb.h: No such file or directory
#include "my_protobuf/proto/transform.pb.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/my_bridge.dir/src/my_bridge/bridge_node.cpp.o] Error 1
make[1]: *** [CMakeFiles/my_bridge.dir/all] Error 2
make: *** [all] Error 2
---
Failed <<< my_bridge [ Exited with code 2 ]
What is the content of the
install/my_protobuf/include
directory? What is the content of the variablemy_protobuf_INCLUDE_DIRS
in the packagemy_bridge
?tree /opt/ros_ws/install/my_protobuf/include/
find_package(my_protobuf REQUIRED)
message(WARNING "my_protobuf_INCLUDE_DIRS: " "${my_protobuf_INCLUDE_DIRS}")