Build Openssl With Rpath

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



Leave a reply



Submit