I am trying to combine two CMakeLists.txt files to compile a C++ program that has both ROS and Libtorch dependencies. The individual files are provided below:
Libtorch CMakeLists.txt file:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(example-app)
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
# The following code block is suggested to be used on Windows.
# According to https://github.com/pytorch/pytorch/issues/25457,
# the DLLs need to be copied to avoid memory errors.
if (MSVC)
file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll")
add_custom_command(TARGET example-app
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TORCH_DLLS}
$<TARGET_FILE_DIR:example-app>)
endif (MSVC)
I found this here: https://pytorch.org/cppdocs/installing.html
ROS CMakeListis.txt file:
cmake_minimum_required(VERSION 2.8.3)
project(fly_bot_cpp)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
geometry_msgs
tf
gazebo_msgs
)
include_directories(
include
${catkin_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
add_executable(example src/example.cpp)
target_link_libraries(example ${catkin_LIBRARIES})
The program example-app.cpp has both libraries of ROS and LibTorch.
So here is what i tried to do:
cmake_minimum_required(VERSION 2.8.3)
project(fly_bot_cpp)
set(CMAKE_PREFIX_PATH="home/jarvis/libtorch;/opt/ros/melodic")
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
geometry_msgs
tf
rospy
message_generation
)
find_package(Torch REQUIRED)
include_directories(
include
${catkin_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
add_executable(test_quad src/test_quad.cpp)
target_link_libraries(test_quad ${catkin_LIBRARIES} "${TORCH_LIBRARIES}")
set_property(TARGET test_quad PROPERTY CXX_STANDARD 14)
The code test_quad.cpp (previously referred to as example-app.cpp) contains ros header files and torch header files:
#include "ros/ros.h"
#include <torch/torch.h>
.
.
.
However, I get the following error.
fatal error: torch/torch.h: No such file or directory
#include <torch/torch.h>
^~~~~~~~~~~~~~~
compilation terminated.
Can someone please help me out??
Thank you so much.
Remove the quotes around ${TORCH_LIBRARIES} in your target_link_libraries.
The line should look like this
target_link_libraries(test_quad ${catkin_LIBRARIES} ${TORCH_LIBRARIES})
This should resolve the torch header.
Please also take a look at this post to find some more answers to where you might get stuck in the future-https://answers.ros.org/question/347885/combining-cmakeliststxt-of-libtorch-and-cmakeliststxt-of-ros-package/#
I hope this answer is helpful to someone new coming onboard to ros and libtorch :)
Related
I tried to used https://github.com/julianxhokaxhiu/SteamworksSDKCI to use steam api on a simple SFML application (helloworld).
I wanted to use cmake to learn it, but I am struggling to understand how the provided CMakeLists and Find*.cmake file are expected to be used.
Currently, I have modified the CMakeLists to change the INSTALL_DIR
INSTALL_DIR "${CMAKE_BINARY_DIR}/../../vendor"
and my CMakeLists is :
cmake_minimum_required(VERSION 3.19)
project(SfmlWithCMake VERSION 1.0)
include(FetchContent)
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake_steam")
# Configure external project
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/cmake_steam
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam
)
# Build external project
execute_process(
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/cmake_steam
)
set(BUILD_SHARED_LIBS OFF)
FetchContent_Declare(
SFML
GIT_REPOSITORY https://github.com/SFML/SFML.git
GIT_TAG 2.5.1
)
FetchContent_MakeAvailable(SFML)
find_package(STEAMWORKSSDK REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)
# Generate config.h
configure_file(config.h.in config.h)
add_executable(
SfmlWithCMake
main.cpp
)
get_target_property(STEAMSDK STEAMWORKSSDK::STEAMWORKSSDK INCLUDE_DIRECTORIES)
target_include_directories(
SfmlWithCMake
PRIVATE
"${PROJECT_BINARY_DIR}"
"${STEAMSDK}"
)
target_link_libraries(
SfmlWithCMake
sfml-graphics
STEAMWORKSSDK::STEAMWORKSSDK
-static gcc stdc++ winpthread -dynamic
)
install(TARGETS SfmlWithCMake DESTINATION bin)
How to get include directories?
I do not succeed to add the steam include to the target_include_directories.
Here the ${STEAMSDK} is my last attempt to get the directory.
If I replace this by ${PROJECT_BINARY_DIR}/vendor/include, everything works.
Also, why does the SFML include are automatically added to my target include directories and not the steam one?
Am I using the Find*.cmake file the right way?
I understood that ExternalProject_Add was performed at build time and thus, as the find_package is needed at configue time, I added the two "execute_process". But, the readme on github only says to do the find package and add the target to target_link_libraries...
Thanks.
I'm totally new to cmake, I'm on MacOs and I'm trying to build a c++ library and I need to link my executables to mpfr in order to make it work
This is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.19)
project(my_project)
set(CMAKE_CXX_STANDARD 14)
add_executable(my_project main.cpp)
find_package(GSL REQUIRED)
target_link_libraries(my_project GSL::gsl GSL::gslcblas)
find_package(Boost REQUIRED)
target_link_libraries(my_project Boost::boost)
find_package(MPFR REQUIRED) # <- It fails here!
target_link_libraries(my_project MPFR::mpfr)
When I try to build my project with CLion I get the following error:
CMake Error at CMakeLists.txt:13 (find_package):
By not providing "FindMPFR.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "MPFR", but
CMake did not find one.
Could not find a package configuration file provided by "MPFR" with any of
the following names:
MPFRConfig.cmake
mpfr-config.cmake
Add the installation prefix of "MPFR" to CMAKE_PREFIX_PATH or set
"MPFR_DIR" to a directory containing one of the above files. If "MPFR"
provides a separate development package or SDK, be sure it has been
installed.
After some research I found out that Cmake was linking correctly both GSL and Boost because there are both a /usr/local/share/cmake/Modules/FindGSL.cmake and a /usr/local/share/cmake/Modules/FindBoost.cmake file, So I looked online for a FindMPFR.cmake file to insert into the /usr/local/share/cmake/Modules/ directory, I tried with this one but the error remains the same. What am I doing wrong?
Edit:
Ok now my CMakeLists.txt file looks like this:
cmake_minimum_required(VERSION 3.19)
project(my_project)
set(CMAKE_CXX_STANDARD 14)
add_executable(my_project main.cpp )
# Append the cmake/ directory to the CMAKE_MODULE_PATH
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(GSL REQUIRED)
message(STATUS "GSL Found: ${GSL_FOUND}")
target_link_libraries(my_project GSL::gsl GSL::gslcblas)
find_package(Boost REQUIRED)
message(STATUS "Boost Found: ${Boost_FOUND}")
target_link_libraries(my_project Boost::boost)
find_package(MPFR REQUIRED)
message(STATUS "MPFR Found: ${MPFR_FOUND}")
target_link_libraries(my_project ${MPFR_LIBRARIES})
And it works fine :)
I have installed ros2 dashing diademata. I wrote a ROS2 node using C++14. I would like to read static_tf by creating a buffer and TransformListener
I am getting the following error when I include, #include "tf2_ros/buffer.h" If I do not include, I do not get any error.
The error is as follows
In file included from /opt/ros/dashing/include/tf2/LinearMath/Vector3.h:21:0,
from /opt/ros/dashing/include/tf2/LinearMath/Matrix3x3.h:19,
from /opt/ros/dashing/include/tf2/LinearMath/Transform.h:21,
from /opt/ros/dashing/include/tf2/buffer_core.h:35,
from /opt/ros/dashing/include/tf2_ros/buffer_interface.h:37,
from /opt/ros/dashing/include/tf2_ros/buffer.h:35,
from /module/src/example/include/example/example.h:17,
from /module/src/example/src/example.cpp:7:
/opt/ros/dashing/include/tf2/LinearMath/Scalar.h: In function ‘tf2Scalar tf2Log(tf2Scalar)’:
/opt/ros/dashing/include/tf2/LinearMath/Scalar.h:187:66: error: expression cannot be used as a function
TF2SIMD_FORCE_INLINE tf2Scalar tf2Log(tf2Scalar x) { return log(x); }
CMakeLists.txt is as follows
cmake_minimum_required(VERSION 3.5)
project(curb_odometry)
# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()
# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Wdeprecated-declarations -Wunused-parameter)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(nav_msgs REQUIRED)
find_package(std_msgs REQUIRED)
find_package(tf2_ros REQUIRED)
find_package(tf2 REQUIRED)
find_package(message_filters REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
include_directories(include
${Boost_INCLUDE_DIRS}
${tf2_ros_INCLUDE_DIRS}
${rclcpp_INCLUDE_DIRS}
${sensor_msgs_INCLUDE_DIRS}
${geometry_msgs_INCLUDE_DIRS}
${nav_msgs_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
${message_filters_INCLUDE_DIR}
)
link_directories(${Boost_LIBRARY_DIRS})
add_executable(example src/example.cpp src/curb_detection.cpp src/curb_odometry.cpp)
target_link_libraries(example ${Boost_LIBRARIES} )
target_include_directories(example PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
ament_target_dependencies(
example
"rclcpp"
"sensor_msgs"
"geometry_msgs"
"nav_msgs"
"std_msgs"
"boost"
"message_filters"
"geometry2"
"tf2_ros"
"tf2"
)
install(TARGETS example
EXPORT export_${PROJECT_NAME}
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# uncomment the line when a copyright and license is not present in all source files
#set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
Looks like the error is coming from tf library. Any help in this regard will be appreciable.
I make my own example following this. But I don't want to make library, but just generate header and source files from .proto file.
So, I just change:
CMakeLists.txt
PROJECT(rpc)
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
SET(CMAKE_CXX_FLAGS "-g -Wall -Werror -std=c++11")
ADD_SUBDIRECTORY(proto)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_EXECUTABLE(main main.cpp)
#TARGET_LINK_LIBRARIES(main proto ${PROTOBUF_LIBRARY})
TARGET_LINK_LIBRARIES(main ${PROTOBUF_LIBRARY}) #<==== I changed here
proto/CMakeLists.txt
INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER message.proto)
#ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC}) #I don't compile lib anymore
But it doesn't generate header and source files from .proto. So it cannot compile. I think when using add_subdirectory, it doesn't run command protobuf_generate_cpp. Any idea is appreciated.
You can either add ${PROTO_HEADER} ${PROTO_SRC} directly to ADD_EXECUTABLE(main) call or add the following line to proto/CMakeLists.txt:
add_custom_target(gen_proto ALL DEPENDS ${PROTO_HEADER} ${PROTO_SRC})
My cmake configuration is not generating any protobuf src and header files.
I've already checked if the proto files can be found.
Cmakelists.txt
cmake_minimum_required(VERSION 3.0.2)
..
include(FindProtobuf REQUIRED)
file(GLOB PROTO_DEF "${CMAKE_CURRENT_SOURCE_DIR}/protobuf/*/*.proto")
foreach(file ${PROTO_DEF})
if(EXISTS ${file})
MESSAGE("YES")
else()
MESSAGE("NO")
endif()
endforeach()
SET(PROTOBUF_GENERATE_CPP_APPEND_PATH PROTOBUF)
SET(PROTOBUF_PROTOC_EXECUTABLE protoc.exe)
..
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_INCL ${PROTO_DEF})
..
add_library(${PROJECT_NAME} STATIC ${INCLUDES} ${INTERNAL_INCLUDES} ${SRC} ${PROTO_SRC} ${PROTO_INCL})
target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})
I have checked the FindProtobuf.cmake and half way through:
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
MESSAGE(1 ${CMAKE_CURRENT_BINARY_DIR})
MESSAGE(2 ${_protobuf_include_path})
MESSAGE(3 ${ABS_FIL})
MESSAGE(4 ${PROTOBUF_PROTOC_EXECUTABLE})
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL}
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
You can see i've added the 4 message commands, the script reaches this point and variables show good values.
The proto files do have a depencency to the library, thus the command should get executed !?
Any ideas on this problem?
update
replacing the add_custom_command with
EXEC_PROGRAM(${PROTOBUF_PROTOC_EXECUTABLE} ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
does generate the source and header files, must i manually activate the custom_commmands?
Regards Auke
The add_custom_command is fired (for my project) during compilation time.
Adding
SET_SOURCE_FILES_PROPERTIES(${PROTO_SRC} ${PROTO_INCL} PROPERTIES GENERATED TRUE)
gives cmake info that the files will be generated.
Alternative if you have an external proto folder:
file(GLOB PROTOBUF_FILELIST ${PROTO_INCLUDE_DIR}/*.proto)
foreach( proto_file ${PROTOBUF_FILELIST} )
get_filename_component(proto_name ${proto_file} NAME_WE)
get_filename_component(proto_path ${PROTO_INCLUDE_DIR} ABSOLUTE)
set_source_files_properties("${proto_path}/${proto_name}.pb.cc"
"${proto_path}/${proto_name}.pb.h"
PROPERTIES GENERATED TRUE)
endforeach()
See that:
https://cmake.org/cmake/help/v3.20/module/FindProtobuf.html
Example:
find_package(Protobuf REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS DESCRIPTORS PROTO_DESCS foo.proto)
protobuf_generate_python(PROTO_PY foo.proto)
add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
target_link_libraries(bar ${Protobuf_LIBRARIES})
Note The protobuf_generate_cpp and protobuf_generate_python functions and add_executable() or add_library() calls only work properly within the same directory.
This problem only happens when the target is a library (using add_library, add_executable seems to be fine). The PROTOBUF_GENERATE_CPP will defer the generation of protobuf sources and headers when building the library. A workaround is to define a custom target and add it as a dependency to the lib target. e.g.
add_custom_target(proto_dep DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
add_library(${PROJECT_NAME} STATIC ${OTHER_SRCS})
add_dependencies(${PROJECT_NAME} proto_dep)
target_link_libraries(${PROJECT_NAME} PRIVATE gRPC::grpc++ gRPC::grpc++_reflection protobuf::libprotobuf)