Linking in OpenSSL libcrypto Statically

I have a C++ program which includes lots of libraries, including openssl libcrypto. In fact, the g++ switches are:

-lxml2 -lcrypto -lcurl etc.

The problem is that when I try to run it on a different flavor of Linux, it complains that it cannot load libcrypto.so.8. I did some research and learned about the difference between static and shared libraries, but can't quite figure out what steps to take to compile the libcrypto library in such a way that everything goes into the executable so that my program can be portable. Thanks in advance for any help you can give me.

Brandon

You need to compile/link with -lcrypto -L dir of libcrypto.a to get a static link. If only .so is available, it will go dynamic.

It is portable in two pieces or if the far end has a compatible .so, hopefully one that is not hacked! It saves space, disk and RAM, increases cache hits as all on one host use same lib at once, and takes little time to dynamically link.

Thanks. Can you give me an example of what the command would look like?

Depends on the compiler, usually in a make file.

gcc -o yourname -Bstatic -L<dir-of-libcrypto.a> -lcrypto . . . yourfile.c
1 Like

Thanks, but I have one point of confusion. How can I make this apply only to the one library libcrypto and not to any of the others in the list?

Just put -Bdynamic before mentioning them, order is important left to right.

Ah, lcrypto is it? Thanks! I always wondered why I couldn't compile ssl-using things statically when giving -static -lssl...

-lxxx means search for libxxx.a if static and libxxx.so if dynamic. It is just shorthand for the library name. traditionally, never a space.

Actually, I downloaded libcrypto.a and then wrote:

g++ -o MyProg -lxxx -lyyy -lzzz -Bstatic -lcrypto

yet when I went to run it on another box, it still complained that it couldn't find libcrypto.so.8. How can this be?

Don't think -Bstatic works quite right in gcc, it's just a compatibility option borrowed from the flags of some esoteric compiler.

You don't need to link in a .a as a library, you can use it just like an object file. (that's what an .a is, essentially -- except it can have more than one .o in it)

gcc myprogram.c /usr/lib/libcrypto.a -o myprogram

It will dynamically link the C runtimes and such dynamically but pull static functions from libcrypto.a as needed, just like it would another .c or .o file.

If you don't have libcrypto.a, you may need to install openssl-dev or whatever your distro hides it under.

You might need -L to find it, too -- no find but dynamic found = dynamic. Hide the dynamic one.

If -Bstatic does not work, grep down the man page for static.

These are really ld options, I believe. Linker ld, language independent, checks out the .o from .a to go with your .o and makes the executable.

Thanks, guys. I think I'll try to treat libcrypto.a as though it were one of my object files. I hope that something works soon, because otherwise, I'll have to find the libcrypto source and include it in my product. My company needs my work to go out the door soon. Again, thanks.

That's all that's in an .a file -- several .o files.

Here is the result:

g++ -o Encode Encode06.o libcrypto.a

libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0xafb): undefined reference to `dlopen'
libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0xb0f): undefined reference to `dlsym'
libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0xb25): undefined reference to `dladdr'
libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0xb31): undefined reference to `dlclose'
libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0xb83): undefined reference to `dlclose'
collect2: ld returned 1 exit status

man dlopen says to link with -ldl.

It indicates that you need to include libdl

Those may be in another library you need to include. dlopen(3) - Linux man page

When I try to link to libcrypto.a, it complains that RSA_generate_key and DH_generate_parameters are undefined references. I am including "-lssl."

If this had worked, I would have next tried to link in libssl, statically, but it didn't because the ssl libraries don't contain those two parameters.

Any idea what library I can link in to define them?

libssl.a

Do you mean that using libssl.a will work, even though -lssl, which presumably chose the shared version, didn't?