summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/languages-frameworks/perl.xml13
-rw-r--r--pkgs/development/interpreters/perl/MakeMaker-cross.patch17
-rw-r--r--pkgs/development/interpreters/perl/default.nix39
-rw-r--r--pkgs/development/interpreters/perl/setup-hook-cross.sh12
-rw-r--r--pkgs/development/perl-modules/generic/builder.sh2
-rw-r--r--pkgs/development/perl-modules/generic/default.nix5
6 files changed, 81 insertions, 7 deletions
diff --git a/doc/languages-frameworks/perl.xml b/doc/languages-frameworks/perl.xml
index dfb463b99912..7f219b8b09dd 100644
--- a/doc/languages-frameworks/perl.xml
+++ b/doc/languages-frameworks/perl.xml
@@ -177,5 +177,18 @@ you need it.</para>
 
 </section>
 
+<section xml:id="ssec-perl-cross-compilation"><title>Cross-compiling modules</title>
+
+<para>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
+<filename>lib/perl5/site_perl/cross_perl/${perl.version}</filename>.
+</para>
+
+</section>
+
 </section>
 
diff --git a/pkgs/development/interpreters/perl/MakeMaker-cross.patch b/pkgs/development/interpreters/perl/MakeMaker-cross.patch
new file mode 100644
index 000000000000..40626c51f9bd
--- /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 f7324fc6d01a..0fd55bd8d71b 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 000000000000..95aae0b2670f
--- /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 1b8888dd3ceb..937dad971b87 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 9e21a141c728..b33861d83eed 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;
   }
 )