This question already has answers here:
Libraries in /usr/local/lib not found
(1 answer)
Why the installed program has error when loading shared library in linux (cmake)
(3 answers)
Closed 2 years ago.
I'm building a kmeans executable from this cmake file:
# check the minimum version
cmake_minimum_required( VERSION 3.16 )
# the project name
project( kmeans )
#########################################################################
#### Define all the global variables to compile the application
#########################################################################
set( APPLICATION_NAME "kmeans")
#########################################################################
#### Adjust compiling option for this application
#########################################################################
# force the Release build if not already set
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE)
# setting common c++ flags
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -pthread -std=c++17 -static-libgcc -DKMEANS_DATASET_PATH=\"\\\"${CMAKE_CURRENT_SOURCE_DIR}/dataset/\\\"\"")
# setting debug flags
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -g3 -O0")
# setting release with debug info flags
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=native -mtune=native -g3 -O2")
# setting release flags
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native -mtune=native -O3")
#########################################################################
#### Find external libaries
#########################################################################
# Boost program options
find_package(Boost REQUIRED program_options)
# include the directories
include_directories(${Boost_INCLUDES} )
################################
#### Sources
################################
set( KMEANS_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src)
set( KMEANS_HDR_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include)
set( KMEANS_HDR_FILES
${KMEANS_HDR_PATH}/kmeans.h
)
set( KMEANS_SRC_FILES
${KMEANS_SRC_PATH}/main.cc
${KMEANS_SRC_PATH}/cluster.c
${KMEANS_SRC_PATH}/kmeans_clustering.c
)
include_directories( ${KMEANS_HDR_PATH} )
################################
#### Compilation
################################
#----- Set binary name for the mini-app
add_executable(${APPLICATION_NAME} ${KMEANS_SRC_FILES} ${KMEANS_HDR_FILES})
target_link_libraries(${APPLICATION_NAME} Boost::program_options)
################################
#### Install
################################
install( TARGETS ${APPLICATION_NAME} DESTINATION ${PROJECT_SOURCE_DIR}/bin )
After building the kmeans executable gets generated correctly inside the build dir (build/kmeans) and works perfectly. After a make install tho the generated binary (bin/kmeans) gives the following error ./kmeans: error while loading shared libraries: libboost_program_options.so.1.75.0: cannot open shared object file: No such file or directory. I tried to take a look at the install command doc but couldn't find any option taking care of the case. I suppose I'm missing something inside the cmake file but cannot spot it.
Related
I am trying to build a ROS2 package, and I get this error
CMake Error at /opt/ros/foxy/share/ament_cmake_target_dependencies/cmake/ament_target_dependencies.cmake:66 (message):
ament_target_dependencies() the passed package name 'Eigen3::Eigen' was not
found before
Call Stack (most recent call first):
CMakeLists.txt:83 (ament_target_dependencies)
I am trying to solve it using this, however i cannot identify which is my source folder for eigen3 installation.
What changes should I should make to my CMakelist?
libeigen3-dev is already the newest version (3.3.7-2).
and also
ros-foxy-eigen3-cmake-module is already the newest version(0.1.1-1focal.20210423.000604).
CMakelist:
cmake_minimum_required(VERSION 3.5)
project(avoidance)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
endif()
find_package(ament_cmake REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(perception_pcl REQUIRED)
find_package(rclcpp REQUIRED)
find_package(tf2 REQUIRED)
get_default_rmw_implementation(rmw_implementation)
find_package("${rmw_implementation}" REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(px4_msgs REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(std_msgs REQUIRED)
find_package(PythonInterp REQUIRED)
find_package(eigen3_cmake_module REQUIRED)
find_package(Eigen3 REQUIRED NO_MODULE)
find_package(Boost REQUIRED COMPONENTS system)
find_package(PCL REQUIRED)
if(DISABLE_SIMULATION)
message(STATUS "Building avoidance without Gazebo Simulation")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDISABLE_SIMULATION")
else()
message(STATUS "Building avoidance with Gazebo Simulation")
find_package(yaml-cpp REQUIRED)
endif(DISABLE_SIMULATION)
#################
# Setup targets #
#################
## CMake Setup
# Build in Release mode if nothing is specified
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE)
## Specify additional locations of header files
include_directories(
include
${rclcpp_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
${YAML_CPP_INCLUDE_DIR}
)
## Declare a C++ library
set(AVOIDANCE_CPP_FILES
"src/common.cpp"
"src/histogram.cpp"
"src/transform_buffer.cpp"
"src/avoidance_node.cpp"
)
if(NOT DISABLE_SIMULATION)
set(AVOIDANCE_CPP_FILES "${AVOIDANCE_CPP_FILES}" "src/rviz_world_loader.cpp")
endif()
# Add avoidance lib
add_library(avoidance SHARED "${AVOIDANCE_CPP_FILES}")
ament_target_dependencies(avoidance Eigen3 px4_msgs ${${PROJECT_NAME}_EXPORTED_TARGETS})
target_include_directories(avoidance PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}>
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
${Eigen3_INCLUDE_DIRS}
)
## Specify libraries to link a library or executable target against
target_link_libraries(
avoidance
Eigen3::Eigen
${YAML_CPP_LIBRARIES}
)
# Add node dependencies
ament_target_dependencies(avoidance px4_msgs rclcpp Eigen3::Eigen)
# Export information to downstream packages
ament_export_dependencies(ament_cmake rclcpp rosidl_default_runtime eigen3_cmake_module Eigen3 px4_msgs geometry_msgs sensor_msgs std_msgs)
ament_export_interfaces(export_avoidance HAS_LIBRARY_TARGET)
ament_export_include_directories(include)
ament_export_libraries(avoidance)
#############
## Install ##
#############
# Install header files
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION include/${PROJECT_NAME}
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
# Install artifacts
install(TARGETS avoidance
EXPORT export_avoidance
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
# Install launch files
install(DIRECTORY
launch
DESTINATION share/${PROJECT_NAME}
)
#############
## Testing ##
#############
# if(CATKIN_ENABLE_TESTING)
# # Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/main.cpp
# test/test_common.cpp
# test/test_usm.cpp
# test/test_transform_buffer.cpp
# )
#
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}
# ${catkin_LIBRARIES}
# ${YAML_CPP_LIBRARIES})
# endif()
#
#
# if (${CMAKE_BUILD_TYPE} STREQUAL "Coverage")
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage --coverage")
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage --coverage")
# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
#
# add_custom_target(${PROJECT_NAME}-test_coverage
# COMMAND lcov --zerocounters --directory ${PROJECT_BINARY_DIR}
# COMMAND lcov --capture --initial --no-external --directory ${PROJECT_BINARY_DIR} --base-directory ${${PROJECT_NAME}_SOURCE_DIR} --output-file base_coverage.info --rc lcov_branch_coverage=1
# COMMAND ${PROJECT_NAME}-test
# COMMAND lcov --capture --no-external --directory ${PROJECT_BINARY_DIR} --base-directory ${${PROJECT_NAME}_SOURCE_DIR} --output-file test_coverage.info --rc lcov_branch_coverage=1
# COMMAND lcov -a base_coverage.info -a test_coverage.info -o coverage.info --rc lcov_branch_coverage=1
# COMMAND lcov --rc lcov_branch_coverage=1 --summary coverage.info
# WORKING_DIRECTORY .
# DEPENDS ${PROJECT_NAME}-test
# )
# add_custom_target(${PROJECT_NAME}-test_coverage_html
# COMMAND genhtml coverage.info --output-directory out --branch-coverage
# COMMAND x-www-browser out/index.html
# WORKING_DIRECTORY .
# DEPENDS ${PROJECT_NAME}-test_coverage
# )
# endif()
# endif()
ament_package()
Taking a look at nav2_smac_planner/CMakeLists.txt
I found that you actually use Eigen3 inside the ament_target_dependencies instead of eigen3_cmake_module.
There they also export it in ament_export_dependencies.
So... for including the header, you should use Eigen3, but dependency-wise, eigen3_cmake_modules should be used.
I've been struggling to fix an intermediate linking error that I get when using CMake to build my nvcc project. I've been upgrading a previous project to utilize CUDA and was able to successfully call functions from that library from host code. When I try to call functions of that library from device code, I get the intermediate linking error. I annotated all of the functions with __device__ and __host__ descriptors.
As a side note, this is a ROS project, so I'm using some of the catkin CMake functions.
This is a snippet from the ParticleFilter code that calls the host and device functions:
#include <cuda.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#include <curand_kernel.h>
#include <iostream>
#include <davinci_kinematics_cuda/davinci_fwd_kinematics.cuh>
__host__
ParticleFilter::ParticleFilter(const unsigned int numParticles, const std::vector<double> &initialJointState, const unsigned int threads,
const unsigned int blocks) {
/* random other work here */
// This works fine (compiles and runs), it is calling host code from the other file
kinematics = davinci_kinematics_cuda::Forward();
std::cout << kinematics.fwd_kin_solve(initialJointState.data()).translation() << std::endl;
}
__global__
void printParticlesKernel(double *particles, const unsigned int numParticles, const unsigned int dimensions, const size_t pitch) {
int locationStart = blockIdx.x * blockDim.x + threadIdx.x;
int stride = blockDim.x * gridDim.x;
// This fails, will not link
davinci_kinematics_cuda::Forward kinematics = davinci_kinematics_cuda::Forward();
for (int n = locationStart; n < numParticles; n += stride) {
double *particle = (double*) ((char*) particles + n * pitch);
/* random other work here */
// this fails, will not link
auto translation = kinematics.fwd_kin_solve(particle).translation();
printf("%f %f %f\n", translation[0], translation[1], translation[2]);
}
}
And this is from the kinematics file:
#include <cuda.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
namespace davinci_kinematics_cuda {
// use member fncs to compute and multiply successive transforms
__host__ __device__
Forward::Forward() {
/* random initialization here */
}
__host__ __device__
Eigen::Affine3d Forward::fwd_kin_solve(const double *q_vec, const unsigned int desired_joint) {
/* other work here */
}
}
This is the relevant CMake parts for the ParticleFilter file.
cmake_minimum_required(VERSION 2.8.10)
project(tool_tracking LANGUAGES CUDA CXX)
# https://stackoverflow.com/questions/25748039/add-cuda-to-ros-package
find_package(CUDA REQUIRED)
# set CUDA_NVCC_FLAGS as you would do with CXX/C FLAGS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CURAND_FLAGS} -fPIC")
set(CUDA_SEPARABLE_COMPILATION ON)
find_package(catkin REQUIRED COMPONENTS
message_generation
roscpp
std_msgs
sensor_msgs
geometry_msgs
cwru_opencv_common
tool_model
cwru_davinci_control
cwru_davinci_kinematics
xform_utils
tf
tool_segmentation
)
catkin_package(
INCLUDE_DIRS
include
LIBRARIES
tool_tracking_particle
CATKIN_DEPENDS
message_runtime
std_msgs
sensor_msgs
geometry_msgs
cwru_opencv_common
tool_model
cwru_davinci_control
cwru_davinci_kinematics
xform_utils
tf
)
include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
include_directories(include ${catkin_INCLUDE_DIRS} tool_model_lib )
cuda_add_executable(test_particlefilter src/ParticleFilter.cu src/Particle.cu)
target_link_libraries(test_particlefilter tool_tracking_particle ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${CUDA_LIBRARIES})
This is the error from CMake:
/usr/bin/cmake -H/home/ethan/catkin_ws/src/cwru_davinci_tool_tracking/tool_tracking -B/home/ethan/catkin_ws/build/tool_tracking --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/ethan/catkin_ws/build/tool_tracking/CMakeFiles /home/ethan/catkin_ws/build/tool_tracking/CMakeFiles/progress.marks
/usr/bin/make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/ethan/catkin_ws/build/tool_tracking'
/usr/bin/make -f CMakeFiles/test_particlefilter.dir/build.make CMakeFiles/test_particlefilter.dir/depend
make[2]: Entering directory '/home/ethan/catkin_ws/build/tool_tracking'
[ 20%] Building NVCC intermediate link file CMakeFiles/test_particlefilter.dir/test_particlefilter_intermediate_link.o
/usr/local/cuda-11.0/bin/nvcc -lcudadevrt -m64 -ccbin /usr/bin/cc -dlink /home/ethan/catkin_ws/build/tool_tracking/CMakeFiles/test_particlefilter.dir/src/./test_particlefilter_generated_ParticleFilter.cu.o /home/ethan/catkin_ws/build/tool_tracking/CMakeFiles/test_particlefilter.dir/src/./test_particlefilter_generated_Particle.cu.o -o /home/ethan/catkin_ws/build/tool_tracking/CMakeFiles/test_particlefilter.dir/./test_particlefilter_intermediate_link.o -Xcompiler -fPIC
nvlink error : Undefined reference to '_ZN23davinci_kinematics_cuda7ForwardC1Ev' in '/home/ethan/catkin_ws/build/tool_tracking/CMakeFiles/test_particlefilter.dir/src/./test_particlefilter_generated_ParticleFilter.cu.o'
nvlink error : Undefined reference to '_ZN23davinci_kinematics_cuda7Forward13fwd_kin_solveEPKdj' in '/home/ethan/catkin_ws/build/tool_tracking/CMakeFiles/test_particlefilter.dir/src/./test_particlefilter_generated_ParticleFilter.cu.o'
CMakeFiles/test_particlefilter.dir/build.make:1468: recipe for target 'CMakeFiles/test_particlefilter.dir/test_particlefilter_intermediate_link.o' failed
make[2]: Leaving directory '/home/ethan/catkin_ws/build/tool_tracking'
make[2]: *** [CMakeFiles/test_particlefilter.dir/test_particlefilter_intermediate_link.o] Error 255
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/test_particlefilter.dir/all' failed
make[1]: Leaving directory '/home/ethan/catkin_ws/build/tool_tracking'
make[1]: *** [CMakeFiles/test_particlefilter.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2
How do I fix the error with the undefined reference? Seems like a linking error, but I am not familiar enough with the compilation / linking process to troubleshoot any further. If I need to post the CMake from the kinematics file I can as well.
Here's the key issue and the part that will be most helpful to other readers of this question. Catkin configures CMake to build shared libraries by default but CUDA separable compilation and nvlink only work with static libraries. You need to set your CUDA libraries (in your case, those in cwru_davinci_kinematics) to be static, always. You can do that by adding the STATIC keyword to the add_library call, as in:
add_library(my_cuda_lib STATIC source1.cu ...)
If you "link" to a shared library with CUDA in CMake, it will just ignore it. This is actually the documented behavior of nvcc. See here: https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/#libraries
The device linker has the ability to read the static host library formats (.a on Linux and Mac OS X, .lib on Windows). It ignores any dynamic (.so or .dll) libraries.
Another major lesson here is that setting CMake to an ancient version is bound to cause problems. While reproducing your issue, I was forced to build OpenCV 3 from source (it's not in Ubuntu 20.04 LTS) and there is no good way to override the search path for a particular package prior to version 3.12, which introduced CMP0074.
Upgrade your minimum CMake version. Ideally you would upgrade to the newest version available to you in your software repositories and set your files' minimums to that. There is zero benefit to being compatible with CMake versions earlier than ~3.5, and I would argue that extends up to 3.16 (the version in Ubuntu 20.04 LTS). Since you're using CUDA, 3.18 is most appropriate. Even worse, many of your projects set a minimum below 2.8.12; compatibility with this version will very soon be removed by CMake.
Here are the exact changes I made to get it to build on Ubuntu 20.04 LTS. I used the following build script, placed in and executed from the ROS workspace:
#!/usr/bin/bash
source /opt/ros/noetic/setup.bash
export CUDACXX=/usr/local/cuda/bin/nvcc
export OpenCV_ROOT=$(readlink -f opencv-install)
[ -f "$CUDACXX" ] || { echo "Invalid CUDACXX: $CUDACXX"; exit; }
[ -d "$OpenCV_ROOT" ] || { echo "Invalid OpenCV_ROOT: $OpenCV_ROOT"; exit; }
rm -rf build devel
catkin build tool_tracking --cmake-args \
-Wno-dev \
-DCMAKE_POLICY_DEFAULT_CMP0074=NEW \
-DCMAKE_CUDA_ARCHITECTURES=75
The directory opencv-install was created by building my own OpenCV 3 (because Ubuntu 20.04 only has v4). The steps for that were:
$ git clone -b 3.4.14 git#github.com:opencv/opencv.git
$ git clone -b 3.4.14 git#github.com:opencv/opencv_contrib.git
$ cmake -G Ninja -S opencv -B opencv-build/ -DOPENCV_EXTRA_MODULES_PATH=$(readlink -f opencv_contrib)/modules -DBUILD_opencv_cnn_3dobj=OFF -DBUILD_opencv_face=OFF -DBUILD_opencv_hdf=OFF -DBUILD_opencv_hfs=OFF -DBUILD_opencv_julia=OFF -DBUILD_opencv_matlab=OFF -DBUILD_opencv_ovis=OFF -DBUILD_opencv_reg=OFF -DBUILD_opencv_sfm=OFF -DBUILD_opencv_text=OFF -DBUILD_opencv_wechat_qrcode=OFF -DBUILD_opencv_ximgproc=OFF
$ cmake --build opencv-build
$ cmake --install opencv-build --prefix opencv-install
This disables the extra modules that have significant/irrelevant dependencies.
The script sets the environment variable OpenCV_ROOT to direct CMake to this locally installed version of OpenCV. Because the minimum version of CMake specified in the file is so low, I must also set CMAKE_POLICY_DEFAULT_CMP0074=NEW so that OpenCV_ROOT will be honored.
Here are the changes I made to your CMake code:
src/cwru_davinci_kinematics/CMakeLists.txt
--- a/src/cwru_davinci_kinematics/CMakeLists.txt
+++ b/src/cwru_davinci_kinematics/CMakeLists.txt
## -1,4 +1,4 ##
-cmake_minimum_required(VERSION 2.8.10)
+cmake_minimum_required(VERSION 3.18)
project(cwru_davinci_kinematics)
#This is needed as part of the migration to ros jade and later
## -26,18 +26,16 ## find_package(catkin REQUIRED COMPONENTS roscpp roslib roslint tf tf2 tf2_eigen)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++0x")
-# https://stackoverflow.com/questions/25748039/add-cuda-to-ros-package
-find_package(CUDA)
-message(STATUS "CUDA_FOUND=${CUDA_FOUND}")
-if(CUDA_FOUND)
- message(STATUS "Found CUDA, setting nvcc compilation flags")
-
- # set CUDA_NVCC_FLAGS as you would do with CXX/C FLAGS
- set(CUDA_NVCC_FLAGS CACHE STRING "nvcc flags" FORCE)
- set(CUDA_VERBOSE_BUILD ON CACHE BOOL "nvcc verbose" FORCE)
+include(CheckLanguage)
+check_language(CUDA)
+if (CMAKE_CUDA_COMPILER)
+ enable_language(CUDA)
+
# fPIC fixes some linker issues with nvcc code / objects
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CURAND_FLAGS} -fPIC")
- set(CUDA_SEPARABLE_COMPILATION ON)
+ set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -fPIC")
+ set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
+
+ find_package(CUDAToolkit REQUIRED)
endif()
include_directories(
## -48,7 +46,7 ## include_directories(
${YAML_CPP_INCLUDE_DIRS}
)
-if (CUDA_FOUND)
+if (CMAKE_CUDA_COMPILER)
catkin_package(
DEPENDS ${Eigen3_DEP}
LIBRARIES
## -82,14 +80,17 ## target_link_libraries(davinci_kinematics
davinci_kinematic_definitions
)
-if (CUDA_FOUND)
- cuda_add_library(davinci_kinematics_cuda src/davinci_fwd_kinematics.cu)
- cuda_add_library(davinci_kinematics_definitions_cuda src/davinci_kinematic_definitions.cu)
-
- target_link_libraries(davinci_kinematics_cuda
- ${catkin_LIBRARIES}
- davinci_kinematics_definitions_cuda
- )
+if (CMAKE_CUDA_COMPILER)
+ add_library(davinci_kinematics_cuda STATIC src/davinci_fwd_kinematics.cu)
+ add_library(davinci_kinematics_definitions_cuda STATIC src/davinci_kinematic_definitions.cu)
+
+ target_link_libraries(
+ davinci_kinematics_cuda
+ PRIVATE
+ CUDA::curand
+ ${catkin_LIBRARIES}
+ davinci_kinematics_definitions_cuda
+ )
endif()
# Examples
The important lines here are:
add_library(davinci_kinematics_cuda STATIC src/davinci_fwd_kinematics.cu)
add_library(davinci_kinematics_definitions_cuda STATIC src/davinci_kinematic_definitions.cu)
I also modernized the CMake code here, because the built-in CUDA language support has considerably advanced.
src/cwru_davinci_tool_tracking/tool_tracking/CMakeLists.txt
--- a/src/cwru_davinci_tool_tracking/tool_tracking/CMakeLists.txt
+++ b/src/cwru_davinci_tool_tracking/tool_tracking/CMakeLists.txt
## -1,18 +1,11 ##
-cmake_minimum_required(VERSION 2.8.10)
-project(tool_tracking LANGUAGES CUDA CXX)
+cmake_minimum_required(VERSION 3.18)
+project(tool_tracking LANGUAGES C CXX CUDA)
-# https://stackoverflow.com/questions/25748039/add-cuda-to-ros-package
-find_package(CUDA REQUIRED)
+set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -fPIC")
+set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
-# set CUDA_NVCC_FLAGS as you would do with CXX/C FLAGS
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CURAND_FLAGS} -fPIC")
-set(CUDA_SEPARABLE_COMPILATION ON)
+find_package(OpenCV 3 REQUIRED)
-#find_package(catkin_simple REQUIRED)
-## Find catkin macros and libraries
-## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
-## is used, also find other catkin packages
-find_package(OpenCV REQUIRED)
find_package(catkin REQUIRED COMPONENTS
message_generation
roscpp
## -28,11 +21,12 ## find_package(catkin REQUIRED COMPONENTS
tool_segmentation
)
+find_package(CUDAToolkit REQUIRED)
catkin_package(
INCLUDE_DIRS
include
- LIBRARIES
+ LIBRARIES
tool_tracking_particle
CATKIN_DEPENDS
message_runtime
## -47,13 +41,7 ## catkin_package(
tf
)
-include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
-include_directories(include ${catkin_INCLUDE_DIRS} tool_model_lib )
-
-#cuda_add_library(tool_tracking_particle src/ParticleFilter.cu src/Particle.cu)
-#add_executable(particle src/tracking_particle.cpp)
-#target_link_libraries(particle tool_tracking_particle ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} davinci_kinematics_cuda
-# davinci_kinematics_definitions_cuda)
-
-cuda_add_executable(test_particlefilter src/ParticleFilter.cu src/Particle.cu)
-target_link_libraries(test_particlefilter tool_tracking_particle ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${CUDA_LIBRARIES})
+add_executable(test_particlefilter src/ParticleFilter.cu src/Particle.cu)
+target_include_directories(test_particlefilter SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})
+target_include_directories(test_particlefilter PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
+target_link_libraries(test_particlefilter PRIVATE ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} CUDA::curand)
I also modernized the CMake code here, because the built-in CUDA language support has considerably advanced.
Miscellaneous changes
I bumped the minimum CMake version from 2.8.x to 3.0.2 in all other places to suppress warnings. I also added a version number 3 to all find_package(OpenCV ...) calls that didn't have it.
Boost no longer has a python3 package; it's just python now. I made the following change to src/vision_opencv/cv_bridge/CMakeLists.txt:
--- a/src/vision_opencv/cv_bridge/CMakeLists.txt
+++ b/src/vision_opencv/cv_bridge/CMakeLists.txt
## -1,18 +1,15 ##
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.0.2)
project(cv_bridge)
find_package(catkin REQUIRED COMPONENTS rosconsole sensor_msgs)
if(NOT ANDROID)
find_package(PythonLibs)
- if(PYTHONLIBS_VERSION_STRING VERSION_LESS 3)
- find_package(Boost REQUIRED python)
- else()
- find_package(Boost REQUIRED python3)
- endif()
+ find_package(Boost REQUIRED python)
else()
-find_package(Boost REQUIRED)
+ find_package(Boost REQUIRED)
endif()
+
find_package(OpenCV 3 REQUIRED
COMPONENTS
opencv_core
How can I get CMake to link pthread statically on Windows? I use MSYS2 MinGW 32 bit and cmake v3.7.
What I would like to achieve is a compiler invocation like
g++ -static-libgcc -static-libstdc++ -std=c++11 -o test test.cpp -Wl,-Bstatic -lpthread
Setting
target_link_libraries(test PUBLIC "-Wl,-Bstatic -lpthread")
results in -Wl,-Bdynamic -Wl,-Bstatic -lpthread being called. If I change CMAKE_EXE_LINKER_FLAGS, pthreads is included before my object files and thus symbols are not resolved.
find the Threads module:
find_package(Threads REQUIRED)
add_executable(myApp main.cpp)
target_link_libraries(myApp Threads::Threads)
Note from the documentation:
For systems with multiple thread libraries, caller can set CMAKE_THREAD_PREFER_PTHREAD
As the FindThreads.cmake mention in its source code:
# For systems with multiple thread libraries, caller can set
#
# ::
#
# CMAKE_THREAD_PREFER_PTHREAD
#
# If the use of the -pthread compiler and linker flag is preferred then the
# caller can set
#
# ::
#
# THREADS_PREFER_PTHREAD_FLAG
#
# Please note that the compiler flag can only be used with the imported
# target. Use of both the imported target as well as this switch is highly
# recommended for new code.
So in addition to what already said, you might need to set the additional flag THREADS_PREFER_PTHREAD_FLAG. In some systems (OSX, etc.) this flag is needed at compilation time because it defines some macros that would be missing if you would only link -lpthread.
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
add_library(test test.cpp)
set_property(TARGET test PROPERTY CXX_STANDARD 11)
set_target_properties(test PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(test PROPERTIES LINK_SEARCH_END_STATIC 1)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
find_package(Threads REQUIRED)
target_link_libraries(test Threads::Threads)
Does it help?
This scientific application I am using uses cmake to build its program. Attached is the CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
set(PROJECT_NAME myproject)
project(${PROJECT_NAME})
# Set verbose output while testing CMake
#set(CMAKE_VERBOSE_MAKEFILE 1)
# Set CMake behavior
cmake_policy(SET CMP0004 OLD)
# Get DOLFIN configuration data (DOLFINConfig.cmake must be in
# DOLFIN_CMAKE_CONFIG_PATH)
find_package(DOLFIN)
# Need to get VTK config because VTK uses advanced VTK features which
# mean it's not enough to just link to the DOLFIN target. See
# http://www.vtk.org/pipermail/vtk-developers/2013-October/014402.html
find_package(VTK HINTS ${VTK_DIR} $ENV{VTK_DIR} NO_MODULE QUIET)
# Default build type (can be overridden by user)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
"Choose the type of build, options are: Debug MinSizeRel Release RelWithDebInfo." FORCE)
endif()
# Compiler definitions
add_definitions(${DOLFIN_CXX_DEFINITIONS})
# Compiler flags
set(CMAKE_CXX_FLAGS "${DOLFIN_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
# Include directories
include_directories(${DOLFIN_INCLUDE_DIRS})
include_directories(SYSTEM ${DOLFIN_3RD_PARTY_INCLUDE_DIRS})
# Executable
add_executable(${PROJECT_NAME} main.cpp)
# Target libraries
target_link_libraries(${PROJECT_NAME} ${DOLFIN_LIBRARIES})
However, I need to include some additional compiler flags and libraries not included within DOLFIN. I need to incorporate this package called PAPI. On my system, the paths/environments are:
PAPI_LIBDIR=/project/cacds/apps/papi/5.4.0/lib
PAPI_INCLUDE=/project/cacds/apps/papi/5.4.0/include
PAPI_FLAG=-lpapi
Normally I would do something like this:
gcc -O3 -o -I myproject $(PAPI_LIBDIR) main.c -L $(PAPI_INCLUDE) $(PAPI_FLAG)
But again I need the additional DOLFIN libraries and third party packages. Pardon me if this is a silly or simple question, but how would I modify the above CMakeLists.txt? I am kind of new to cmake, so any help appreciated, thanks
The cleanest solution would be to create a FindPAPI.cmake. So, add to your project this file inside of a cmake/folder:
FindPAPI.cmake
# Try to find PAPI headers and libraries.
#
# Usage of this module as follows:
#
# find_package(PAPI)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# PAPI_PREFIX Set this variable to the root installation of
# libpapi if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# PAPI_FOUND System has PAPI libraries and headers
# PAPI_LIBRARIES The PAPI library
# PAPI_INCLUDE_DIRS The location of PAPI headers
find_path(PAPI_PREFIX
NAMES include/papi.h
)
find_library(PAPI_LIBRARIES
# Pick the static library first for easier run-time linking.
NAMES libpapi.a papi
HINTS ${PAPI_PREFIX}/lib ${HILTIDEPS}/lib
)
find_path(PAPI_INCLUDE_DIRS
NAMES papi.h
HINTS ${PAPI_PREFIX}/include ${HILTIDEPS}/include
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PAPI DEFAULT_MSG
PAPI_LIBRARIES
PAPI_INCLUDE_DIRS
)
mark_as_advanced(
PAPI_PREFIX_DIRS
PAPI_LIBRARIES
PAPI_INCLUDE_DIRS
)
Then, modify your CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
set(PROJECT_NAME myproject)
project(${PROJECT_NAME})
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(PAPI REQUIRED)
...
# Include directories
include_directories(${DOLFIN_INCLUDE_DIRS})
include_directories(SYSTEM ${DOLFIN_3RD_PARTY_INCLUDE_DIRS})
include_directories(${PAPI_INCLUDE_DIRS})
# Executable
add_executable(${PROJECT_NAME} main.cpp)
# Target libraries
target_link_libraries(${PROJECT_NAME} ${PAPI_LIBRARIES} ${DOLFIN_LIBRARIES})
I hope it resolves it! ;)
I want to not add boost.cxx if cmake find_package found no boost installed. Does find_package return something that I can wrap in condition to compile boost.cxx or not. Here is my current cmake file:
add_executable (complex complex.cxx lexer.cxx boost.cxx ../../src/lili.cxx ../../src/lilu.cxx)
# Make sure the compiler can find all include files
include_directories (../../src)
include_directories (.)
# Make sure the linker can find all needed libraries
# rt: clock_gettime()
target_link_libraries(complex rt)
# Install example application
install (TARGETS complex
RUNTIME DESTINATION bin)
IF(UNIX)
find_package(Boost COMPONENTS system filesystem REQUIRED)
## Compiler flags
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-O2")
set(CMAKE_EXE_LINKER_FLAGS "-lsqlite3 -lrt -lpthread")
endif()
target_link_libraries(complex
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
#${PROTOBUF_LIBRARY}
)
ENDIF(UNIX)
The FindXXX scripts are supposed to set a variable <Packagename>_FOUND to TRUEif the package was found. So in your case, it will set Boost_FOUND if boost was found.
When compiling your Boost.cxx, I assume that you will need Boost headers as well, so you should adjust your include directories as well.*
look for Boost before creating your executable. Furhtermore, you need to set your include directories before adding the executable.
IF(UNIX)
find_package(Boost COMPONENTS system filesystem REQUIRED)
# IF( Boost_FOUND ) # checking this variable isnt even necessary, since you added
# REQUIRED to your call to FIND_PACKAGE
SET( BOOST_SRC_FILES boost.cxx )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} ) # you could move this down as well
# as ${Boost_INCLUDE_DIRS} will be
# empty if Boost was not found
# ENDIF()
ENDIF()
add_executable (complex complex.cxx lexer.cxx ${BOOST_SRC_FILES} ../../src/lili.cxx ../../src/lilu.cxx)
# Make sure the compiler can find all include files
include_directories (../../src)
include_directories (.)
# INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} ) # alternative location to
# add include dirs, see above
# Make sure the linker can find all needed libraries
# rt: clock_gettime()
target_link_libraries(complex rt)
# Install example application
install (TARGETS complex
RUNTIME DESTINATION bin)
IF(UNIX)
## Compiler flags
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-O2")
set(CMAKE_EXE_LINKER_FLAGS "-lsqlite3 -lrt -lpthread")
endif()
target_link_libraries(complex
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
#${PROTOBUF_LIBRARY}
)
ENDIF(UNIX)
Afternote: Since you use the REQUIRED flag when looking for Boost (since you only need it on Unix platform) it is even sufficient to use the optional-source-files-in-a-variable trick.
(*) Thanks to your question, I just found out that it doesn't matter whether include_directories(...) is called before or after creating the target with ADD_EXECUTABLE or ADD_LIBRARY since the directories are added to all targets in the same project.
Yes, if the find_package(Boost COMPONENTS system filesystem REQUIRED) succeeds, Boost_FOUND will be true.
Also, there will be component-specific versions, so Boost_date_time_FOUND, Boost_filesystem_FOUND, etc.
For further info, run
cmake --help-module FindBoost
Yes, it sets variable Boost_FOUND. Example from FindBoost.cmake:
== Using actual libraries from within Boost: ==
#
# set(Boost_USE_STATIC_LIBS ON)
# set(Boost_USE_MULTITHREADED ON)
# set(Boost_USE_STATIC_RUNTIME OFF)
# find_package( Boost 1.36.0 COMPONENTS date_time filesystem system ... )
#
# if(Boost_FOUND)
# include_directories(${Boost_INCLUDE_DIRS})
# add_executable(foo foo.cc)
# target_link_libraries(foo ${Boost_LIBRARIES})
# endif()