I have a shared library that is provided to me for for target aarch64. I wrote some quick CMake to create an import target for it as follows:
add_library(BeClearWrapper SHARED IMPORTED GLOBAL)
set_target_properties(BeClearWrapper PROPERTIES IMPORTED_LOCATION
"${CMAKE_CURRENT_LIST_DIR}/libBeClearSuperHandsFree.so"
)
set_target_properties(BeClearWrapper PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
${CMAKE_CURRENT_LIST_DIR}/include
)
Elsewhere I consume that library with a benchmarking exe (also cross-compiled to aarch64 of course):
set(CMAKE_SKIP_INSTALL_RPATH TRUE)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
add_executable(BeClearBenchmark main.cpp)
target_link_libraries(BeClearBenchmark
PRIVATE
BeClearWrapper
)
I push these to the target but the executable can’t find the shared library. I started using SKIP_RPATH settings as a trial to see if I could remove the hard-coded path to the library which didn’t seem to affect anything. I’ve also tried just setting LD_LIBRARY_PATH to point to the location of the shared library but in all cases I get the message below in my adb shell. The path shown is the path to the library on the host/build machine.
I’ve got to be missing something simple here - any insights?
malcolm-B17687# BeClearBenchmark
BeClearBenchmark: error while loading shared libraries: /home/rich/scratch/BeClearBenchmark/BeClearBenchmark/BeClear/libBeClearSuperHandsFree.so: cannot open shared object file: No such file or directory
(exit=127)malcolm-B17687# ldd BeClearBenchmark
linux-vdso.so.1 (0x0000007fa1502000)
/home/rich/scratch/BeClearBenchmark/BeClearBenchmark/BeClear/libBeClearSuperHandsFree.so => not found
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000007fa1340000)
libm.so.6 => /lib64/libm.so.6 (0x0000007fa1287000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000007fa1262000)
libc.so.6 => /lib64/libc.so.6 (0x0000007fa10e9000)
/lib64/ld-linux-aarch64.so.1 => /lib/ld-linux-aarch64.so.1 (0x0000007fa14d4000)
malcolm-B17687#
It looks like the DT_SONAME
entry of that BeClearBenchmark
is wrong. What is output if you run readelf -d
on it?
this is the full output from readelf -d BeClearBenchmark
on the build machine
readelf -d BeClearBenchmark
Dynamic section at offset 0x1d60 contains 31 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [/home/rich/scratch/BeClearBenchmark/BeClearBenchmark/BeClear/libBeClearSuperHandsFree.so]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/rich/scratch/BeClearBenchmark/BeClearBenchmark/BeClear:]
0x000000000000000c (INIT) 0xaf8
0x000000000000000d (FINI) 0x145c
0x0000000000000019 (INIT_ARRAY) 0x11d48
0x000000000000001b (INIT_ARRAYSZ) 16 (bytes)
0x000000000000001a (FINI_ARRAY) 0x11d58
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x2a0
0x0000000000000005 (STRTAB) 0x4e8
0x0000000000000006 (SYMTAB) 0x2c0
0x000000000000000a (STRSZ) 695 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x11fe8
0x0000000000000002 (PLTRELSZ) 360 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x990
0x0000000000000007 (RELA) 0x840
0x0000000000000008 (RELASZ) 336 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffb (FLAGS_1) Flags: PIE
0x000000006ffffffe (VERNEED) 0x7d0
0x000000006fffffff (VERNEEDNUM) 3
0x000000006ffffff0 (VERSYM) 0x7a0
0x000000006ffffff9 (RELACOUNT) 7
0x0000000000000000 (NULL) 0x0
Whoops, that is the executable. I want to see the output on that libBeClearSuperHandsFree.so
library. Sorry.
Here it is:
rich@doodad:~/scratch/BeClearBenchmark/BeClearBenchmark/BeClear$ readelf -d libBeClearSuperHandsFree.so
Dynamic section at offset 0x46080 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0xfe8
0x000000000000000d (FINI) 0x4034c
0x0000000000000019 (INIT_ARRAY) 0x56000
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x56008
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x180
0x0000000000000005 (STRTAB) 0x718
0x0000000000000006 (SYMTAB) 0x1f0
0x000000000000000a (STRSZ) 873 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x562c0
0x0000000000000002 (PLTRELSZ) 768 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xce8
0x0000000000000007 (RELA) 0xb68
0x0000000000000008 (RELASZ) 384 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffc (VERDEF) 0xaf0
0x000000006ffffffd (VERDEFNUM) 2
0x000000006ffffffe (VERNEED) 0xb28
0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0xa82
0x000000006ffffff9 (RELACOUNT) 10
0x0000000000000000 (NULL) 0x0
For now I’ll just do the quick but inelegant approach here:
add_executable(BeClearBenchmark main.cpp)
target_include_directories(BeClearBenchmark PRIVATE BeClear/include)
target_link_directories(BeClearBenchmark PRIVATE BeClear)
target_link_libraries(BeClearBenchmark
PRIVATE
libBeClearSuperHandsFree.so
# BeClearWrapper
)
I’m starting to think that to properly use an imported library I’d need to create a full package configuration file.
It seems to me there are limitations to using an imported library the way I was trying to. The obvious one here is that anyone linking against it has a fixed filesystem path to the location of that imported library, which causes problems if you want to load it from a different location when the executable is deployed.
Oh, the library completely lacks DT_SONAME
. If you add one (something like -Wl,-soname=libBeClearSuperHandsFree.so
if manually built or the SONAME
property if it uses CMake) and rebuild, it should work a lot better.
Are you saying do something like this (see last set_target_properties
) in the CMakeLists.txt that declares the imported target?
add_library(BeClearWrapper SHARED IMPORTED GLOBAL)
set_target_properties(BeClearWrapper PROPERTIES IMPORTED_LOCATION
"${CMAKE_CURRENT_LIST_DIR}/libBeClearSuperHandsFree.so"
)
set_target_properties(BeClearWrapper PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
${CMAKE_CURRENT_LIST_DIR}/include
)
set_target_properties(BeClearWrapper PROPERTIES INTERFACE_LINK_DIRECTORIES
${CMAKE_CURRENT_LIST_DIR}
)
set_target_properties(BeClearWrapper PROPERTIES IMPORTED_SONAME
libBeClearSuperHandsFree.so
)
I gave this a quick test and it unfortunately didn’t change anything.
No, the thing that builds the library. The HandsFree.so
library is broken because it lacks a DT_SONAME
. It will need relinked at least.
That library is provided by a vendor precompiled for aarch64. I don’t control the building of that.
Then you’ll need to use something like patchelf
to edit the DT_NEEDED
entry:
$ patchelf --replace-needed /full/path/that/shows/up/libBeClearSuperHandsFree.so libBeClearSuperHandsFree.so program
to anything that links it on the command line (even transitively). Alternatively, you can use:
$ patchelf --set-soname libBeClearSuperHandsFree.so /path/to/precompiled/library
as a pre-processing step.
1 Like
I would encourage you to contact your vendor to provide a soname for the library so that it can be used properly as delivered.
1 Like