cmake cannot find library when linking library to another application - c++

I am trying to make generate a shared library of an existing application, so that i can link it to gtest application.
My main applications cmake file looks like this:
project(audiodLib CXX C)
cmake_minimum_required(VERSION 2.8.7)
## Lets store all the source code in ${SOURCES}
file(GLOB SOURCES src/*.cpp src/controls/*.cpp src/controls/pulse/*.cpp src/modules/*.cpp src/product/*.cpp src/umi/*.cpp src/umi/modules/*.cpp src/umi/soundSettings/*.cpp src/utils/*.cpp utils/*.cpp pmtrace/*.c)
##Lets generate the library
##Please note, here instead of ${SOURCES} if i try to directly add source code, I always get
##an error saying that cmake could not find any *.cpp files
add_library(audiodLib SHARED ${SOURCES})
##Lets link it with libraries
target_link_libraries(audiodLib ${GLIB2_LDFLAGS}
${LUNASERVICE_LDFLAGS}
${PBNJSON_C_LDFLAGS}
${LUNAPREFS_LDFLAGS}
${POWERD_LDFLAGS}
${PMLOGLIB_LDFLAGS}
${NYXLIB_LDFLAGS}
${LIBPBNJSON_LDFLAGS}
${PULSE_LDFLAGS}
${LTTNG_UST_LDFLAGS}
${URCU_BP_LDFLAGS}
${PULSE_SIMPLE_LDFLAGS}
${WEBOSI18N_LDFLAGS}
pthread
rt
dl
-lsnapshot-boot
)
##Lets make this library availabel for other modules
install(TARGETS audiodLib LIBRARY DESTINATION ${WEBOS_INSTALL_LIBDIR})
After compilation, libaudiodLib.so is generated in /usr/lib directory.
And now if I try to access the audiodLib in my gtest code like this:
##${WEBOS_INSTALL_LIBDIR} = /usr/lib/
include_directories(${WEBOS_INSTALL_LIBDIR})
target_link_libraries(${GTEST_EXECUTABLE}
${WEBOS_GTEST_LIBRARIES}
${GLIB2_LDFLAGS}
${LUNASERVICE_LDFLAGS}
${PBNJSON_C_LDFLAGS}
${LUNAPREFS_LDFLAGS}
${POWERD_LDFLAGS}
${PMLOGLIB_LDFLAGS}
${NYXLIB_LDFLAGS}
${LIBPBNJSON_LDFLAGS}
${PULSE_LDFLAGS}
${LTTNG_UST_LDFLAGS}
${URCU_BP_LDFLAGS}
${PULSE_SIMPLE_LDFLAGS}
${WEBOSI18N_LDFLAGS}
pthread
rt
dl
-lsnapshot-boot
-laudiodLib
)
I get the following error:
cannot find -laudiodLib
The folder structure is as follows:
audiod/
CMakeList
|src
|tests
CMakelist
If someone can point out what I am doing wrong, it would be of great help. I am kind of stuck and clueless after spending 2-3 days on this.

Thank you so very much for offering me suggestions, and pointers, I was finally able to sove the problem.
Regarding library not found issue, I resolved it by rearranging the TARGET_LINK_LIBRARIES as follows:
target_link_libraries(audiod
audiodLib
${GLIB2_LDFLAGS}
${LUNASERVICE_LDFLAGS}
${PBNJSON_C_LDFLAGS}
${LUNAPREFS_LDFLAGS}
${POWERD_LDFLAGS}
${PMLOGLIB_LDFLAGS}
${NYXLIB_LDFLAGS}
${LIBPBNJSON_LDFLAGS}
${PULSE_LDFLAGS}
${LTTNG_UST_LDFLAGS}
${URCU_BP_LDFLAGS}
${PULSE_SIMPLE_LDFLAGS}
${WEBOSI18N_LDFLAGS}
pthread
rt
dl
-lsnapshot-boot
)
And how i resolved the BAD RPATH Error during do_package_qa, I have already answerd it here:
bitbake do_package_qa issue contains bad RPATH

Related

Using new tensorflow op in a c++ library that already uses tensorflow as third party

That's my first time asking a question in stackoverflow. I will try my best to formulate my question properly.
I want to use a custom tensorflow op in in a c++ library, which already uses tensorflow as third party. But I just don't know how to use my custom operation in c++ code at all. I'm trying to learn that with the easy ZeroOut example from Tensroflow c++ tutorial. I registered the ZeroOut op for cpu as in https://github.com/MatteoRagni/tf.ZeroOut.gpu: compiling with make worked and I got a .so file in the usr-ops folder, where also the cc file was. Then I tried to add the ZeroOut.so file to my lib as shared library, but it didn't compile. However, before I added my custom op, registered with bazel as described in tensorflow new op tutorial, in the same way and my library compiled. Maybe because the .so file was created in ../bazel-bin/tensorflow/core/user_ops/ . But in this case I'm not able to use the operation as I should. And including ZeroOut.cpp or the .cpp files of my op in my c++ files didn't make any difference until now.
Here is my CMakeList.txt, which also creates the whole library I'm working with:
cmake_minimum_required(VERSION 2.8)
project(Project1)
set(CMAKE_BUILD_TYPE "Release") # Debug Release
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -std=c++14 -O3 -Wall -fopenmp")
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
#-------------path of 3rd party libraries-------------
# special libs.
find_package(Boost COMPONENTS filesystem iostreams regex)
find_package(FFTW)
find_package(NLopt)
find_package(HDF5 COMPONENTS CXX)
set(EXTERN_LIB_ROOT ${PROJECT_SOURCE_DIR}/3rd-party)
set(TENSORFLOW_ROOT /.../tensorflow)
set(TF_INCLUDE_DIRS "${TENSORFLOW_ROOT}" "${TENSORFLOW_ROOT}/bazel- genfiles" "${TENSORFLOW_ROOT}/bazel-tensorflow/external/protobuf_archive/src")
# lib dirs.
set(LUA_LIBRARIES "${EXTERN_LIB_ROOT}/lua/liblua53.so") #5.3.4
set(LINENOISE_LIBRARIES "${EXTERN_LIB_ROOT}/linenoise-ng/build/liblinenoise.so")
set(YACAS_LIBRARIES "${EXTERN_LIB_ROOT}/yacas/cyacas/libyacas/build/libyacas.so")
set(TF_LIBRARIES ${TENSORFLOW_ROOT}/bazel-bin/tensorflow/libtensorflow_cc.so
${TENSORFLOW_ROOT}/tensorflow/core/user_ops/tf.ZeroOut.gpu-master/zero_out.so
${TENSORFLOW_ROOT}/bazel-bin/tensorflow/core/user_ops/MyNewOp.so)
#-------------ssl headers-------------
include_directories(${PROJECT_SOURCE_DIR}/src
${EXTERN_LIB_ROOT}/eigen
${EXTERN_LIB_ROOT}/gnuplot-iostream
${EXTERN_LIB_ROOT}/
${EXTERN_LIB_ROOT}/linenoise-ng/include
${EXTERN_LIB_ROOT}/yacas/cyacas/libyacas/include
${EXTERN_LIB_ROOT}/lua/src
${NLOPT_INCLUDE_DIRS}
${FFTW_INCLUDES}
${TF_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${HDF5_INCLUDE_DIRS}
${TENSORFLOW_ROOT})
option(BUILD_SHARED_LIBS "build shared library" ON)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
#-------------ssl kernel lib-------------
file(GLOB_RECURSE _src_list
LIST_DIRECTORIES false
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/src/*.h" "${PROJECT_SOURCE_DIR}/src/*.cpp" "")
add_library(ssl SHARED ${_src_list})
set(SSL_LIBRARIES ${TF_LIBRARIES} ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${NLOPT_LIBRARIES} ${FFTW_LIBRARIES} ${LINENOISE_LIBRARIES} ${YACAS_LIBRARIES} ${HDF5_CXX_LIBRARIES}) #${TF_LIBRARIES}
target_link_libraries(ssl ${SSL_LIBRARIES} dl)
add_executable(Project1 main.cpp)
target_link_libraries(Project1 ssl)
There is a related question, but there is no clear answer. How to run custom GPU tensorflow::op from C++ code?
What am I doing wrong? I have no experience in shared library, but maybe there are other better ways to do what I'm trying to do...?
Can someone help me, Maybe giving an example of the required CMakeList.txt?
About the errors I got at runtime:
it was a very trivial one, just the function in my .so file couldn't be found if called with the right amount of parameters, if called with the wrong one it just didn't run.
In the meanwhile I found a better workaround. Since I can use my custom op in python, I will embed python in my c++ library, call a python function to make the graph,which will call my custom op to build the graph. But I didn't finish yet.
Using pkg_config it becomes very simple:
cmake_minimum_required(VERSION 3.10)
project(tf-inference)
find_package(PkgConfig)
pkg_check_modules(TensorFlow REQUIRED tensorflow)
link_directories(${TensorFlow_LIBRARY_DIRS})
include_directories(${TensorFlow_INCLUDE_DIRS})
add_compile_definitions(${TensorFlow_CFLAGS_OTHER})
add_executable(tf-inference inference.cpp)
target_link_libraries(tf-inference ${TensorFlow_LIBRARIES})
However that requires your TensorFlow install has the tensorflow.pc file included. On MacOS: brew install libtensorflow will include this file, and the above works automatically.

Building an external static library in CMake, and including the result

My C++ project has a dependency to a library, that I have the source for in a subdirectory. This external library has an option 'build_static_lib' for building it as a static library in its CMakeLists.txt file.
In my top directory CMakeLists.txt, my understanding is that this should be simple:
add_executable(myproject ${SOURCES})
set(build_static_lib ON)
add_subdirectory(${CMAKE_SOURCE_DIR}/subdirectory/external_project)
unset(build_static_lib)
....
target_link_libraries(myproject PRIVATE externalproject another_library)
When I run this, my sources are built, then during the make, I am given an error that it cannot find -lexternalproject.
The strange thing is, when I change CMakeLists.txt (or delete the CMakeCache), and run it again, suddenly it successfully builds the libexternalproject and links it correctly.
Am I missing something? My journey with CMake has been unbelievably painful and any suggestions would be appreciated. It seems like every online resource has a very different strategy, and none of them quite achieve this presumably simple case. Thanks!
EDIT:
The content of the external project's CMakeLists.txt is https://github.com/muflihun/easyloggingpp/blob/master/CMakeLists.txt:
if (build_static_lib)
if (lib_utc_datetime)
add_definitions(-DELPP_UTC_DATETIME)
endif()
require_cpp11()
add_library(easyloggingpp STATIC src/easylogging++.cc)
install(TARGETS
easyloggingpp
ARCHIVE DESTINATION lib)
endif()

How to link prebuilt .so files using CMakeLists.txt

I am trying to use cmake with android studio to compile c++ code, and I have a .so library which needs to be linked with the target.
I am new to cmake and this is what I have:
add_library(
my_target
SHARED
${SRCS}
)
find_library(
SSL
apex_fips_libs/libccmssl.so
)
target_link_libraries(
my_target
${SSL}
)
Folder structure:
-- Src
-- some.cpp
-- some2.cpp
-- CMakeLists.txt
-- apex_fips_libs
--libccmssl.so
But I am getting following error:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
SSL
I understand that SSL is not being set as find_library does not find the .so, but why?
I even tried using the absolute path. Can someone point me to the correct way of doing this?
Thank You.
If you're guaranteed to have that library there already built then perhaps this is the easiest solution
target_link_libraries(my_target ${CMAKE_SOURCE_DIR}/apex_fips_libs/libccmssl.so)
Otherwise you might want to try something more like
find_library(SSL NAMES ccmssl PATHS ${CMAKE_SOURCE_DIR}/apex_fips_libs)
target_link_libraries(my_target ${SSL})

Cmake cannot find library using "link_directories"

I Ubuntu, I am learning about cmake and make, and just trying a simple example. I have two directories: src and build. In src, I have two files: main.cpp, and CMakeLists.txt, which has (only) the following text:
add_executable(test main.cpp)
link_directories(/usr/lib/x86_64-linux-gnu)
target_link_libraries(test protobuf)
In /usr/lib/x86_64-linux-gnu, there is a shared library called libprotobuf.so, which I want to link against. My main.cpp uses functions in this library, by including the releveant header file, #include <google/protobuf/message.h>.
Now, in my build directory, I run cmake ../src, and then make. However, I then get linker errors telling me that there are undefined references to some of the functions in the protobuf library. If I do a search through all the files and subdirectories in build, there is not mention of anything related to protobuf.
However, if I remove the link_directories line in my CMakeLists.txt file, and instead write the full path to the library when specifying the executable, i.e. target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so), it compiles and links fine.
Why is link_directories not allowing cmake to find this library?
Do not use link_directories like this in CMake.
This is a common beginner's mistake, as many other build environments work like this, but in CMake it's just asking for trouble. Even the official documentation specifically advises against it:
Note that this command [link_directories] is rarely necessary. Library locations returned
by find_package() and find_library() are absolute paths. Pass these
absolute library file paths directly to the target_link_libraries()
command. CMake will ensure the linker finds them.
So instead, always pass absolute paths to target_link_libraries and use find_library to resolve the link directory:
find_library(PROTOBUF_LIBRARY protobuf HINTS /usr/lib/x86_64-linux-gnu)
target_link_libraries(test PUBLIC ${PROTOBUF_LIBRARY})
This has the huge benefit that you will probably get a diagnostic at CMake configure time if the expected library cannot be found, instead of a random linker error at compile time. Also, this allows the user to specify a library location via the GUI if the target machine has a non-standard directory layout.
So if it doesn't work right away, be sure to check the result of the find_library call and consult the official documentation to track down why it doesn't find your library as intended.
Make sure that your call to link_directories takes place before your call to the relevant add_executable.
I had mistakenly believed it only needed to be before the call to target_link_libraries, but that's not the case. After moving the call, the library is linked properly.
Make sure that the order will be link_directories, set PROJECT_LINK_LIBS, add_executable and then target_link_libraries.
Below is example to demonstarte it:
cmake_minimum_required(VERSION 2.8.9)
project (Logging)
include_directories(include)
file(GLOB LOGGINGSOURCES "libsrc/*.cpp")
file(GLOB SOURCES "src/*.cpp")
add_library(convertString SHARED ${LOGGINGSOURCES})
install(TARGETS convertString DESTINATION /root/Deepak/)
link_directories( /root/Deepak/ )
set(PROJECT_LINK_LIBS libconvertString.so)
add_executable(hello ${SOURCES})
target_link_libraries(hello ${PROJECT_LINK_LIBS} )
Perhaps it's very old topic but none of proposed solutions worked for me. So I had to make my own dirty hack. I do crosscompiling with buildroot and include toolchainfile.cmake.
#...
set(LIB_PATH ${PROJECT_SOURCE_DIR}/relative/path/to/your/lib)
#...
include_directories(/path/to/library/include)
set(LIB_MYLIB ${LIB_PATH}/libmylib.so)
#...
add_executable(${PROJECT_NAME} ${APP_SOURCES})
target_link_libraries(${PROJECT_NAME}
${LIB_MYLIB}
)
Hope this will help

CMake link library from subdirectory

I am trying to include SFML sources in my project. My directories are laid out like this:
main
SFML (subtree synced with the official git repo)
src
<various modules>
General (here lies the binary)
From the main level I am adding SFML subdirectory first and then src. As I've seen looking at the build log, this produces libraries:
sfml‑system
sfml‑window
sfml‑network
sfml‑graphics
sfml‑audio
sfml‑main
Now I want to link them to my binary in the General directory like this:
add_executable(main ${main_SRCS})
target_link_libraries (main
sfml‑system
sfml‑window
sfml‑network
sfml‑graphics
sfml‑audio
sfml‑main
# Other stuff here
)
But I get:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lsfml‑system
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lsfml‑window
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lsfml‑network
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lsfml‑graphics
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lsfml‑audio
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lsfml‑main
Why does CMake try to use system libraries instead of those it just built and how do I fix this?
This should just work.
Tried the following with Visual Studio generator on Windows and Makefile generator on Linux on CMake 3.2:
cmake_minimum_required(VERSION 2.8)
project(test)
add_subdirectory(SFML-2.2)
add_executable(foo bar.cpp)
target_link_libraries(foo sfml-system)
SFML is built correctly and foo links correctly to sfml-system.
The fact that you build your executable from another subdirectory should not have an impact here.