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)
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...
I've been given a dll without libs.
The dll comes with hpp and h files.
I used dumpbin to create an exports.def file and lib to create a library.
I'm using the following CMakeLists.txt
cmake_minimum_required ( VERSION 3.22 )
project ( mytest )
include_directories("${PROJECT_SOURCE_DIR}/libincludedir")
add_executable ( mytest main.cpp)
target_link_libraries ( mytest LINK_PUBLIC ${PROJECT_SOURCE_DIR}/libincludedir/anewlib.lib )
The original dll and created lib and h and hpp files are all in the libincludedir. Dll is also copied to the bin dir where the exe would be.
I get no linker errors with the lib, but no functions defined in the include headers have bodies found. Types are Undefined. Classes are incomplete.
How do I fix this? Can I progress with what I was given or should I ask for more?
Assuming that you created the .lib correctly, this is how you would set up something linkable:
cmake_minimum_required(VERSION 3.22)
project(example)
add_library(anewlib::anewlib SHARED IMPORTED)
set_target_properties(
anewlib::anewlib
PROPERTIES
IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/libincludedir/anewlib.lib"
IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/libincludedir/anewlib.dll"
IMPORTED_NO_SONAME "TRUE"
INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/libincludedir"
)
add_executable(mytest main.cpp)
target_link_libraries(mytest PRIVATE anewlib::anewlib)
Always link to targets since they provide CMake with much more information than a raw library file. Here, we're telling CMake about the locations of both the .lib and the .dll, that it doesn't have a SONAME (a *nix only thing, anyway, but good to include), and the include path that linkees should use to find its associated headers.
Then when you link mytest to it, mytest will have a correct link line constructed and it will see the right headers.
Question is: How do I get CMAKE to set/make the CURL_INCLUDE_DIR be "/usr/local/Cellar/curl/7.75.0/include/"?
No matter what I do, CMAKE only finds the Xcode lib version/location.
My CMAKE file contains:
set(CURL_ROOT_DIR /usr/local/Cellar/curl/7.75.0/include/)
find_package(curl REQUIRED)
message(STATUS ">>> CURL Dir Found: " ${CURL_INCLUDE_DIR})
No matter what I've tried, the above CMAKE code will result in a "CURL_INCLUDE_DIR" of
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include
Note, utilizing "include(findcurl)" instead of "find_package(curl REQUIRED)" gives same result.
I've resorted to adding
set(CMAKE_CXX_FLAGS "-I/usr/local/Cellar/curl/7.57.0/include
-L/usr/local/Cellar/curl/7.57.0/lib")
to get CMAKE to actually utilize the lib version/location that I want. Is there a better way that I'm failing to figure out?
The cmake FindCURL module (at least in the version I have, 3.5.1) does not make reference to CURL_ROOT_DIR anywhere, so I don't believe setting that variable will have any effect.
In fact the FindCURL module is really quite basic and doesn't offer any means for customising where to look, which means it will be looking only in "standard" paths (eg /usr/lib, /usr/local/lib etc)
You can, however, use find_library which takes a PATHS argument.
set(CURL_PATH "/usr/local/Cellar/curl/7.75.0")
find_library(
LIB_CURL
NAMES
curl
PATHS
${CURL_PATH}/lib)
At this point you will have a variable ${LIB_CURL} which points to the location of libcurl
Link against the library and set the include path:
You can then just link against ${LIB_CURL} directly, and manually specify the include path for your target too, such as:
add_executable(
foo
main.cpp)
target_link_libraries(
foo
${LIB_CURL})
target_include_directories(
foo
SYSTEM
PRIVATE "${CURL_PATH}/include")
IMPORTED library target:
Another option, if you want to be fancy, is to create an IMPORTED library target using ${LIB_CURL}, and set the INTERFACE_INCLUDE_DIRECTORIES on that target, so consumers get the include path set automatically.
add_library(
libcurl
IMPORTED)
set_target_properties(
libcurl
PROPERTIES
IMPORTED_LOCATION "${LIB_CURL}")
set_target_properties(
libcurl
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CURL_PATH}/include")
Now you will just be able to link against target libcurl directly, and your app will automatically have its include paths updated
add_executable(
foo
main.cpp)
target_link_libraries(
foo
libcurl)
My problem is relatively simple to explain. I have a CMake project(using CLion) running mainly on Windows.
A main CMakeLists.txt project, linking 2 subdirectories
src/Library shared library
src/Executable executable linking Library
See the project structure below.
# main CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(TestTest)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(src/Library)
add_subdirectory(src/Executable)
# src/Library/CMakeLists.txt
add_subdirectory(include)
add_subdirectory(src)
add_library(TestLib SHARED ${TESTLIB_H_FILES} ${TESTLIB_SRC_FILES} )
target_include_directories(TestLib PUBLIC include)
#src/Executable/CMakeLists.txt
add_subdirectory(src)
add_executable(Executable ${EXECUTABLE_SRC_FILES})
target_link_libraries(Executable PUBLIC TestLib)
My problem is that the executable can't find the shared library at runtime.
I tried to add link_directories( ${CMAKE_CURRENT_BINARY_DIR}/src/Library) but didn't work.
What am I missing?
Please note: I wouldn't like to copy the shared library next to the executable manually/automatically by CMake, since I believe I would loose the debugging "capability" of the shared library. I will be getting the following error message by the GDB: No source file named C:/Users/flatron/CLionProjects/TestTest/src/Library/src/library.cpp.
All suggestions are really welcome and appreciated,
Thank you for your help
I suggest to use the following cmake command:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
This will build all executables and shared libraries into the bin folder.
So there is no need to copy anything by hand.
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.