CMake library target brought in thru Conan - when linked to executable I can't get rid of full-path to library

I’m building a test application that links against a library provided by a Conan package. Through the use of some autogenerated CMake provided by Conan, that library is linked against as a target, such as:
consumed-lib::consumed-lib. The problem with this CMake target is that the library has no relative path from the current CMake project’s build folder - it’s a full path. That full path ends up in the resulting elf file and results in the executable not finding the library at runtime even when LD_LIBRARY_PATH is set to point to where that library is on the target’s file system.

Here’s an actual snippet from the elf file:

readelf -d AudioFileTest | head -20

Dynamic section at offset 0x3d90 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libRpcClientBeClearMaec.so]
 0x0000000000000001 (NEEDED)             Shared library: [/home/rich/.conan/data/be-clear-philips-audiofile/1.2.1/bose-corp/master/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/lib/libBeClearAudiofile.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [/opt/Bose/lib64/:/opt/Bose/lib/:/home/rich/.conan/data/be-clear-philips-audiofile/1.2.1/bose-corp/master/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/lib:/home/rich/scratch/BeClearRPCClient/tests/simple-audio-file/.:/home/rich/scratch/BeClearRPCClient/build/Release/src]
 0x000000000000000c (INIT)               0x1230
 0x000000000000000d (FINI)               0x24d4

The first shared library listed is one created as part of the local CMake project. The 2nd is brought in via Conan - that’s a path to my local Conan cache. How can I tell CMake to force the linker to not use the full path to the library, because that full path seems to be what’s causing the runtime error.

For reference here’s the CMake that’s building the test executable:

find_package(be-clear-philips-audiofile)

add_executable(AudioFileTest AudioFileTest.c)

target_include_directories(AudioFileTest
    PRIVATE
    .
    ${be-clear-rpc-server_INCLUDE_DIRS}
)

target_link_directories(AudioFileTest
    PRIVATE
    .
)

target_link_libraries(AudioFileTest
    PRIVATE
    RpcClientBeClearMaec
    hexagon-sdk::hexagon-sdk
#    libBeClearAudiofile.so
    be-clear-philips-audiofile::be-clear-philips-audiofile
)

Note the commented out line in the target_link_libraries - if I copy the library from the Conan cache to the current directory and just link it as a raw library then the problem goes away - the elf file shows just the library name without a full path.

I reached out first in the CppLang slack channel for Conan, but the Conan rep that usually can answer all my questions couldn’t help me with this one.

Suggestions or thoughts on what I can try?

Can you provide the output of readelf -d /path/to/libBeClearAudiofile.so? I suspect it is missing a DT_NAME entry which means that the DT_NEEDED entry you get depends on the spelling on the command line. If this is the case, that library needs to set a soname for itself.

1 Like

Definitely - here it is.

rich@doodad:~/.conan/data/be-clear-philips-audiofile/1.2.1/bose-corp/master/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9$ readelf -d ./lib/libBeClearAudiofile.so 

Dynamic section at offset 0x12028 contains 19 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000004 (HASH)               0x180
 0x0000000000000005 (STRTAB)             0x2b80
 0x0000000000000006 (SYMTAB)             0xb10
 0x000000000000000a (STRSZ)              4625 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x221c0
 0x0000000000000002 (PLTRELSZ)           2688 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x4388
 0x0000000000000007 (RELA)               0x4088
 0x0000000000000008 (RELASZ)             768 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x4048
 0x000000006fffffff (VERNEEDNUM)         2
 0x000000006ffffff0 (VERSYM)             0x3d92
 0x000000006ffffff9 (RELACOUNT)          10
 0x0000000000000000 (NULL)               0x0

You’ll need to talk to upstream about giving a real soname to it. If it is CMake, you can do this by setting the library target’s SOVERSION property (usually to an integer, but it’s really upstream’s call).

1 Like

Interesting. I’m still not sure I understand why the behavior is different when I use the same library, copied into the current project’s source folder and linked as a raw library, not a CMake target. I suppose because the linker command has:

-lBeClearAudioFile instead of
/home/rich/.conan/data/be-clear-philips-audiofile/1.2.1/bose-corp/master/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/lib/libBeClearAudiofile.so

and that changes what is in the executable’s elf file on the NEEDED line.

I think I can properly explain this to the vendor, who supplies the library in binary form to us - i.e. we don’t build it. I’m sure they’ll be able to adjust their build for us.

This SO post might help if they have questions: linux - What is the 'soname' option for building shared libraries for? - Stack Overflow