Imported shared library - can't seem to get rid fixed path to it in exe

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