Cmake - not creating the dynamic links - cmake

The project that I am compiling is not linking my shared object file to the main program. This can be confirmed by doing the ldd command on my executable and seeing it say libba.so => not found.
Inside my CMakeLists.txt file I have:
add_library(ba SHARED "/usr/local/include/libba.cpp" "/usr/local/include/libba.h")
target_link_libraries(ba (list of other libraries that link to ba))
set_target_properties(ba PROPERTIES LINK_INTERFACE_LIBRARIES "" LINK_FLAGS "${NO_UNDEFINED}")
add_executable(run "/usr/local/main/run.cpp")
target_link_libraries(run ba)

ldd reports what the run-time linker can find.
If you see libba.so in the output it means the binary is linked to the library.
The "not found" means the run-time linker can't find that library (i.e. you don't have it installed in a normal system location).
So you can either install your library to a system location, configure your run-time linker to know about your custom location, link your application statically, or use an rpath in your binary to have it give the run-time linker additional places to look for just itself.

Related

CMake: embedding path to imported shared library in executable

I have an external library. That I am bringing into a CMake build using an imported library target. The build is baking in relative path to the shared library with respect to the CMAKE_BINARY_DIR.
I have something like this:
add_library(libstring UNKNOWN IMPORTED)
set_target_properties(libstring PROPERTIES
IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/external/libstring.so"
)
add_executable(my_exe "${CMAKE_CURRENT_BINARY_DIR}/my_exe.cpp")
target_link_libraries(my_exe PRIVATE libstring)
Then ldd my_exe returns
external/libstring.so => not found
If instead of linking to the imported target I link directly to the library giving the absolute file path it works fine.
target_link_libraries(my_exe PRIVATE "${CMAKE_BINARY_DIR}/external/libstring.so")
Then ldd returns
libstring.so => /<bin-dir>/external/libstring.so (0x00007fce27537000)
In both cases rpath is set to /<bin-dir>/external.
When linking to an imported target how to make CMake bake in just the name of the library in the executable?
Note, that when the imported library path is outside of the binary tree, then the absolute path is baked in the executable.
It turned out that it is not CMake causing this problem, but this particular library.
With Unix Makefiles, CMake passes to the linker relative paths with respect to the CMAKE_CURRENT_BINARY_DIR.
../external/libstring.so
Or with Ninja it passes relative to CMAKE_BINARY_DIR.
external/libstring.so
The linker then bakes-in this whole relative path. Not the name of the library only.
Other libs are not affected even when passed to the linker like that. I don't know what is different with this library.
The solution is to set IMPORTED_NO_SONAME property for the library:
set_property(TARGET libstring PROPERTY IMPORTED_NO_SONAME TRUE)
Documentation for this property says:
Set this property to true for an imported shared library file that has
no soname field. CMake may adjust generated link commands for some
platforms to prevent the linker from using the path to the library in
place of its missing soname.

CMake library file missing

I'm currently struggling with cmake.
I'm using Cmake for an embedded platform with GCC.
My project is separate into several modules. Each module is build into a static library. At link time, all of these libraries are collected and linked into one binary.
The problem: I created a new folder for some unit tests. All sources are build into a library libunit_tests.a.(I checked the library actually gets created).
However in my linker call other libraries are passed to the linker, mine however gets omitted resulting in an undefined reference error.
My folder structure looks like this
*
unit_tests/
*
unit_tests/inc
*unit_tests/src
There is one Cmake file located at
- /unit_tests/CMakeLists.txt
My actual CMakeLists.txt file is pretty basic
include_directories("./inc")
set(module_name "unit_tests")
set(MODULE_SOURCES
./inc/active_tests.h
./inc/Run_All_Tests.h ./src/Run_All_Tests.c
)
###########################
# add library
###########################
if(MODULE_SOURCES)
# add files to library
add_library("${module_name}"
${MODULE_SOURCES})
target_link_libraries("${module_name}"
-Wl,--start-group
-Wl,--end-group)
endif()
How do i pass this library to the linker to resolve the undefined reference error?
I thought this is done via add_libary and target_link_libraries?

CMAKE - runtime library hidden files

I am running Linux Redhat, I have Anaconda installed and I am trying to install a program (libspimage) using CMAKE amd I get the following warning/error:
CMake Warning at src/CMakeLists.txt:74 (ADD_LIBRARY):
Cannot generate a safe runtime search path for target _spimage_pybackend
because files in some directories may conflict with libraries in implicit
directories:
runtime library [libtiff.so.5] in /usr/lib64 may be hidden by files in:
/home/michantia/anaconda2/lib
Some of these libraries may not be found correctly.
When I do:
echo $PATH
I get:
/home/mi_a/anaconda2/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/michantia/.local/bin:/home/michantia/bin
I tried:
export PATH=/usr/lib64:$PATH
hoping cmake would find the libraries in this directory before finding them in anancoda's, but that did not work. I also tried two other similar suggestions for a similar problem that I saw in stackoverflow, but that did not work.
Any other ideas are highly welcomed.
Warning message
Cannot generate a safe runtime search path for target
is related neither with CMake ability to find a library (libtiff.so.5 in your case) nor with a linker ability to link the library.
The warning message means that when a target (_spimage_pybackend) will be loaded, the loader will be unable to choose the correct library: according to the loader's algorithm and the target's setting, file /home/michantia/anaconda2/lib/libtiff.so.5 will be choosen instead of proper one /usr/lib64/libtiff.so.5.
The error is usually resulted in linking into the single target two libraries from different directories, when the directory with a second library also contains a file with the name of the first library:
Directory /usr/lib64 contains a library libtiff.so.5, which is linked into the target.
Directory /home/michantia/anaconda2/lib contains a library <A> which is also linked into the target; but this directory also contains a file libtiff.so.5.
According to CMake algorithm, runpath for the binary file of such target will include both directories, so both libraries could be found. But such runpath confuses the loader to find the first library properly.
Except from avoiding such situation (when a library is contained in two directories), one hardly is able to handle this warning.

Link errors when building shared library even though source files are included

I am specifying a shared library build from source files in my CMakeLists.txt file like so:
# Library setup
file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.cpp)
file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.h)
Inside the source directories contain all my .h and .cpp files required to build my shared library. So I then do something like this:
add_library(mylibrary SHARED ${SOURCES} ${HEADERS} )
I also link a bunch of other .libs with mylibrary later on as well (Could there be a clashing issue?). The problem arises when I try to build mylibrary. I receive linking errors such as:
Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol __imp_cosf mylibrary ***.obj 1
even though the symbol is defined in my source files that I have included. I am not exactly sure what to do in order to properly let my project find those symbols. The funny thing is is that when I build as a static library it is fine. However, when I try to build as a dynamic library, these errors appear.
So, I'm not exactly sure why this worked. But there was a conflict warning between linking to MSVRCT and libcmt. It said something like this in the output log:
Resolving LNK4098: defaultlib 'MSVCRT' conflicts with ...
This is because libcmt is a static library for release build and uses \MT flags. MSVRCT is a release DLL version and compiled with \MD flag. Because of this conflict, I had to change my compiler flags to be:
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
Then the symbols were able to be found. If anyone has any comments/corrections to why this worked please add.

How to build library or executable binary project with dependent library project with cmake

I have two cmake projects:
BiosPatcher\CommonBase\
BiosPatcher\Bios\
First one builds a library and has ./include folder with headers.
How to build second project library(or executable) which depends on first library ./include for compilation and libCommonBase.dll for execution(in case of executable file building).
I've included header files like that
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../CommonBase/include)
And it works.
And I link library like that:
target_link_libraries (Bios libCommonBase)
But I get error message:
c:\Users\Sakhno\workspace\BiosPatcher\Bios\build>make
[ 16%] Linking CXX shared library libBios.dll
C:/mingw-w64/mingw32/bin/../lib/gcc/i686-w64-mingw32/5.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -llibCommonBase
collect2.exe: error: ld returned 1 exit status
I think i need somehow specify folder to look for the library but i don't know how.
I was able to build Bios project which depends on CommonBase project target library by adding following lines.
set(COMMON_BASE_PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../CommonBase)
...
include_directories(${COMMON_BASE_PROJECT_DIR}/include)
...
target_link_libraries (Bios ${COMMON_BASE_PROJECT_DIR}/build/libCommonBase.dll)