Installing Deviant OpenSSL XS Modules

Installing XS modules that link to OpenSSL can be tricky if you don't have OpenSSL installed in the normal place. I'm using Solaris 10, and I have OpenSSL installed in /usr/sfw.

I was having a problem getting Crypt::OpenSSL::Random, Crypt::OpenSSL::RSA, Crypt::OpenSSL::DSA and Crypt::OpenSSL::Bignum to install.

~> /usr/bin/perl Makefile.PL
Checking if your kit is complete...
Looks good
Note (probably harmless): No library found for -lssl
Note (probably harmless): No library found for -lcrypto
Writing Makefile for Crypt::OpenSSL::Random
~> make
cp Random.pm blib/lib/Crypt/OpenSSL/Random.pm
AutoSplitting blib/lib/Crypt/OpenSSL/Random.pm (blib/lib/auto/Crypt/OpenSSL/Random)
/usr/bin/perl /usr/perl5/site_perl/5.8.4/ExtUtils/xsubpp  -typemap /usr/perl5/5.8.4/lib/ExtUtils/typemap  Random.xs > Random.xsc && mv Random.xsc Random.c
Please specify prototyping behavior for Random.xs (see perlxs manual)
cc -c    -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -xarch=v8 -D_TS_ERRNO -xO3 -xspace -xildoff    -DVERSION=\"0.04\"  -DXS_VERSION=\"0.04\" -KPIC "-I/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE"   Random.c
"Random.xs", line 5: cannot find include file: 
"Random.xs", line 23: warning: implicit function declaration: RAND_bytes
"Random.xs", line 25: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
"Random.xs", line 50: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
"Random.xs", line 71: warning: implicit function declaration: RAND_seed
"Random.xs", line 72: warning: implicit function declaration: RAND_status
"Random.xs", line 87: warning: implicit function declaration: RAND_egd
cc: acomp failed for Random.c
*** Error code 2
make: Fatal error: Command failed for target `Random.o'


It couldn't compile because it didn't find the OpenSSL header files. I neglected to specify the additional include path, which I can do by specifying an INC argument to Makefile.PL.

~> /usr/bin/perl Makefile.PL INC=-I/usr/sfw/include
Checking if your kit is complete...
Looks good
Note (probably harmless): No library found for -lssl
Note (probably harmless): No library found for -lcrypto
Writing Makefile for Crypt::OpenSSL::Random
~> make
cp Random.pm blib/lib/Crypt/OpenSSL/Random.pm
AutoSplitting blib/lib/Crypt/OpenSSL/Random.pm (blib/lib/auto/Crypt/OpenSSL/Random)
/usr/bin/perl /usr/perl5/site_perl/5.8.4/ExtUtils/xsubpp  -typemap /usr/perl5/5.8.4/lib/ExtUtils/typemap  Random.xs > Random.xsc && mv Random.xsc Random.c
Please specify prototyping behavior for Random.xs (see perlxs manual)
cc -c  -I/usr/sfw/include  -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -xarch=v8 -D_TS_ERRNO -xO3 -xspace -xildoff    -DVERSION=\"0.04\"  -DXS_VERSION=\"0.04\" -KPIC "-I/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE"   Random.c
"Random.xs", line 25: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
"Random.xs", line 50: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
Running Mkbootstrap for Crypt::OpenSSL::Random ()
chmod 644 Random.bs
rm -f blib/arch/auto/Crypt/OpenSSL/Random/Random.so
cc  -G Random.o  -o blib/arch/auto/Crypt/OpenSSL/Random/Random.so       \
        \
  
chmod 755 blib/arch/auto/Crypt/OpenSSL/Random/Random.so
cp Random.bs blib/arch/auto/Crypt/OpenSSL/Random/Random.bs
chmod 644 blib/arch/auto/Crypt/OpenSSL/Random/Random.bs
Manifying blib/man3/Crypt::OpenSSL::Random.3
> make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl
1..5
Can't load 'blib/arch/auto/Crypt/OpenSSL/Random/Random.so' for module Crypt::OpenSSL::Random: ld.so.1: perl: fatal: relocation error: file blib/arch/auto/Crypt/OpenSSL/Random/Random.so: symbol RAND_bytes: referenced symbol not found at /usr/perl5/5.8.4/lib/sun4-solaris-64int/DynaLoader.pm line 230.
 at test.pl line 11
Compilation failed in require at test.pl line 11.
BEGIN failed--compilation aborted at test.pl line 11.
not ok 1
*** Error code 255
make: Fatal error: Command failed for target `test_dynamic'


Now it compiles, but failed to link. I neglected to specify the additional lib path, which I can do by passing in a LIBS argument to Makefile.PL.

~> /usr/bin/perl Makefile.PL LIBS=-L/usr/sfw/lib INC=-I/usr/sfw/include
Checking if your kit is complete...
Looks good
Writing Makefile for Crypt::OpenSSL::Random
~> make
cp Random.pm blib/lib/Crypt/OpenSSL/Random.pm
AutoSplitting blib/lib/Crypt/OpenSSL/Random.pm (blib/lib/auto/Crypt/OpenSSL/Random)
/usr/bin/perl /usr/perl5/site_perl/5.8.4/ExtUtils/xsubpp  -typemap /usr/perl5/5.8.4/lib/ExtUtils/typemap  Random.xs > Random.xsc && mv Random.xsc Random.c
Please specify prototyping behavior for Random.xs (see perlxs manual)
cc -c  -I/usr/sfw/include  -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -xarch=v8 -D_TS_ERRNO -xO3 -xspace -xildoff    -DVERSION=\"0.04\"  -DXS_VERSION=\"0.04\" -KPIC "-I/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE"   Random.c
"Random.xs", line 25: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
"Random.xs", line 50: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
Running Mkbootstrap for Crypt::OpenSSL::Random ()
chmod 644 Random.bs
rm -f blib/arch/auto/Crypt/OpenSSL/Random/Random.so
cc  -G Random.o  -o blib/arch/auto/Crypt/OpenSSL/Random/Random.so       \
        \
  
chmod 755 blib/arch/auto/Crypt/OpenSSL/Random/Random.so
cp Random.bs blib/arch/auto/Crypt/OpenSSL/Random/Random.bs
chmod 644 blib/arch/auto/Crypt/OpenSSL/Random/Random.bs
Manifying blib/man3/Crypt::OpenSSL::Random.3
> make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl
1..5
Can't load 'blib/arch/auto/Crypt/OpenSSL/Random/Random.so' for module Crypt::OpenSSL::Random: ld.so.1: perl: fatal: relocation error: file blib/arch/auto/Crypt/OpenSSL/Random/Random.so: symbol RAND_bytes: referenced symbol not found at /usr/perl5/5.8.4/lib/sun4-solaris-64int/DynaLoader.pm line 230.
 at test.pl line 11
Compilation failed in require at test.pl line 11.
BEGIN failed--compilation aborted at test.pl line 11.
not ok 1
*** Error code 255
make: Fatal error: Command failed for target `test_dynamic'


Weird. Still failing to link. It seems to be ignoring what I pass in to the LIBS argument.

This is where I got stuck. I realized that I didn't know how MakeMaker works. I did some Googling for the error and read the ExtUtils::MakeMaker documentation. Then I found this blog post on
Installing Crypt::OpenSSL::RSA on Solaris 10 which told me what I was doing wrong.

Taking a look at Makefile.PL...

~> less Makefile.PL 
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
    'NAME'              => 'Crypt::OpenSSL::Random',
    'VERSION_FROM'      => 'Random.pm', # finds $VERSION
    'PREREQ_PM'         => {}, # e.g., Module::Name => 1.1
    'LIBS'              => ['-lssl -lcrypto'],   # e.g., '-lm' 
    'DEFINE'            => '', # e.g., '-DHAVE_SOMETHING'
    'INC'               => '', # e.g., '-I/usr/include/other'
);


LIBS is already defined. What happens when you pass in a LIBS argument to Makefile.PL? It doesn't append it, it overrides it.

The existing value "-lssl -lcrypto" is important, so we don't want to override the value. Also, in the blog post I mentioned, jad noticed that the ordering of the LIBS arguments is important. So, even if MakeMaker was smart enough to append my additions to LIBS, how would it know to pre-pend vs. post-pend.

So, the solution is to combine the completed LIBS arguments to pass in to Makefile.PL.

~> /usr/bin/perl Makefile.PL LIBS="-L/usr/sfw/lib -lssl -lcrypto" INC=-I/usr/sfw/include
Checking if your kit is complete...
Looks good
Writing Makefile for Crypt::OpenSSL::Random
~> make
cp Random.pm blib/lib/Crypt/OpenSSL/Random.pm
AutoSplitting blib/lib/Crypt/OpenSSL/Random.pm (blib/lib/auto/Crypt/OpenSSL/Random)
/usr/bin/perl /usr/perl5/site_perl/5.8.4/ExtUtils/xsubpp  -typemap /usr/perl5/5.8.4/lib/ExtUtils/typemap  Random.xs > Random.xsc && mv Random.xsc Random.c
Please specify prototyping behavior for Random.xs (see perlxs manual)
cc -c  -I/usr/sfw/include  -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -xarch=v8 -D_TS_ERRNO -xO3 -xspace -xildoff    -DVERSION=\"0.04\"  -DXS_VERSION=\"0.04\" -KPIC "-I/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE"   Random.c
"Random.xs", line 25: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
"Random.xs", line 50: warning: argument #1 is incompatible with prototype:
        prototype: pointer to const char : "/usr/perl5/5.8.4/lib/sun4-solaris-64int/CORE/proto.h", line 520
        argument : pointer to unsigned char
Running Mkbootstrap for Crypt::OpenSSL::Random ()
chmod 644 Random.bs
rm -f blib/arch/auto/Crypt/OpenSSL/Random/Random.so
LD_RUN_PATH="/usr/sfw/lib" cc  -G Random.o  -o blib/arch/auto/Crypt/OpenSSL/Random/Random.so    \
   -L/usr/sfw/lib -lssl -lcrypto        \
  
chmod 755 blib/arch/auto/Crypt/OpenSSL/Random/Random.so
cp Random.bs blib/arch/auto/Crypt/OpenSSL/Random/Random.bs
chmod 644 blib/arch/auto/Crypt/OpenSSL/Random/Random.bs
Manifying blib/man3/Crypt::OpenSSL::Random.3
> make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl
1..5
ok 1
ok 2
ok 3
ok 4
ok 5


This method worked for all of the aformentioned modules without fail.

Additional Question

Now I pose the same question as jad. Is there a way to do this when installing modules using cpan or cpanminus?

Update: I pose the possibility of adding a makepl_args option for cpanminus in cpanm --makepl_args ?

3 Comments

Hmmm... mention this article to mst and see if he's willing to change the EU::MM behavior to prepending the command line arguments to the WriteMakefile arguments? Then o conf makepl_arg "LIBS="..." INC="..."" would work fine in cpan, as long as you made sure that EU::MM was up-to-date.

And yes, the makepl_arg option is where you want to put arguments to Makefile.PL.

(And no, I haven't seen an option for either the CPAN shell or command to pass options in on a one-time basis. Maybe provide a patch to App::CPAN?)

Or... maybe implement a +LIBS="" option for prepending, so as to not break previously established expectations.

Leave a comment

About Jesse Thompson

user-pic I blog about Perl.