How to solve the 'undefined reference to libusb' error in ros? - c++

I am trying to transfer a camera(non-uvc) stream program to ros platform.
I've already got the camera driver running
and Makefile is like this:
g++ main.cpp -o test_gui -g -I /usr/local/include -L /usr/local/lib -D_LIN -D_DEBUG -L../lib/x64 -I../include -lASICamera -lpthread -lusb -DGLIBC_20 -m64 -lrt -I/opt
Now I want to do this in a ros node, so I write a node in which the CMakelists is like this:
include_directories(
${catkin_INCLUDE_DIRS}
)
include_directories(/usr/local/include)
include_directories(/root/catkin_ws/src/asi_converter_real/include/asi_converter_real)
link_directories(/usr/local/lib)
link_libraries(pthread)
link_libraries(usb)
link_libraries(libASICamera.a)
link_libraries(libASICamera.so)
add_executable(asi_converter_real src/asi_converter_real.cpp)
target_link_libraries(asi_converter_real ${catkin_LIBRARIES})
And the Makefile line generated into /catkin_ws/build/***/ is like this:
/usr/bin/c++ CMakeFiles/asi_converter_real.dir/src/asi_converter_real.cpp.o -o /root/catkin_ws/devel/lib/asi_converter_real/asi_converter_real -rdynamic -L/usr/local/lib -lpthread -lusb -Wl,-Bstatic -lASICamera -Wl,-Bdynamic -lASICamera
But it seems that the system cannot find the dynamic libraries of libusb, coz' it reports
undefined reference to `libusb_set_configuration'
undefined reference to `libusb_claim_interface'
/usr/local/lib/libASICamera.a(ASI174MM.o): In function `WorkingFunc(void*)':
undefined reference to `libusb_bulk_transfer'
undefined reference to `libusb_bulk_transfer'
[1]Is there anyone who knows how to solve this problem ?
[2]How to find the .a and .so of libusb in my computer ? (I am sure I have them, coz' I can pkg-config --cflags/--libs them)
[3]How could I explicitly link a dynamic library in ros CMakelists ? or just link_libraries(usb) is enough for both static and dynamic libriries ?

find_package requires that CMake have a corresponding Find<package>.cmake
Cmake have a pkg-config module.
You can use it to write your own FindLibUSB, as explained on the CMake wiki.
Or you can use it directly in your CMakeLists.txt :
find_package(PkgConfig REQUIRED)
pkg_search_module(LIBUSB1 REQUIRED libusb-1.0)
include_directories(SYSTEM ${LIBUSB1_INCLUDE_DIRS})
You can see in the module documentation all the variables that are set : LIBUSB1_LIBRARIES for the libraries, etc ...

Finding libraries in cmake is typically done using find_package.
In your case it might look like this (taken from this question):
find_package(libusb-1.0 REQUIRED)
include_directories (${LIBUSB_1_INCLUDE_DIRS})
...
target_link_libraries(asi_converter_real ${catkin_LIBRARIES} ${LIBUSB_1_LIBRARIES})
You may have to adjust the version number of course (maybe it can simply be removed).

Related

Converting a Makefile into CMakeLists.txt equivalent

I am working on a project were I maintain a CMakeLists.txt file to keep track of the dependencies when I need to compile.
I recently, started using a new library that I need to integrate in my project. The library comes with some examples on how to compile but this is purely a Makefile. I would like to integrate the logic of the Makefile into my project's CMakeLists.txt file.
The Makefile of this library is as follows:
COMMON=-O2 -I/home/john/.mujoco/mjpro200/include -L/home/john/.mujoco/mjpro200/bin -std=c++11 -mavx -pthread -Wl,-rpath,'$$ORIGIN'
all:
g++ $(COMMON) basic.cpp -lmujoco200 -lGL -lglew /home/john/.mujoco/mjpro200/bin/libglfw.so.3 -o basic
gcc -c -O2 -mavx -I/home/john/.mujoco/mjpro200/include /home/john/.mujoco/mjpro200/include/uitools.c
rm *.o
I would like to convert this Makefile into CMakeLists.txt exactly if possible. I see that they provide some flags for threading (pthread) and I want to keep these flags and settings in my CMakeLists.txt in case they are needed for performance.
Here is my CMakeLists.txt:
cmake_minimum_required (VERSION 2.6.0)
project(myproject)
add_compile_options(-std=c++11) # CMake 2.8.12 or newer
if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
add_definitions("-fno-strict-aliasing -Wall")
endif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
# optional in case boost is used
find_package(Boost 1.58 EXACT)
find_package(Eigen REQUIRED)
set(mujocoCommon "-O2 -I/home/john/.mujoco/mjpro200/include -L/home/john/.mujoco/mjpro200/bin -std=c++11 -mavx -pthread -Wl,-rpath,'$$ORIGIN'")
set(Mujoco_INCLUDE_DIRS "/home/john/.mujoco/mjpro200/include")
include_directories(${Boost_INCLUDE_DIRS} ${Eigen_INCLUDE_DIRS} ${Mujoco_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_executable(myproject mycode.cpp)
install(TARGETS myproject DESTINATION .)
So I tried to define a variable mujocoCommon similar to the COMMON in the Makefile as well as the Mujoco_INCLUDE_DIRS that I then use in the CMake's include_directories.
Note that in the myproject.cpp I have MuJoCo code and other dependencies that I need to correctly link against. In the Makefile things looks a bit more simpler because in there the code has only MuJoco dependencies.
I need some heads-up on how to add in my CMakeLists.txt the following:
-mavx -pthread -Wl,-rpath,'$$ORIGIN' part of Makefile's COMMON variable.
-lmujoco200 -lGL -lglew /home/john/.mujoco/mjpro200/bin/libglfw.so.3
-c -O2 -mavx -I/home/john/.mujoco/mjpro200/include /home/john/.mujoco/mjpro200/include/uitools.c
Currently with the minimal knowledge on CMake and what I have in my CMakeLists.txt when I compile using "make" I get many errors of the kind:
myproject.cpp:(.text+0xfa9): undefined reference to `glfwSetMouseButtonCallback'
Basically I would like to link (?) my code with MuJoco library as is done in their Makefile.
Thanks.
Edit
In regards with the possible duplicate flag, I added the following flag:
set(Mujoco_LIBRARIES "/home/john/.mujoco/mjpro200/bin")
target_link_libraries(myproject ${Mujoco_LIBRARIES} -lboost_system)
But it didn't solved the problem.
Edit 2:
I have also added this one:
set(CMAKE_CXX_FLAGS "-lmujoco200 -lGL -lglew /home/john/.mujoco/mjpro200/bin/libglfw.so.3")
The errors I am getting:
/usr/bin/x86_64-linux-gnu-ld: cannot find -lmujoco200
/usr/bin/x86_64-linux-gnu-ld: cannot find -lglew
You also need to add the opengl libraries to the link libraries, target_link_libraries. Don't add them with -l.

Is it possible to force CMake to reorder arguments when calling the linker? [duplicate]

This question already has an answer here:
Flag '-l' in CMAKE_CXX_FLAGS doesn't work
(1 answer)
Closed 4 years ago.
I have a strange behavior where CMake is not able to link any executable if dynamic linking is required. g++ is not able to find any of the symbols defined in the libraries.
I found out it might have to do with the order of the arguments CMake passes to g++ when linking.
Here is the verbose output of the build process (which fails linking):
[ 50%] Building CXX object CMakeFiles/chargen.dir/test.cpp.obj
g++ -std=c++11 -o CMakeFiles/test.dir/test.cpp.obj -c /f/test/test.cpp
[100%] Linking CXX executable mytest
/usr/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
g++ -std=c++11 -lSDL2 CMakeFiles/test.dir/test.cpp.obj -o mytest
Indeed if I try to link using that command I get undefined references, however if I compile with the library flags at the end:
g++ -std=c++11 CMakeFiles/test.dir/test.cpp.obj -o mytest -lSDL2
it runs just fine. How can I force CMake to use that order of arguments instead?
The contents of the CMakeLists.txt:
cmake_minimum_required(VERSION 3.6)
project(mytest)
set(COMPILER_PATH "/usr/bin/")
set(CMAKE_MAKE_PROGRAM "make")
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lSDL2")
set(SOURCE_FILES test.cpp)
add_executable(mytest ${SOURCE_FILES})
You have probably added -lSDL2 into CMAKE_CXX_FLAGS. In that case it will appear withn compile/link flags, in front of source file name in actual link command, as you showed. Don't do that.
You should use _target_link_libraries_ cmake command in order to define libraries to link against. In brief, the skeleton of your CMakeLists.txt should look like this:
project (project_name)
add_executable (mytest test.cpp)
target_link_libraries( mytest SDL2)
In this case, cmake will put libraries on correct place. Note that you may use target_link_libraries after adding target mytest
[EDIT]
After seeing your CMakeLists it is obvious that your problem is in wrong CMAKE_EXE_LINKER_FLAGS. Simply delete the line where you are setting it, and add target_link_libraries after add_executable.
Regarding your question about handling circular dependencies among static libs, you handle it the sam way as you would if you didn't use cmake: mention it twice:
target_link_libraries(
mytest
circular_dep1
circular_dep2
circular_dep1
circular_dep2
)
regarding your question about specific linker flags, just place them into target_link_libraries command, it accepts linker flags as well. You can find documentation on following link:
https://cmake.org/cmake/help/latest/command/target_link_libraries.html

what's the differences between pthread and -pthread options in cmake?

Environment
ubuntu 16.04, gcc 5.4.0, cmake 3.5.1
Question
target_link_libraries(promise pthread)
target_link_libraries(promise -pthread)
target_link_libraries(promise -lpthread)
What's the differences, which is better ?
Problem
promise.cpp
std::promise<int> pr;
auto fut = pr.get_future();
pr.set_value(10); // throw std::exception and terminate
CMakeLists.txt
add_executable(promise promise.cpp)
target_link_libraries(promise pthread)
Solution
Modify CMakeLists.txt slightly.
add_executable(promise promise.cpp)
target_link_libraries(promise -pthread)
I found the answer from here. But I don't know why ?
But, the best solution is portable.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
target_link_libraries(promise Threads::Threads)
All calls are generally wrong. As answered by #vre, you should use find_package(Threads) instead.
But all these calls are effectively the same!
Calls
target_link_libraries(promise pthread)
and
target_link_libraries(promise -lpthread)
are transformed into the same linker's command line: for parameters not starting with -, CMake will add -l automatically (from target_link_libraries documentation):
A plain library name: The generated link line will ask the linker to search for the library (e.g. foo becomes -lfoo or foo.lib).
While calls
target_link_libraries(promise -lpthread)
and
target_link_libraries(promise -pthread)
are translated into different flags, for linking process these flags means the same.
Option -pthread, passed to gcc, would add additional compile definitions. But parameters for target_link_libraries are not used for compilation.
Why using find_package(Threads) is correct
If one uses
set(THREADS_PREFER_PTHREAD_FLAG ON) # Without this flag CMake may resort to just '-lpthread'
find_package(Threads)
a library target Threads::Threads is created, with additional compile and link options -pthread attached to it as an interface.
When use
target_link_libraries(promise Threads::Threads)
CMake automatically propagates interface compile and link options, thus promise target is both compiled and linked with -pthread option.
First, we can use cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON to see the underlying commands of make.
target_link_libraries(promise pthread) and target_link_libraries(promise -lpthread) will result the same link option: -lpthread, like:
/usr/bin/c++ -std=c++11 -rdynamic CMakeFiles/promise.dir/promise.cpp.o -o promise -lpthread
However, target_link_libraries(promise -pthread) will give you -pthread option:
/usr/bin/c++ -std=c++11 -rdynamic CMakeFiles/promise.dir/promise.cpp.o -o promise -pthread
The difference between -pthread and -lpthread is well explained here. In general, you should use -pthread and target_link_libraries(promise -pthread).
btw, clang built binary seems ok with both options.
I would suggest using the modern CMake way by means of imported targets:
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
target_link_libraries(promise Threads::Threads)
This does not only add the library dependency, it also sets the compile option and works on almost all platforms. See the answers to the following post for further details:
Difference between -pthread and -pthreads for C/C++ on Ubuntu 14.04
And have a look into the fine documentation of FindThreads.cmake module:
https://cmake.org/cmake/help/v3.11/module/FindThreads.html

How to link compiled cmph library in my project using CMake

In order to use cmph, a perfect minimal hashing library, in my project organised using CMake, I installed cmph library in a ubuntu machine and tested it using a single c file called main.c.
If I try to compile this file using gcc 5.3.0 using the following command:
gcc main.c
I will get the following output
/tmp/ccSOH5ob.o: In function `main':
testperfect.c:(.text+0x63): undefined reference to `cmph_io_vector_adapter'
testperfect.c:(.text+0x73): undefined reference to `cmph_config_new'
testperfect.c:(.text+0x88): undefined reference to `cmph_config_set_algo'
testperfect.c:(.text+0x9b): undefined reference to `cmph_config_set_mphf_fd'
testperfect.c:(.text+0xa7): undefined reference to `cmph_new'
testperfect.c:(.text+0xb7): undefined reference to `cmph_config_destroy'
testperfect.c:(.text+0xca): undefined reference to `cmph_dump'
testperfect.c:(.text+0xd6): undefined reference to `cmph_destroy'
testperfect.c:(.text+0xe2): undefined reference to `cmph_load'
testperfect.c:(.text+0x118): undefined reference to `cmph_search'
testperfect.c:(.text+0x153): undefined reference to `cmph_destroy'
testperfect.c:(.text+0x15f): undefined reference to `cmph_io_vector_adapter_destroy'
But if I run this command:
gcc main.c $(pkg-config --libs cmph) -o main
It will be compiled and run normally.
Now I need to add a similar piece of code in my project and the CMakeList.txt is written like this:
set(PROJECT_EXECUTABLE ${PROJECT_NAME})
# Compiling flags.
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
endif()
# Inject project config.
configure_file(
${PROJECT_INCLUDE_DIR}/phsim/config.hpp.in
${PROJECT_INCLUDE_DIR}/phsim/config.hpp
)
include(FindPkgConfig)
find_package(PkgConfig REQUIRED)
pkg_search_module(CMPH REQUIRED cmph)
target_link_libraries(Phsim ${CMPH_LIBRARIES})
target_include_directories(Phsim PUBLIC ${CMPH_INCLUDE_DIRS})
target_compile_options(Phsim PUBLIC ${CMPH_CFLAGS_OTHER})
# Compile executable.
file(GLOB SOURCES ${PROJECT_SRC_DIR}/*.cpp)
add_executable(${PROJECT_EXECUTABLE} ${SOURCES})
set_target_properties(${PROJECT_EXECUTABLE} PROPERTIES
VERSION ${PHSIM_VERSION_LITER}
)
And then I try to run cmake . and make, but only get the error message:
CMake Error at src/CMakeLists.txt:20 (target_link_libraries):
Cannot specify link libraries for target "Phsim" which is not built by this
project.
But I won't get target executable file unless I compile the project. If I try to compile my project without those commands related to library linking, the compiler will give similar link errors provided in the beginning of my question.
I have checked the following questions:
Undefined reference to cmph functions even after installing cpmh library
And I tried instructions provided by these sites:
https://cmake.org/Wiki/CMake:How_To_Find_Libraries
https://cmake.org/cmake/help/v3.6/module/FindPkgConfig.html
Many thanks in advance.
Finally Solved.
cmake_minimum_required(VERSION 3.0.2)
project(TestGamma)
set(GAMMATEST_VERSION_MAJOR 1)
set(GAMMATEST_VERSION_MINOR 0)
set(CMPH_INCLUDE_DIR /usr/local/lib)
include(FindPkgConfig)
configure_file(
"${PROJECT_SOURCE_DIR}/TestGammaConfig.h.in"
"${PROJECT_BINARY_DIR}/TestGammaConfig.h"
)
include_directories(${PROJECT_BINARY_DIR})
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(testgamma ${SOURCE_FILES})
pkg_check_modules(CMPH REQUIRED cmph)
include_directories(${CMPH_INDLUDE_DIR})
link_directories(${CMPH_INCLUDE_DIR})
target_link_libraries(testgamma cmph ${CMPH_INCLUDE_DIR})
Make sure to include pkgconfig at first and add link operations after calling "add_executable"
#usr1234567 Thank you for your attention.

undefined reference to `shm_open' using CMake

I am using CMake under Ubuntu 14.04 to configure my project.
I need to use a 3rd party library (say stuff.so).
In the CMakeLists.txt, I use TARGET_LINK_LIBRARIES to link the stuff library.
However, I got an error:
DIR_TO_LIB/stuff.so:-1: error: undefined reference to `shm_open'
I tried to put these flag in the CMakeLists.txt but it didn't work:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrt")
A post (link) saying that -lrt should be put as the last argument of g++. In my case where CMake is used, how shall I do this?
UPDATE:
I added
SET (CMAKE_VERBOSE_MAKEFILE 1)
and I found that -lrt is not the last (even though I put it at the end of the target link). Please see this link for compile output.
As you can see from the compile output, there are some linking flags for the opencv.
I don't understand how could this happen as I link the OpenCV library first in the TARGET_LINK_LIBRARIES. How does CMake handle these linking order?
Please also see my CMakeLists.txt.
Thank you.
You need to add rt in TARGET_LINK_LIBRARIES as a last one, for example:
TARGET_LINK_LIBRARIES(my_app ${Boost_LIBRARIES} rt)
You can verify position of rt by enabling verbose build output:
SET (CMAKE_VERBOSE_MAKEFILE 1)
First, the answer is: Append -lrt to the end of your macro target_link_libraries for your target my_app, i.e.,
target_link_libraries(my_app ${Boost_LIBRARIES} -lrt)
That achieves the same effect in solving the missing library to be linked against by using e.g. gcc compiler:
gcc my_app.c -o my_app -lrt
The reason behind, as you may have already figured out, is the missing required ("realtime") library. For that, you can check by typing in the command
man shm_open
and then finding the key snippet explaining the reason of adding -lrt, i.e.,
"These functions are provided in glibc 2.2 and later. Programs using these functions must specify the -lrt flag to cc in order to link against the required ("realtime") library."