Shared object library not listing particular shared object dependencies - cmake

Using target_link_libraries in my CMakeLists.txt file results in only some of the shared-object library dependencies being set in the built library.
In my CMakeLists.txt file I have this:
set(STIREN_LIBS)
list(APPEND STIREN_LIBS
/usr/lib/x86_64-linux-gnu/libcairo.so
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so
/usr/lib/x86_64-linux-gnu/libboost_regex.so
/usr/lib/x86_64-linux-gnu/libicuuc.so
/usr/lib/x86_64-linux-gnu/libproj.so.12
/usr/lib/x86_64-linux-gnu/libharfbuzz.so
/usr/lib/x86_64-linux-gnu/libxml2.so
)
If I call target_link_libraries on that, as follows:
target_link_libraries(${PROJECT_NAME} PRIVATE ${STIREN_LIBS})
I get this as the result of objdump -p
Dynamic Section:
NEEDED libcairo.so.2
NEEDED libboost_filesystem.so.1.65.1
NEEDED libboost_regex.so.1.65.1
NEEDED libproj.so.12
NEEDED libxml2.so.2
NEEDED libstdc++.so.6
NEEDED libm.so.6
NEEDED libgcc_s.so.1
NEEDED libc.so.6
NEEDED ld-linux-x86-64.so.2
SONAME libstiren.so
It is missing the dependencies for libicuuc and lifharfbuzz. I confirm that those file paths are valid.
If I omit the target_link_libraries, I get this in the output of objdump -p
Dynamic Section:
NEEDED libstdc++.so.6
NEEDED libm.so.6
NEEDED libgcc_s.so.1
NEEDED libc.so.6
NEEDED ld-linux-x86-64.so.2
SONAME libstiren.so
So why is it that only some dependencies making it through?

Related

Build llvm-ar statically

I'm trying to compile llvm-ar (and only that) from LLVM statically because I need a static ar implementation for another purpose. AFAICS the official LLVM building documentation doesn't discuss this usage, only the option to build with shared libs, which is disabled by default anyway. Adding -static to CLAGS or the CMake option LLVM CFLAGS doesn't change the build process at all.
This is the build process I'm running right now:
cmake -DLLVM_ENABLE_PROJECTS=llvm-ar -G "Unix Makefiles" ../llvm
make -j3 llvm-ar
which then builds a dynamic llvm-ar:
$ ldd bin/llvm-ar
linux-vdso.so.1 (0x00007fff46154000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007faa84536000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007faa84319000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007faa840ef000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007faa83d66000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007faa839c8000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007faa837b0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faa833bf000)
/lib64/ld-linux-x86-64.so.2 (0x00007faa87163000)
How can I cause this target to be compiled statically? I'd also like to build with musl-gcc instead of the system default.

undefined reference to `shm_open' - how can I pinpoint the culprit?

I am trying to build a simple program against a library, which itself depends on librt. The library compiles just fine and the -lrt flag is used there. The program also builds fine on amd64 using cmake - but on arm64, it fails. This is not cross-compilation, but directly building it on the target. I'm using a normal cmake build system (cmake ..; make).
The exact same build system can also compile a different program, which uses the same library, but not the same functions from it.
Here is the build error:
[100%] Linking C executable mrun-talker
/usr/lib/gcc/aarch64-linux-gnu/7/../../../../lib/libsec-common.so: undefined reference to `shm_open'
/usr/lib/gcc/aarch64-linux-gnu/7/../../../../lib/libsec-common.so: undefined reference to `shm_unlink'
And here is the linker command:
/usr/bin/cc CMakeFiles/sec-talker.dir/main.c.o -o sec-talker -lsec-common -lsec-rosc -lsec-api -ltert -lgcov -lm -lrt -lpthread
The linker command does contain the -lrt flag at the end of the command and the lrt.so is available on the target.
Is there a chance that although the library compiles just fine, it does not properly link and causes this error later when I try to use it?
Full cmake-file:
get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(REPLACE " " "_" ProjectId ${ProjectId})
project(${ProjectId})
set(ExecName ${ProjectId})
enable_language(C)
find_package(Threads)
add_executable(${ExecName} main.c)
target_link_libraries(
${ExecName}
# sec libraries
sec-common
sec-rosc
sec-api
tert
# system libraries
gcov
m
Threads::Threads
rt
)
link_directories("/usr/local/lib")
install(TARGETS ${ExecName})
/edit
I used ldd to check the linking of the libsec-common. Here is the result of the (working) amd64 version:
# ldd /usr/lib/libsec-common.so
linux-vdso.so.1 (0x00007fff7e922000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffa350ef000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffa356ec000)
And of the (not-working) arm64 version.
# ldd /usr/lib/libsec-common.so
linux-vdso.so.1 (0x0000ffffb2dc6000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffb2c26000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffb2d9b000)
I don't see an issue here tbh.
The issue here was that the dependency itself did not correctly link it's dependency.

Link libc statically

I am trying to make a static executable with CMake 3.15. I am building on Alpine Linux (hence with musl), and currently, my executable's ldd output is:
# ldd my_executable
/lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7fc6f65b3000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7fc6f659f000)
I can set target_link_options(my_executable PRIVATE -static-libgcc -static-libstdc++), and they got linked statically:
# ldd my_executable
/lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
But I can't manage to get musl to link statically. I tried (with clean builds, to make sure that the configure step starts from zero):
Adding -static to target_link_options above.
set(CMAKE_EXE_LINKER_FLAGS "-static") before the call to add_executable(my_executable ...)
Adding -static to target_link_libraries(my_executable lib1 lib2 -static)
When I run CMake in VERBOSE=1 mode, it always ends the linking command with:
... -Wl,-Bdynamic -ldl -lrt -lm -lpthread
I believe that this is my issue: I want to get rid of that -Bdynamic. What am I missing? Is this -Bdynamic coming from one of my dependencies? I build them all from sources as static (.a) libraries, so how could they be linking libc dynamically? Or would I need to patch them all to add -static when I build them?
As hinted by KamilCuk's comment, the answer here seems to have the solution. Still, I'm not doing exactly the same, therefore I'll keep this answer, too.
For the target executable that I want statically linked:
add_executable(my_executable main.cpp)
I had to set the following properties/options:
set_target_properties(my_executable PROPERTIES LINK_SEARCH_START_STATIC ON)
set_target_properties(my_executable PROPERTIES LINK_SEARCH_END_STATIC ON)
target_link_options(my_executable PRIVATE -static-libgcc -static-libstdc++ -static)
Some notes:
LINK_SEARCH_*_STATIC were useful to remove -Bdynamic from the linking command.
I never managed to remove -ldl from the linking command, but it seems like dl did not get link eventually (presumably because it is not used).
ldd was not enough to verify that my_executable is statically linked. readelf -l my_executable showed that it does not have an INTERP header, and there is currently no such thing as a dynamic binary without it (using musl).
It turns out that checking whether a binary is statically linked or not is not so straightforward :-).

how do i specify libraries's path to cmake which are used by target_link_libraries

I have some codebase which has cmake build system .while building iam getting an error as below
/usr/bin/ld: cannot find -lcurl
below is the sample cmakelist.txt
cmake_minimum_required(VERSION 2.8.6)
project(oci_object_test)
set(IB_HOME /home/user/sample_cmake/usr/lib)
include_directories(${LIB_HOME}/include)
link_directories(${LIB_HOME}/lib64)
link_directories(/home/user/sample_cmake/usr/lib/lib64)
link_directories(/home/user/)
set(SOURCES
sample.cpp
)
add_executable(demo ${SOURCES})
target_link_libraries(demo curl openssl)
for the above cmakelist.txt below is the link.txt generated by cmake
/usr/bin/c++ CMakeFiles/demo.dir/sample.cpp.o -o demo -L/home/user/sample_cmake/usr/lib/lib64 -L/home/user -rdynamic -lcurl -lopenssl -Wl,-rpath,/home/user/sample_cmake/usr/lib/lib64:/home/user
this issue is due to -lcurl getting added in link.txt generated by cmake . if i remove -lcurl from link.txt manually and build ,build will get success with no linker error . So is there any way i can get rid off this -lcurl in link.txt or is it possible to define -lcurl path where it actual libcurl present ( for example suppose libcurl present inside /usr/curl_path/curl) so that cmake could generate link.txt as below?
/usr/bin/c++ CMakeFiles/demo.dir/sample.cpp.o -o demo -L/home/user/sample_cmake/usr/lib/lib64 -L/home/user -rdynamic /usr/curl_path/curl -lopenssl -Wl,-rpath,/home/user/sample_cmake/usr/lib/lib64:/home/user
i know i can define libucrl path directly as below which will solve my issue ,
target_link_libraries(demo /usr/curl_path/curl openssl)
but iam looking for something like SET or any other cmake environment variable which i can define inside toolchain.cmake file so that cmakelist.txt is untouched ,in simple words how do i specify those libraries's path to cmake which are going use inside target_link_libraries
If your CMake version is less than 3.12, you need to use this old method. See:
https://cmake.org/cmake/help/v3.10/module/FindCURL.html
cmake_minimum_required(VERSION 3.10)
project(program)
find_package(CURL REQUIRED)
if (CURL_FOUND)
add_executable(program main.cpp)
target_link_libraries(program ${CURL_LIBRARIES})
target_include_directories(program PRIVATE ${CURL_INCLUDE_DIRS})
endif()
There is a new method for CMake 3.12 and later using imported targets. See the new alternative FindCurl.
cmake_minimum_required(VERSION 3.12)
project(program)
find_package(CURL REQUIRED)
if (CURL_FOUND)
add_executable(program main.cpp)
target_link_libraries(program CURL::libcurl)
endif()
I found out that this issue can be solved by two methods (first method is similar to this)
second method is by adding below two lines of code to your cmakelist.txt file before calling target_link_directories
add_library( curl SHARED IMPORTED)
set_property(TARGET curl PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}")
where CURL_LIBRARY is the path for libcurl.so specified in toolchain.cmake
unfortunately i didn't find any solution to solve this issue without touching cmakelist.txt.

Unable to link libssl to libcrypto

I have created an application where it uses libssl which apparently uses libcrypto. I have kept these libraries at a user-defined location /path/to/xyz/lib/
---------------------------------------------------------------------------------------------------------------------------------
I have written a CMake for the application which links the libraries as follows:
set(GCC_LINK_FLAGS "-L/path/to/xyz/lib -lcurl -lpthread -lcrypto -lssl //other libs")
add_executable(Foo ${APP_SOURCE_FILES})
target_link_libraries(Foo ${GCC_LINK_FLAGS})
The CMake didnot give any error and created the Makefile which creates the executable.
---------------------------------------------------------------------------------------------------------------------------------
But When I run the executable. it throws the below error
./Foo: error while loading shared libraries: libcrypto.so.3: cannot open shared object file: No such file or directory
I have checked the dynamic linking of libssl.so as follows and found the libcrypto isn't linked...
[root#localhost build]# ldd /path/to/xyz/lib/libssl.so.3
linux-vdso.so.1 => (0x00007fffa5fa7000)
libcrypto.so.3 => not found
libdl.so.2 => /lib64/libdl.so.2 (0x00007f17ea772000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f17ea556000)
libc.so.6 => /lib64/libc.so.6 (0x00007f17ea193000)
/lib64/ld-linux-x86-64.so.2 (0x0000563b0856f000)
I have checked the /path/to/xyz/lib/pkgconfig/libssl.pc file and found this suspicious for this error
prefix=/path/to/xyz/lib/
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenSSL-libssl
Description: Secure Sockets Layer and cryptography libraries
Version: 3.0.0-dev
Requires.private: libcrypto
Libs: -L${libdir} -lssl
Cflags: -I${includedir}
QUESTION
What does Requires.private: libcrypto do?
And how to solve this error?
--------------------------------------------------------------EDIT--------------------------------------------------------------
I have Done following edits in the cmake file
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "/path/to/xyz/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_executable(SpeechToText ${APP_SOURCE_FILES})
target_link_libraries(Foo ${GCC_LINK_FLAGS})
install (TARGETS Foo RUNTIME DESTINATION /path/to/project/directory)
I am getting segmentation fault by this change.
Install the project...
-- Install configuration: ""
-- Installing: /path/to/project/directory/Foo
-- Set runtime path of "/path/to/project/directory/Foo" to "/path/to/xyz/lib"
[root#localhost build]# ../Foo
Segmentation fault (core dumped)