How to set --rpath in configure script for openssl
OK. Here is the - very simple - way how to solve it according to 3) from my question.
I ran ./config -h
and got this output:
root => ./config -h
Usage: config [options]
-d Build with debugging when possible.
-t Test mode, do not run the Configure perl script.
-v Verbose mode, show the exact Configure call that is being made.
-h This help.
Any other text will be passed to the Configure perl script.
See INSTALL for instructions.
Operating system: x86_64-whatever-linux2
Configuring for linux-x86_64
The text Any other text will be passed to the Configure perl script.
says it all.
I just added the --rpath
at the end to the config
command which looks now like this:./config --prefix=/FaF/openssl threads shared -Wl,--rpath=/FaF/openssl/lib
Qt5.9.6 do not follow RPATH to search openssl
So the thing is, Qt loads the OpenSSL library as a plugin, and the dynamic linker ld.so
on Linux only takes into account the rpath of the executable and/or shared object that calls dlopen()
. And because Qt itself doesn't have the rpath for your OpenSSL copy set, it won't load it.
The best way around that is (as long as you don't want to recompile Qt yourself with that rpath) to load OpenSSL manually before invoking any Qt function. So add the following to your code at the beginning of main()
:
void* crypto_handle = dlopen("libcrypto.so", RTLD_NOW | RTLD_GLOBAL);
if (!crypto_handle)
std::cerr << "error loading libcrypto.so: " << dlerror() << std::endl;
void* ssl_handle = dlopen("libssl.so", RTLD_NOW | RTLD_GLOBAL);
if (!ssl_handle)
std::cerr << "error loading libssl.so: " << dlerror() << std::endl;
Note that you must load libcrypto.so
before libssl.so
, otherwise libssl.so
won't load, because libssl.so
in your installation doesn't have an rpath set for itself, so it won't find the correct libcypto.so
unless you load that yourself as well.
Further note: technically you could use the official SONAMEs libssl.so.1.0.0
and libcrypto.so.1.0.0
(yes, even for 1.0.2 those are the correct SONAMEs), but your Qt version is compiled against a weird version of OpenSSL that thinks its SONAME has 1.0.2k
as the extension, not 1.0.0
as it should be, so it will only find the libraries by their generic names, and you have to load the libraries by their generic names (libssl.so
, libcrypto.so
) to make the dynamic linker aware that these are aliases.
If both of these are loaded, Qt will be able to work, because then the dynamic linker will see that the libraries in question have already been loaded into the program, and will hence reuse them, without looking for them in the filesystem.
Running your program will then give the following output:
build openssl: OpenSSL 1.0.2k-fips 26 Jan 2017
load openssl: OpenSSL 1.0.2k 26 Jan 2017
That all said: OpenSSL 1.0.2 has not been supported for 2.5 years. And the version you're using, 1.0.2k
is even older, that's from 5.5 years (!) ago. There are several security issues that have been fixed in OpenSSL since, and it is a really bad idea to write new code that relies on such outdated software when it comes to network communication.
Please, please use OpenSSL 1.1, which is still supported until September of next year. Qt has support for that since 5.12. From my experience the upgrade from 5.9 to 5.12 was completely painless. Though ideally I'd suggest that new code should use Qt6.
(Unfortunately not even Qt6 appears to work with OpenSSL 3.0 yet, but hopefully that'll change soon.)
How to build openssl for M1 and for Intel?
Use command lipo
to combine binaries
Compile Intel and ARM versions separately (arm version requires Xcode 12).
export MACOSX_DEPLOYMENT_TARGET=10.9
cp -r openssl-1.1.1p openssl-1.1.1p-arm64
cp -r openssl-1.1.1p openssl-1.1.1p-x86_x64
Build the Intel half
cd openssl-1.1.1p-x86_x64
./Configure darwin64-x86_64-cc shared
make
Build the Arm half
export MACOSX_DEPLOYMENT_TARGET=10.15 /* arm64 only with Big Sur -> minimum might be 10.16 or 11.0 */)
cd ../openssl-1.1.1p-arm64
./Configure enable-rc5 zlib darwin64-arm64-cc no-asm
make
To create universal binary use command lipo:
cd ..
mkdir openssl-mac
lipo -create openssl-1.1.1p-arm64/libcrypto.a openssl-1.1.1p-x86_x64/libcrypto.a -output openssl-mac/libcrypto.a
lipo -create openssl-1.1.1p-arm64/libssl.a openssl-1.1.1p-x86_x64/libssl.a -output openssl-mac/libssl.a
Verify that resulting binary contains both architectures:
file libcrypto.a libssl.a
libcrypto.a: Mach-O universal binary with 2 architectures: [x86_64:current ar archive random library] [arm64]
libcrypto.a (for architecture x86_64): current ar archive random library
libcrypto.a (for architecture arm64): current ar archive random library
libssl.a: Mach-O universal binary with 2 architectures: [x86_64:current ar archive random library] [arm64]
libssl.a (for architecture x86_64): current ar archive random library
libssl.a (for architecture arm64): current ar archive random library
PS: If you plan to use dynamic library combine dylib
files using lipo
and run instal_name_tool
cd openssl-mac
install_name_tool -id '@rpath/libcrypto.1.1.1.dylib' libcrypto.1.1.1.dylib
install_name_tool -id '@rpath/libssl.1.1.dylib' libssl.1.1.dylib
otool -D libssl.1.1.dylib /* to verify */
Result:
libssl.1.1.dylib:
@rpath/libssl.1.1.dylib
How can one build openssl on ubuntu with a specific version of zlib?
The answer turns out to be, you need to set an rpath with a syntax similar to the following. I do mine in a Makefile, which is the reason for the double '$'.
LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib'
Now, I don't necessarily need to do this on the library (openssl) itself. I can do this on the calling executable instead. If the library has no rpath, the rpath on the executable gets used next. In short, I don't need to stress that ldd -r <library>
is returning the wrong path, provided that ldd -r <executable>
returns the correct path.
I can test by library with the following command:
env LD_LIBRARY_PATH=$PWD ldd -r <library>
And once my executable is compiled, I can verify everything like this:
ldd -r <executable>
Long story short, everything is working just fine, don't get hung up on what ldd -r <library>
is returning, just worry about ldd -r <executable>
.
Related Topics
Cannot Connect to the Docker Daemon At Unix:/Var/Run/Docker.Sock. Is the Docker Daemon Running
How to Parse a CSV File in Bash
How to Change the Number of Open Files Limit in Linux
What's the Best Way to Send a Signal to All Members of a Process Group
Static Link of Shared Library Function in Gcc
Better Way to Rename Files Based on Multiple Patterns
Can Windows Containers Be Hosted on Linux
How to Run a Shell Script At Startup
What Does the Number in Parentheses Shown After Unix Command Names in Manpages Mean
Exploring Docker Container'S File System
How to Make a Program Continue to Run After Log Out from Ssh
Best Practices When Running Node.Js With Port 80 (Ubuntu/Linode)