Why does Crypt::SSLeay fail to build under Strawberry Perl?

After a comment on my blog attracted my attention to some interesting failures when trying to build Crypt::SSLeay with Strawberry Perl, I was perplexed.

I don’t really use Strawberry. I have always used either ActivePerl, or built my own perl, depending on my taste for experimentation. So, I went over to Strawberry Perl’s web site, and downloaded their latest portable 64-bit distribution, unzipped, and tried to install Crypt::SSLeay.

And, I got a similar failure at link stage:

dlltool --def SSLeay.def --output-exp dll.exp
g++.exe -o blib\arch\auto\Crypt\SSLeay\SSLeay.dll -Wl,
    --base-file -Wl,dll.base -
mdll -s -L"C:\…\strawberry\perl\lib\CORE"
    -L"C:\…\strawberry\c\lib" SSLeay.o
    C:\…\strawberry\perl\lib\CORE\libperl518.a
    C:\…\strawberry\c\lib\libssl32.a
    C:\…\strawberry\c\lib\libssleay32.a
    C:\…\strawberry\c\lib\libz.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libmoldname.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libkernel32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libuser32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libgdi32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libwinspool.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libcomdlg32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libadvapi32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libshell32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libole32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\liboleaut32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libnetapi32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libuuid.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libws2_32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libmpr.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libwinmm.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libversion.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libodbc32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libodbccp32.a
    C:\…\strawberry\c\x86_64-w64-mingw32\lib\libcomctl32.a
    dll.exp
SSLeay.o:SSLeay.c:(.text+0x403):
 undefined reference to `X509_get_issuer_name'
SSLeay.o:SSLeay.c:(.text+0x410):
 undefined reference to `X509_NAME_oneline'
SSLeay.o:SSLeay.c:(.text+0x42f):
 undefined reference to `CRYPTO_free'
SSLeay.o:SSLeay.c:(.text+0x573):
 undefined reference to `X509_get_subject_name'
SSLeay.o:SSLeay.c:(.text+0x580):
 undefined reference to `X509_NAME_oneline'
SSLeay.o:SSLeay.c:(.text+0x59f):
 undefined reference to `CRYPTO_free'
SSLeay.o:SSLeay.c:(.text+0x6d7):
 undefined reference to `X509_free'
SSLeay.o:SSLeay.c:(.text+0x2756):
 undefined reference to `d2i_PKCS12_fp'
SSLeay.o:SSLeay.c:(.text+0x2798):
 undefined reference to `PKCS12_parse'
SSLeay.o:SSLeay.c:(.text+0x27be)
: undefined reference to `EVP_PKEY_free'
SSLeay.o:SSLeay.c:(.text+0x27e0):
 undefined reference to `X509_free'
SSLeay.o:SSLeay.c:(.text+0x27e8):
 undefined reference to `PKCS12_free'
SSLeay.o:SSLeay.c:(.text+0x314e):
 undefined reference to `RAND_load_file'
SSLeay.o:SSLeay.c:(.text+0x3211):
 undefined reference to `OPENSSL_add_all_algorithms_noconf'
SSLeay.o:SSLeay.c:(.text+0x321b):
 undefined reference to `ERR_load_crypto_strings'
SSLeay.o:SSLeay.c:(.text+0x3270):
 undefined reference to `RAND_seed'
SSLeay.o:SSLeay.c:(.text+0x3316):
 undefined reference to `ERR_get_error'
SSLeay.o:SSLeay.c:(.text+0x3397):
 undefined reference to `ERR_get_error'
SSLeay.o:SSLeay.c:(.text+0x33b0):
 undefined reference to `ERR_error_string'

*Sigh!*

So, the libraries we want to link to are there, but …

At this point, I am actually using Devel::CheckLib to check if compiling programs against the requested libraries succeeds, so I know the libraries are there. Why is linking failing?

I mean, look at this:

C:\…\strawberry\c\lib> strings libeay32.a
   | perl -ne "print if /X509_NAME_oneline/"
X509_NAME_oneline
__imp_X509_NAME_oneline
X509_NAME_oneline
X509_NAME_oneline
__imp_X509_NAME_oneline

So, at least superficially, it looks like everything is there. Why the failures?

Also, it turns out the January 2014 release of Strawberry Perl (/w perl 5.18) comes with OpenSSL 1.0.1e. Is there a better excuse to build OpenSSL from scratch?

But, that would require putting together a whole MinGW environment.

Of course, don’t use outdated versions of OpenSSL. But, the solution to the linking problem was much simpler. The candidate library list I am using was ssl crypto ssl32 ssleay32 libeay32 z. Well, using GCC, libeay32.a would be linked by specifying -leay32. If you use -llibeay32, the linker will look for liblibeay32.a.

Therefore, changing that list of libraries to ssl crypto ssl32 ssleay32 eay32 z works for Strawberry. It does, however, fail when I try it using Windows SDK 7.1 build environment. Therefore, the new list of candidate libraries is ssl crypto ssl32 ssleay32 eay32 libeay32 z. I’ll push the change to CPAN and GitHub.