Help with shared libraries on Linux.

My application builds and links with Qt6 picking up the Qt .so files because CMake builds some rpath “magic” into the executable when linking so that the libraries are picked up even though they are not listed in /etc/ld.so.conf.

I don’t use Qt6Network directly.

When I add calls into another .so that requires Qt6Network, and add it to target_link_libraries, it all goes to pot, giving me:
/home/amonra/.vs/DSS/out/build/DeepSkyStackerLive/DeepSkyStackerLive: error while loading shared libraries: libQt6Network.so.6: cannot open shared object file: No such file or directory

That external library is built using CMake and installed as /usr/local/lib/libSmtpMime.so.2. Its CMakeLists.txt says:

find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network REQUIRED)

qt_add_library(${PROJECT_NAME} SHARED
    emailaddress.cpp
    : omitted
)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Network)

set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH “${ORIGIN}”)

What to I need to do to my project to be able to run the executable a) from the build directory and b) after installation.

I’m totally confused by this rpath stuff (new to Linux).

PS If this should be in Usage, please move it…

This looks wrong. CMake will see the ${ORIGIN} and try to evaluate it as a CMake variable, and that’s probably going to be an empty string. You need to specify it without the curly braces:

set(CMAKE_INSTALL_RPATH "$ORIGIN")

Of course, that will only help if the library you’re wanting to find is in the same directory as the binary that needs it, but I assume that’s the situation you are creating, or at least trying to create.

That’s not MY script - it belongs to the library.

I’ll report it

I changed their cmake file as you suggested. When I ran the install I saw:

– Set non-toolchain portion of runtime path of “/usr/local/lib/libSmtpMime.so.2.0” to “”

Is that what you would expect to see with the change you suggested?

I know I probably shouldn’t doubt the author of Professional CMake, but shouldn’t that be:

SET(CMAKE_INSTALL_RPATH "$\{ORIGIN\}")

Many thanks
David

I changed the build of the .so in question as suggested and ran its install. The files libSmtpMime.so.2 and libSmtpMime.so.2.0 were copied to my install dir from /usr/local/lib by qt6_deploy_runtime_dependencies.

All the libQt6xxxxx.so files are this directory. But:

amonra@styx:~/.vs/DSS/x64/Linux/Debug$ ldd libSmtpMime.so
	linux-vdso.so.1 (0x00007ffdb7db9000)
	libQt6Network.so.6 => not found
	libQt6Core.so.6 => not found
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f996452e000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f996450a000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f99642e1000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f99641f8000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f99647f0000)
amonra@styx:~/.vs/DSS/x64/Linux/Debug$

From what you said in your reply the other day I thought this should pick up the libs.

Clearly something is either amiss with their CMakeLists.txt content, or something else is wrong.

amonra@styx:~/.vs/DSS/x64/Linux/Debug$ readelf -d DeepSkyStacker | head -20

Dynamic section at offset 0xe8efe0 contains 39 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Widgets.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Gui.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libGLX.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libOpenGL.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Network.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Core.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgomp.so.1]
 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]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN:$ORIGIN/]
 0x000000000000000c (INIT)               0x10e000
 0x000000000000000d (FINI)               0xa01e04
 0x0000000000000019 (INIT_ARRAY)         0xe0f9a0
 0x000000000000001b (INIT_ARRAYSZ)       536 (bytes)
amonra@styx:~/.vs/DSS/x64/Linux/Debug$ readelf -d libSmtpMime.so.2 | head -20   
Dynamic section at offset 0x3dc98 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Network.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Core.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libSmtpMime.so.2]
 0x000000000000000c (INIT)               0x1b000
 0x000000000000000d (FINI)               0x32124
 0x0000000000000019 (INIT_ARRAY)         0x3e2a8
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x3e2b8
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2f0
 0x0000000000000005 (STRTAB)             0x8160
 0x0000000000000006 (SYMTAB)             0x1d88
 0x000000000000000a (STRSZ)              48634 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
amonra@styx:~/.vs/DSS/x64/Linux/Debug$

D.

On Linux, you can run readelf -d <binary-to-analyze> and look at any RUNPATH or RPATH entries. That should tell you what is ending up being embedded in each binary. That should at least help narrow down where to look for something behaving differently to what you expected.

EDIT: Sorry, just saw this is exactly what you did in your last post, which I skipped through too quickly.

It’s not the *.so files you need at run time, it’s the *.so.X where X is some number. You need to find an exact match for what is listed as the NEEDED entries of a binary in the readelf -d output. The *.so files are for the build-time linker, and even then will only be needed if you’re relying on linker search paths (and CMake tries hard to avoid that). The run time loader will look for the NEEDED files, and those file names should match the SONAME embedded in each of those libraries too.

No, as I tried to mention in my earlier comment, the $ORIGIN is for the run time loader, not CMake. The run time loader understands $ORIGIN, I don’t know for sure if it understands ${ORIGIN} (it probably does). Either way, CMake does not understand $ORIGIN as anything to substitute and leaves it alone, so you may as well just use that. Then you don’t have to mess around with escaping.

All the libQt6xxx.so.??? files are present and correct. The issue is with libSmtpMime.so.2.0 which DOES NOT HAVE an RUNPATH entry.

The CMakeLists.txt file for building that library says (now):

set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)

but when I re-run the CMake, do a ninja clean, ninja, sudo ninja install, the install step says (as I said earlier):

amonra@styx:~/Downloads/SmtpClient-for-Qt/build$ sudo ninja install
[0/1] Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/libSmtpMime.so.2.0
-- Installing: /usr/local/lib/libSmtpMime.so.2
-- Set non-toolchain portion of runtime path of "/usr/local/lib/libSmtpMime.so.2.0" to ""

Even though the cmake file says to put the origin stuff there when installing, it is simply wiping it out :frowning:

amonra@styx:~/Downloads/SmtpClient-for-Qt/build$ cmake --version
cmake version 3.31.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).
amonra@styx:~/Downloads/SmtpClient-for-Qt/build$ ninja --version
1.10.1
amonra@styx:~/Downloads/SmtpClient-for-Qt/build$

Let’s eliminate some things. Rather than installing to /usr/local/lib and having to use sudo, let’s try installing to some temporary location that doesn’t need admin privileges. Please wipe your build directory, build again from scratch, and instead of sudo ninja install, please do cmake --install . --prefix staging (from the top level build directory). You should see the project installed to a staging subdirectory of your build directory.

It might also be useful if you can attach the cmake_install.cmake file, the one that installs libSmtpMime.so.2 (you may have to look in subdirectories for the right one).

Here’s the console session:

amonra@styx:~/Downloads/SmtpClient-for-Qt$ mkdir build
amonra@styx:~/Downloads/SmtpClient-for-Qt$ cmake -B ./build -G Ninja -DQT_VERSION_MAJOR=6 -DCMAKE_INSTALL_PREFIX:STRING="/usr/local" -DCMAKE_PREFIX_PATH:STRING="/opt/Qt/6.8.0/gcc_64"
-- The C compiler identification is GNU 13.1.0
-- The CXX compiler identification is GNU 13.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Performing Test HAVE_STDATOMIC
-- Performing Test HAVE_STDATOMIC - Success
-- Found WrapAtomic: TRUE
USINGQt6
-- Found OpenGL: /usr/lib/x86_64-linux-gnu/libOpenGL.so
-- Found WrapOpenGL: TRUE
-- Found XKB: /usr/lib/x86_64-linux-gnu/libxkbcommon.so (found suitable version "1.4.0", minimum required is "0.5.0")
-- Could NOT find WrapVulkanHeaders (missing: Vulkan_INCLUDE_DIR)
-- Configuring done (0.6s)
-- Generating done (0.0s)
-- Build files have been written to: /home/amonra/Downloads/SmtpClient-for-Qt/build
amonra@styx:~/Downloads/SmtpClient-for-Qt$ cd build
amonra@styx:~/Downloads/SmtpClient-for-Qt/build$ ninja
[46/46] Linking CXX executable demos/demo2/demo2
amonra@styx:~/Downloads/SmtpClient-for-Qt/build$ cmake --install . --prefix staging
-- Install configuration: ""
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/lib/libSmtpMime.so.2.0
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/lib/libSmtpMime.so.2
-- Set non-toolchain portion of runtime path of "staging/lib/libSmtpMime.so.2.0" to ""
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/lib/libSmtpMime.so
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/SmtpMime
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/emailaddress.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimeattachment.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimefile.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimehtml.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimeinlinefile.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimemessage.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimepart.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimetext.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/smtpclient.h
-- Up-to-date: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/SmtpMime
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/quotedprintable.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimemultipart.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/smtpmime_global.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimecontentencoder.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimebase64encoder.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimeqpencoder.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimeqpformatter.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimebase64formatter.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimecontentformatter.h
-- Installing: /home/amonra/Downloads/SmtpClient-for-Qt/build/staging/include/smtpmime/mimebytearrayattachment.h
amonra@styx:~/Downloads/SmtpClient-for-Qt/build$

I’ll attach the file you asked for, looks like it is still stripping out RUNPATH
cmake_install.cmake (4.4 KB)

 readelf -d libSmtpMime.so.2 | head -20

Dynamic section at offset 0x3dc98 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Network.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Core.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libSmtpMime.so.2]
 0x000000000000000c (INIT)               0x1b000
 0x000000000000000d (FINI)               0x32124
 0x0000000000000019 (INIT_ARRAY)         0x3e2a8
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x3e2b8
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2f0
 0x0000000000000005 (STRTAB)             0x8160
 0x0000000000000006 (SYMTAB)             0x1d88
 0x000000000000000a (STRSZ)              48634 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
amonra@styx:~/Downloads/SmtpClient-for-Qt/build/staging/lib$

There’s something strange about the way the SmtpClient target is being defined. I suspect something is clearing out or changing some of its target properties after you’ve set it to what you want. You could try checking the values of some properties at the very end of the top level CMakeLists.txt to see if they still hold the values you expected at that point. I’d check any of the target properties that include RPATH in their name.

You can DL the entire thing from: https://github.com/bluetiger9/SmtpClient-for-Qt.

I’m off to bed now and will look in the morning

This seems to say it all:

Invoke add_sub-directory(src)
At end of src/CMakeLists.txt
CMAKE_INSTALL_RPATH: $ORIGIN
After add_subdirectory(src)
CMAKE_INSTALL_RPATH:

The CMAKE_INSTALL_RPATH variable only affects targets created after the variable is set. In other words, it’s the value of that variable at the point add_library() or add_executable() is called that matters. Setting CMAKE_INSTALL_RPATH after those calls won’t affect those targets.

If CMAKE_INSTALL_RPATH is being set in src/CMakeLists.txt rather than the top level CMakeLists.txt file, then it won’t be visible in the top level CMakeLists.txt file. This is normal variable scope behavior.

Normally, you would set CMAKE_INSTALL_RPATH in the top level CMakeLists.txt file, and before any calls to add_subdirectory() or any other command that might result in targets being created. Then it would apply to the whole project consistently.

1 Like

And just to make things worse those set commands were after the add_lbrary, so wouldn’t have been applied to it anyway :frowning: .

After moving the set statements into the top level CMake file before the add_subdirectory commands:

readelf -d libSmtpMime.so.2 | head -20

Dynamic section at offset 0x3dc98 contains 30 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Network.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Core.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libSmtpMime.so.2]
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN]
 0x000000000000000c (INIT)               0x1b000
 0x000000000000000d (FINI)               0x32124
 0x0000000000000019 (INIT_ARRAY)         0x3e2a8
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x3e2b8
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2f0
 0x0000000000000005 (STRTAB)             0x8160
 0x0000000000000006 (SYMTAB)             0x1d88
 0x000000000000000a (STRSZ)              48616 (bytes)

Thank you ever so much for all your help.
D.