Cmake cannot find library - c++

I have a library called Kinova.API.CommLayerUbuntu.so which I want to link against with cmake. So, in my CMakeLists.txt file, I have the line:
target_link_libraries(demo ~/Libraries/Kinova.API.CommLayerUbuntu.so)
However, during compilation, I receive the error:
cannot find -lKinova.API.CommLayerUbuntu
This baffles me because I am telling cmake to look for Kinova.API.CommLayerUbuntu.so, not for -lKinova.API.CommLayerUbuntu. Please could somebody explain what is going on?
In verbose mode, the cmake output gives the following:
Linking CXX executable demo
/usr/bin/cmake -E cmake_link_script CMakeFiles/demo.dir/link.txt --verbose=1
/usr/bin/c++ CMakeFiles/demo.dir/demo.cpp.o -o demo -L/home/karnivaurus/Libraries -rdynamic -lKinova.API.CommLayerUbuntu -Wl,-rpath,/home/karnivaurus/Libraries
/usr/bin/ld: cannot find -lKinova.API.CommLayerUbuntu

The -l is just the flag used to tell the compiler to link a library. Your library name is nonstandard. The compiler will remove the -l and prepend lib to the string you use, and look for a file called libKinova.API.CommLayerUbuntu.so.
This looks like an issue with the distribution of this API. You can try working around it by creating a symbolic link from libKinova.API.CommLayerUbuntu.so to Kinova.API.CommLayerUbuntu.so.

Related

CMake check_symbol_exists doesn't work because of missing -pthread

I'm trying to build https://github.com/iovisor/bpftrace.git on Ubuntu 18.04. I built and installed its dependency bcc by hand (the bpftrace repo build docs suggest that because the packaged version on ubuntu lacks required header files).
I found that cmake would complain for me as follows:
-- Looking for bcc_prog_load - not found
After some CMakeLists.txt edits to ensure suitable -I flags are passed, and looking in CMakeFiles/CMakeError.log, I see that the build fails like this:
/usr/bin/cc -I/home/me/dev/bcc/src/cc -I/home/me/dev/bcc/src/cc/libbpf/src -o CMakeFiles/cmTC_653d8.dir/CheckSymbolExists.c.o -c /home/me/dev/bpftrace/build/CMakeFiles/CMakeTmp/CheckSymbolExists.c
Linking C executable cmTC_653d8
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_653d8.dir/link.txt --verbose=1
/usr/bin/cc -rdynamic CMakeFiles/cmTC_653d8.dir/CheckSymbolExists.c.o -o cmTC_653d8 -lbcc
CMakeFiles/cmTC_653d8.dir/CheckSymbolExists.c.o: In function `main':
CheckSymbolExists.c:(.text+0x1b): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
If I run with --debug-trycompile and run the failing commands by hand, I see that passing the -pthread command line option to gcc fixes that error. From this answer I glean that something like the following is supposed to fix that:
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_app Threads::Threads)
However, the thing that is failing here is not some target I have added, but merely a check for the presence of a symbol:
check_symbol_exists(bcc_prog_load "libbpf.h" HAVE_BCC_PROG_LOAD)
I therefore don't know how to specify a target for target_link_libraries. I tried replacing the target_link_libraries with link_libraries (dropping the first argument my_app), but that does not cause CMake to pass the -pthread argument to gcc when testing for the presence of the symbol.
What can I do to make the check_symbol_exists work?

g++ not find .so files

I am trying to generate a c++ library using the g++ compiler. My library has another C library as dependency and I have compiled it in order to obtain the .so files.
I have the following structure:
src:
include/linux:
libcustom.a
libcustom.la
libcustom.so
libcustom.so.0
libcustom.so.0.0.0
Now, when I have all the .o files of my cpp classes, and I want to link the library, I execute the following command:
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o mylibrary.so File1.o File2.o File3.o -L./include/linux -lc++ -lutil -lm -lcustom -Wl,-rpath='$ORIGIN/include/linux' -L/usr/lib/R/lib -lR
But it throws me the error:
libcustom.so.0: cannot open shared object file: No such file or directory
I am executing the command from the src directory.
I know it could be fixed editing the LD_LIBRARY_PATH, but the idea it is someone can use my library without the need of configuring anything, so I am trying to do that with the c++'s -rpath flag.
Any idea how can I fix it, or the reason for the error?
The error message you got seems to come from the run-time loader ld.so instead of the linker ld (I know the names are confusing). You have to distinguish between finding so's at link-time and at run-time. The -L flag you give at link-time has nothing to do with localizing the library at run-time.
Your rpath=./include/linux value is not correct, because dot is not recognized by the ld as relative path. Relative searching path should be given like
-Wl,-rpath='$ORIGIN/include/linux'
where the $ORIGIN represents the folder where your executable (not mylibrary.so) locates. Make sure to use single quote and not double quote because the string $ORIGIN should be passed to the linker literally and hard coded into the executable file.
More details goes
how to link to shared lib from shared lib with relative path
ld: Using -rpath,$ORIGIN inside a shared library (recursive)

gcc does not link properly against gsoap

I'm migrating my C++ application build system to cmake. One dependency is gsoap++, which generates a SOAP service and client. To link against it, I specify
set(CMAKE_CXX_LINK_FLAGS "-lgsoap++ ... [other flags]")
in the root CMakeLists.txt. The generated sources are created with
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src/generated/c++/ws)
set(GEN_WS_SOURCES ws/Bar.h ws/Bar_USCOREBinding.nsmap ws/soapBar_USCOREBindingProxy.h ws/soapBar_USCOREBindingProxy.cpp ws/soapBar_USCOREBindingService.h ws/soapBar_USCOREBindingService.cpp ws/soapH.h ws/soapC.cpp ws/soapStub.h)
add_custom_command(OUTPUT ${GEN_WS_SOURCES}
COMMAND wsdl2h -o ${CMAKE_BINARY_DIR}/src/generated/c++/ws/Bar.h -t wsdl/typemap.dat wsdl/bar.wsdl
COMMAND soapcpp2 -Lwxi -I/usr/include/gsoap ${CMAKE_BINARY_DIR}/src/generated/c++/ws/Bar.h -d ${CMAKE_BINARY_DIR}/src/generated/c++/ws
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
add_library(GEN_WS ${GEN_WS_SOURCES})
Everything seems to work properly, the sources get created. But when linking the application, I get lots of errors like
undefined reference to `soap_end'
undefined reference to `soap_sender_fault'
more undefined references to `soap_sender_fault' follow
If I compile with make VERBOSE=1, I see that -lgsoap++ is passed to /usr/bin/c++ when linking. Other libraries I link against don't throw any errors, but for some reason, the linker does not seem to find gsoap's functions. The library is present and there is no error that the linker can't find it.
The old, custom build script worked as expected; it also just passed -lgsoap++ to the linker. The only real difference I see is that my cmake build groups the sources into static libraries before attempting to link everything together. But I don't see how this can lead to all the symbols from the library not being found.
What's the problem here? Why can't the linker find gsoap's symbols?
Host OS is debian.
Edit: This is the complete linker command executed by cmake:
/usr/bin/c++ -w -Wall -pedantic -fdata-sections -ffunction-sections -std=c++0x
-lgsoap++ -lsoci_core -lsoci_sqlite3 -lmicrohttpd -lfetcp -lfeisc -lFedmIscCore
-lboost_system -lboost_thread -lboost_program_options -lboost_date_time
-lboost_unit_test_framework CMakeFiles/bar.dir/main.cpp.o
CMakeFiles/bar.dir/mainapp.cpp.o -o bar -rdynamic ../../libs/c++/libLIB_JSONXX.a
../../libs/c++/libLIB_CONFIG.a ../../libs/c++/libLIB_DB.a ../../libs/c++/libLIB_OBID.a
../../libs/c++/libLIB_HELPER.a ../../generated/c++/libGEN_WS.a
../../generated/c++/libGEN_DB.a ../../generated/c++/libGEN_CONFIG.a
libMAIN_CONTROLLERS.a libMAIN_HARDWARE.a libMAIN_HELPER.a libMAIN_MODEL.a
libMAIN_NETWORK.a libMAIN_SYSTEM.a ../../generated/c++/libGEN_DB.a
../../libs/c++/libLIB_DB.a ../../generated/c++/libGEN_CONFIG.a
../../libs/c++/libLIB_JSONXX.a ../../libs/c++/libLIB_CONFIG.a
../../libs/c++/libLIB_HELPER.a ../../libs/c++/libLIB_OBID.a
../../generated/c++/libGEN_WS.a
I'm not sure if it will directly solve your problem, but this:
set(CMAKE_CXX_LINK_FLAGS "-lgsoap++ ... [other flags]")
Should be:
set(CMAKE_CXX_LINK_FLAGS "[other flags]")
target_link_library(GEN_WS gsoap++) # after add_library of course

Cmake doesn't honour -D CMAKE_CXX_COMPILER=g++

I'm trying to force cmake to build my cpp code with g++, as by default it uses clang instead. So I use: cmake -D CMAKE_CXX_COMPILER=g++ ../src/CMakeLists.txt after which cmake checks for gcc and g++ (with success), but nonetheless make VERBOSE=1 yields
/usr/bin/c++ -o CMakeFiles/trial_cpp.dir/trial.cpp.o -c "/Users/Kuba/Code/Sketchpad/Trial project/src/trial.cpp"
Linking CXX executable trial_cpp
/opt/etlocal/bin/cmake -E cmake_link_script CMakeFiles/trial_cpp.dir/link.txt --verbose=1
/usr/bin/c++ -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/trial_cpp.dir/trial.cpp.o -o trial_cpp
As it calls /usr/bin/c++ not /usr/bin/g++ I concur it still uses clang. Any idea what's the problem? I know I have g++ and it's in /usr/bin/.
I'm running Mac OS X 10.8.2
CMAKE_CXX_COMPILER can only be set the first time cmake is run in a given build directory. On subsequent runs it is ignored. In order to change CMAKE_CXX_COMPILER you first need to delete the contents of the build directory and then run cmake again with that option.
Source: http://www.cmake.org/Wiki/CMake_Useful_Variables
I believe the reasoning for only using that variable on the first run is because changing it later would potentially invalidate everything already built including the configuration checks so cmake would have to start from scratch anyway.
I do it like this instead:
CXX=/usr/bin/g++ cmake ../src/CMakeLists.txt

Clang linker does not look into LD_LIBRARY_PATH

I am trying to build and link a C++, cmake-based project with clang (3.0). This project links to several libraries that are installed in a custom directory /my/dir/. This directory is included in the LD_LIBRARY_PATH and LIBRARY_PATH environment variables. Project builds and links fine with g++.
The link command generated and executed by cmake looks like the following:
/usr/bin/clang++ -O3 stuff.cpp.o -o stuff -rdynamic -lmylib
ld then complains with the following message:
/usr/bin/ld: cannot find -lmylib
The link command above runs fine whenever I manually add -L/my/dir/. Is there a way to link without specifying the -L flag?
The $LD_LIBRARY_PATH environment variable (and its various alternatives on other UNIX-based platforms) is used at runtime, not link time, to find libraries.
Using -L is the correct approach and cannot be avoided.
Note: A better approach under Linux (you don't specify your platform so I'm guessing) is to correctly configure a file in /etc/ld.so.conf.d/ and avoid using $LD_LIBRARY_PATH altogether.