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 ?
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.The +LIBS="" idea seems interesting. What about a LIBS+="", for appending, as well?