On Ubuntu, I have two directories: build and src. In src, my CMakeLists.txt file has the lines:
add_executable(Test main.cpp)
target_link_libraries(Test libCamera.so)
After running cmake in the build directory (cmake ../src), I then copy my library file libCamera.so into the build directory. After running make, the main.cpp.o file compiles successfully, but I receive the following error during linking:
/usr/bin/ld: cannot find -lCamera
Why is this? The shared library is in the same directory that I am building in... and the same thing happens if I copy the library to /usr/bin...
You should not put prefix lib and suffix .so of the library, so just use:
target_link_libraries(Test Camera)
if your library not found you may need to add directory, where library is located:
link_directories( /home/user/blah ) # for specific path
link_directories( ${CMAKE_CURRENT_BINARY_DIR} ) # if you put library where binary is generated
Note: you copied lib to /usr/bin but unlike Windows where dll files stored with executables, in Linux that is not the case, so it would be /usr/lib, not /usr/bin. Also you may change LD_LIBRARY_PATH variable to make your program to find a library in a custom location.
Related
Simplified a little
I have a project with 2 targets (subdirectories): first libMain.so library, who linked with second libDependent.so :
add_library( Main SHARED ${cpp} )
target_link_libraries(Main
Dependent
)
I make a conan package, that contains 2 libraries - libMain.so and libDependent.so inside /package/CONANPACKAGEID/lib folder
In conan also located FindMainPackage.cmake with example code
find_library (Main_LIBRARIES Main Main_d
HINTS ${Main_ROOT_DIR} ${CMAKE_INSTALL_PREFIX}
PATH_SUFFIXES lib
)
and find_path
In my general project I use find_package(Main) and link my third lib with Main
target_link_libraries(General
${Main_LIBRARIES}
)
or
target_link_libraries(General
Main
)
both variants are work
And last I linked this lib with my google test binary
target_link_libraries( Test
GTest::GTest
General
)
If I set to LD_LIBRARY_PATH a variable ${CONAN_LIB_DIRS_MAIN} (equal /package/CONANPACKAGEID/lib) and run binary from build dir from terminal -> it work good, all libs are found
But if I try to run w/o (5) I get the output
error while loading shared libraries: libDependent.so: cannot open shared object file: No such file or directory
I check my binary with ld command and get the output
libMain.so /.conan/data/package/CONANPACKAGEID/lib/libMain.so (0x00007c815718f000)
libDependent.so => **not found**
If I link my General with Dependent
target_link_libraries(General
Main
Dependent
)
all works good and libDependent.so located in conan package near with libMain.so in ld output
My questions:
Why my binary know thatlibMain.so inside conan package folder. This conan package are not exists in lib pathes ( check with ldconfig)
Why my binary cannot find libDependent.so automatically
How I can fix this or how work with situation right?
Thank you for help, my brain in over after 2days...
Here is a sample project I am trying to build with a "Packages" directory which includes all the libraries to be used in the main code.
I am trying to keep my root cmake file as clean as possible and avoid relative path such as
include_directory(packages/lib1)
but I am struggling. Is there a way of including sub-directories of a directory for the purposes of header inclusion.
First a few minor remarks:
always name the CMake configuration files CMakeLists.txt (because of)
bookmark the documentation on CMake: https://cmake.org/documentation/
Sometimes it's not that easy to read, but very specific once you adopt your head to the "CMake world" ;-)
make yourself comfortable with the scope of CMake variables
include_directories(DIR1 [DIR2 [...]])
Tells CMake where the compiler should look for header files, i.e. -IDIR1 -IDIR2 ....
add_library(NAME [STATIC|SHARED] SOURCES)
This command creates the required compiler commands to create a static or shared library out of a given list of source files. No need to add in the header files. The make target will be called NAME and the library target is known to CMake as NAME.
add_subdirectory(DIR)
Tells CMake to look into DIR and parse the included CMakeLists.txt with all its content.
target_link_libraries(TARGET LIB1 [LIB2 [...]])
Tells CMake to instruct the linker to link LIB1, LIB2, etc. to the TARGET, i.e. -LLIB1 -LLIB2 .... TARGET is a CMake/make target previously defined/created with a call to add_{library,executable,custom_target}.
CMakeLists.txt:
include_directories(libraries)
# a header file in `libraries/lib1/foo.hpp` can be included
# in the whole CMake project by `#include "lib1/foo.hpp"`.
add_subdirectory(libraries)
add_subdirectory(tests)
libraries/CMakeLists.txt:
add_subdirectory(lib1)
add_subdirectory(lib2)
libraries/lib1/CMakeLists.txt:
add_library(lib1 STATIC ${LIB1_SOURCES})
libraries/lib2/CMakeLists.txt:
add_library(lib2 STATIC ${LIB2_SOURCES})
tests/CMakeLists.txt:
add_executable(tests ${TEST_SOURCES})
target_link_libraries(tests lib1 lib2)
I have linked an external c++-library to an existing cmake project using the following cmake commands:
SET (some_src
.
.(sourcefiles here)
.
.
.
.
)
ADD_LIBRARY(some_proj SHARED ${some_src})
# Adding precompiled NURBS lib
SET(nurbs_libs ${CMAKE_SOURCE_DIR}/src/nurbs/libs)
ADD_LIBRARY( nurbs_C SHARED IMPORTED )
SET_TARGET_PROPERTIES( nurbs_C PROPERTIES
IMPORTED_LOCATION ${nurbs_libs}/surface.so.1.0
LINKER_LANGUAGE "CXX")
TARGET_LINK_LIBRARIES( some_proj nurbs_C )
SET(CMAKE_INSTALL_PATH ${nurbs_libs})
INSTALL(TARGETS some_proj DESTINATION lib)
install(FILES ${nurbs_libs}/surface.so.1.0 DESTINATION lib)
When trying to run a program that uses the library I keep getting the error
reels: error while loading shared libraries:
surface.so.1: cannot open shared object file: No such file or directory
I tried playing with LD_LIBRARY_PATH and RPATH but to no avail. I suspect I did something wrong with the cmake file. How can I handle this problem?
Because you have binary file compiled, there is probably no problem with your CMakeLists.txt. Use ldd to find out which libraries you are missing. Also check that you have surface.so.1 present on disk (probably it would be link directing to surface.so.1.0)
I downloaded libboost1.50-all in Raspberry Pi and has successfully compiled and execute a program using threads. Libraries were also found in CMake. I then copied the libraries of the boost and its include from /usr/lib and /usr/include/boost respectively to C:\Boost such that the hierarchy becomes:
C:
-> Boost
-> lib
... files
-> include
-> boost
... files
I then used the same CMakeLists.txt and the source code but the library was not found.
NOTE: The cross compiler that I used is fully working and I was able to produce an executable with CMake in Cygwin using the std library. I even specified the location of the library and the user and the root.
Is there anything that I missed out?
cmake_minimum_required(VERSION 2.8)
set(BOOST_ROOT C:/Boost/)
set(BOOST_INCLUDEDIR C:/Boost/include/)
set(BOOST_LIBRARYDIR C:/Boost/lib/)
SET(Boost_DEBUG ON)
find_package(Boost 1.50.0 COMPONENTS thread system)
if (Boost_FOUND)
include_directories (${Boost_INCLUDE_DIRS})
add_executable (thread thread.cpp)
target_link_libraries(thread ${Boost_LIBRARIES})
endif()
Use CMAKE -GUI and then check whether your boost libraries are detected . If not then manually set in the CMAKE-GUI and configure again.
TEMPORARY SOLUTION that I was able to come up to!
I placed the boost lib and include to where the cross compiler is installed since the cross compile was able to link the source code to libstdc++.
The library is placed here:
C:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\arm-unknown-linux-gnueabi\sysroot\lib
The include files are placed here:
C:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\arm-unknown-linux-gnueabi\include\c++\4.6.3
The CMakeLists content is as follows now:
cmake_minimum_required(VERSION 2.8)
add_executable (thread main.cpp)
target_link_libraries(thread boost_thread boost_system)
Open Cygwin terminal and invoke cmake there, then make. Viola! It now compiles successfully! :>
The magic lies in here:
target_link_libraries(thread boost_thread boost_system)
I found this in one of the questions here in Stackoverflow where someone said to manually link the libraries..
Even though that it worked, why is it that CMake cannot detect the boost library both in Windows (Cygwin terminal) and Linux (VMware) -- These I tried -- but the library was found in Raspberry Pi (Raspbian) using the same CMakeLists.txt and main.cpp. Isn't it the purpose of CMake is to find the libraries itself? If I were just to link them manually, better do it like this then:
arm-unknown-linux-gnueabi-g++.exe -lboost_thread -lboost_system
#include path
include_directories(
${PROJECT_SOURCE_DIR}/include
${HGE_INCLUDE_DIR}
${IKL_INCLUDE_DIR}
${BOOST_DIRECTORY}
)
#include all files
FILE(GLOB CORE_SRCS source/core/*.cpp)
FILE(GLOB TOOL_SRCS source/tools/*.cpp)
FILE(GLOB GAME_SRCS source/game/*.cpp)
#Making a compiled library
add_library(GAMECORE_LIBRARY ${CORE_SRCS} ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY})
#add executable
add_executable(DemoGame ${GAME_SRCS})
##link executable to HGE lib
TARGET_LINK_LIBRARIES(DemoGame ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY} ${IKL_LIBRARY} GAMECORE_LIBRARY)
if(BUILD_TOOLS)
add_executable(EntityTool ${TOOL_SRCS})
TARGET_LINK_LIBRARIES(EntityTool ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY} ${IKL_LIBRARY} GAMECORE_LIBRARY)
endif(BUILD_TOOLS)
this is my current cmake ..
I get a weird linker error for hgeGUI class
eg : DemoGame/source/core/GameMainMenu.cpp:74: undefined reference to `hgeGUI::hgeGUI()'
This only happens when I try to compile the core files into a static library.
When I add the executable with the CORE_SRCS and remove the dependencies on my current compiled library .. it will work fine..
Also I tried copy pasting the hgegui.cpp file into my core sources directory .. and change the #include "..\..\include\hgegui.h" to #include "hgegui.h"
After that my linker code resolves the issue but I get segmentation faults but I m guessing linking the file in the previous step was not right ..
Here's a link to their .h file
http://trac.assembla.com/snowscape/browser/hge/include/hgegui.h
It looks like you're misusing the ${HGE_LIBRARY} and ${HGE_HELPER_LIBRARY} variables.
In an add_library call, you include all the source files which make up that library.
In a target_link_libraries call, you specify libraries or flags to use when linking the target.
So, if ${HGE_LIBRARY} and ${HGE_HELPER_LIBRARY} specify paths to libraries which you want to specify as dependencies of GAMECORE_LIBRARY, you need to do:
add_library(GAMECORE_LIBRARY ${CORE_SRCS})
target_link_libraries(GAMECORE_LIBRARY ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY})
The dependencies are transitive, so this means when you specify GAMECORE_LIBRARY as a dependency of DemoGame and EntityTool, then CMake recognises that ${HGE_LIBRARY} and ${HGE_HELPER_LIBRARY} are also dependencies, so you can remove them from the target_link_libraries calls for DemoGame and EntityTool if you want.
For further info on add_library and target_link_libraries, run:
cmake --help-command add_library
cmake --help-command target_link_libraries