diff --git a/doc/languages-frameworks/perl.xml b/doc/languages-frameworks/perl.xml index dfb463b9991..7f219b8b09d 100644 --- a/doc/languages-frameworks/perl.xml +++ b/doc/languages-frameworks/perl.xml @@ -177,5 +177,18 @@ you need it. +
Cross-compiling modules + +Nixpkgs has experimental support for cross-compiling Perl +modules. In many cases, it will just work out of the box, even for +modules with native extensions. Sometimes, however, the Makefile.PL +for a module may (indirectly) import a native module. In that case, +you will need to make a stub for that module that will satisfy the +Makefile.PL and install it into +lib/perl5/site_perl/cross_perl/${perl.version}. + + +
+ diff --git a/pkgs/development/interpreters/perl/MakeMaker-cross.patch b/pkgs/development/interpreters/perl/MakeMaker-cross.patch new file mode 100644 index 00000000000..40626c51f9b --- /dev/null +++ b/pkgs/development/interpreters/perl/MakeMaker-cross.patch @@ -0,0 +1,17 @@ +diff -Naur a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm +--- a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm 2017-06-30 17:03:20.000000000 -0400 ++++ b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm 2018-02-28 10:06:37.031237946 -0500 +@@ -1267,7 +1267,12 @@ + my $value = shift; + return $value if $UNDER_CORE; + my $tvalue = ''; +- require B; ++ eval { ++ require B; ++ }; ++ if ($@) { ++ return $tvalue; ++ } + my $sv = B::svref_2object(\$value); + my $magic = ref($sv) eq 'B::PVMG' ? $sv->MAGIC : undef; + while ( $magic ) { diff --git a/pkgs/development/interpreters/perl/default.nix b/pkgs/development/interpreters/perl/default.nix index f7324fc6d01..0fd55bd8d71 100644 --- a/pkgs/development/interpreters/perl/default.nix +++ b/pkgs/development/interpreters/perl/default.nix @@ -1,4 +1,6 @@ -{ lib, stdenv, fetchurlBoot, buildPackages, enableThreading ? stdenv ? glibc, fetchpatch }: +{ lib, stdenv, fetchurlBoot, buildPackages +, enableThreading ? stdenv ? glibc, fetchpatch, makeWrapper +}: with lib; @@ -29,7 +31,8 @@ let }; # TODO: Add a "dev" output containing the header files. - outputs = [ "out" "man" "devdoc" ]; + outputs = [ "out" "man" "devdoc" ] ++ + stdenv.lib.optional crossCompiling "dev"; setOutputFlags = false; patches = @@ -45,7 +48,8 @@ let }) ++ optional stdenv.isSunOS ./ld-shared.patch ++ optional stdenv.isDarwin ./cpp-precomp.patch - ++ optional (stdenv.isDarwin && versionAtLeast version "5.24") ./sw_vers.patch; + ++ optional (stdenv.isDarwin && versionAtLeast version "5.24") ./sw_vers.patch + ++ optional crossCompiling ./MakeMaker-cross.patch; postPatch = '' pwd="$(type -P pwd)" @@ -117,6 +121,28 @@ let if stdenv.cc.cc or null != null then stdenv.cc.cc else "/no-such-path" }" /no-such-path \ --replace "$man" /no-such-path + '' + stdenv.lib.optionalString crossCompiling + '' + mkdir -p $dev/lib/perl5/cross_perl/${version} + for dir in cnf/{stub,cpan}; do + cp -r $dir/* $dev/lib/perl5/cross_perl/${version} + done + + mkdir -p $dev/bin + install -m755 miniperl $dev/bin/perl + + export runtimeArch="$(ls $out/lib/perl5/site_perl/${version})" + # wrapProgram should use a runtime-native SHELL by default, but + # it actually uses a buildtime-native one. If we ever fix that, + # we'll need to fix this to use a buildtime-native one. + # + # Adding the arch-specific directory is morally incorrect, as + # miniperl can't load the native modules there. However, it can + # (and sometimes needs to) load and run some of the pure perl + # code there, so we add it anyway. When needed, stubs can be put + # into $dev/lib/perl5/cross_perl/${version}. + wrapProgram $dev/bin/perl --prefix PERL5LIB : \ + "$dev/lib/perl5/cross_perl/${version}:$out/lib/perl5/${version}:$out/lib/perl5/${version}/$runtimeArch" ''; # */ meta = { @@ -139,7 +165,7 @@ let sha256 = "1gh8w9m5if2s0lrx2x8f8grp74d1l6d46m8jglpjm5a1kf55j810"; }; - depsBuildBuild = [ buildPackages.stdenv.cc ]; + depsBuildBuild = [ buildPackages.stdenv.cc makeWrapper ]; postUnpack = '' unpackFile ${perl-cross-src} @@ -150,6 +176,11 @@ let ''; configurePlatforms = [ "build" "host" "target" ]; + + inherit version; + + # TODO merge setup hooks + setupHook = ./setup-hook-cross.sh; }); in rec { perl = perl524; diff --git a/pkgs/development/interpreters/perl/setup-hook-cross.sh b/pkgs/development/interpreters/perl/setup-hook-cross.sh new file mode 100644 index 00000000000..95aae0b2670 --- /dev/null +++ b/pkgs/development/interpreters/perl/setup-hook-cross.sh @@ -0,0 +1,12 @@ +addPerlLibPath () { + addToSearchPath PERL5LIB $1/lib/perl5/site_perl/@version@ + addToSearchPath PERL5LIB $1/lib/perl5/site_perl/cross_perl/@version@ + # Adding the arch-specific directory is morally incorrect, as + # miniperl can't load the native modules there. However, it can + # (and sometimes needs to) load and run some of the pure perl + # code there, so we add it anyway. When needed, stubs can be put + # into $1/lib/perl5/site_perl/cross_perl/@version@ + addToSearchPath PERL5LIB $1/lib/perl5/site_perl/@version@/@runtimeArch@ +} + +addEnvHooks "$targetOffset" addPerlLibPath diff --git a/pkgs/development/perl-modules/generic/builder.sh b/pkgs/development/perl-modules/generic/builder.sh index 1b8888dd3ce..937dad971b8 100644 --- a/pkgs/development/perl-modules/generic/builder.sh +++ b/pkgs/development/perl-modules/generic/builder.sh @@ -22,7 +22,7 @@ preConfigure() { fi done - perl Makefile.PL PREFIX=$out INSTALLDIRS=site $makeMakerFlags + perl Makefile.PL PREFIX=$out INSTALLDIRS=site $makeMakerFlags PERL=$(type -P perl) FULLPERL=$perl/bin/perl } diff --git a/pkgs/development/perl-modules/generic/default.nix b/pkgs/development/perl-modules/generic/default.nix index 9e21a141c72..b33861d83ee 100644 --- a/pkgs/development/perl-modules/generic/default.nix +++ b/pkgs/development/perl-modules/generic/default.nix @@ -1,6 +1,6 @@ perl: -{ buildInputs ? [], name, ... } @ attrs: +{ nativeBuildInputs ? [], name, ... } @ attrs: perl.stdenv.mkDerivation ( { @@ -27,6 +27,7 @@ perl.stdenv.mkDerivation ( { name = "perl-" + name; builder = ./builder.sh; - buildInputs = buildInputs ++ [ perl ]; + nativeBuildInputs = nativeBuildInputs ++ [ (perl.dev or perl) ]; + inherit perl; } )