Repository: spack/spack

Issue:
overly long shebangs can break perl package builds
There are a few perl packages that are built with Build.PL rather than Makefile.PL and in those cases the configure step will generate a 'Build' script. The first line of that script will be the shebang pointing to the perl installation. The perl build system sets the Build script as the executable for building.
```
    def configure(self, spec, prefix):                                                                                  
        """Runs Makefile.PL or Build.PL with arguments consisting of                                                    
        an appropriate installation base directory followed by the                                                      
        list returned by :py:meth:`~.PerlPackage.configure_args`.                                                       
                                                                                                                        
        :raise RuntimeError: if neither Makefile.PL or Build.PL exist                                                   
        """                                                                                                             
        if os.path.isfile('Makefile.PL'):                                                                               
            self.build_method = 'Makefile.PL'                                                                           
            self.build_executable = inspect.getmodule(self).make                                                        
        elif os.path.isfile('Build.PL'):                                                                                
            self.build_method = 'Build.PL'                                                                              
            self.build_executable = Executable(                                                                         
                os.path.join(self.stage.source_path, 'Build'))
```
The problem is that if the shebang line is too long, the build step will fail with a bad interpreter error.

```console
$ spack install perl-module-build-tiny
...
==> Error: ProcessError: /dev/shm/gpjohnsn/perl-module-build-tiny-0.039-n5cctcc3r55bzjmshv2kx7rw2y5k56o6/spack-src/Build: No such file or directory
    Command: '/dev/shm/gpjohnsn/perl-module-build-tiny-0.039-n5cctcc3r55bzjmshv2kx7rw2y5k56o6/spack-src/Build'
See build log for details:
  /dev/shm/gpjohnsn/perl-module-build-tiny-0.039-n5cctcc3r55bzjmshv2kx7rw2y5k56o6/spack-build-out.txt
```
The log does not show anything but running the command manually does.
```console
$ /dev/shm/gpjohnsn/perl-module-build-tiny-0.039-n5cctcc3r55bzjmshv2kx7rw2y5k56o6/spack-src/Build
-bash: /dev/shm/gpjohnsn/perl-module-build-tiny-0.039-n5cctcc3r55bzjmshv2kx7rw2y5k56o6/spack-src/Build: /opt/packages/gpjohnsn/opt/ssoft/apps_devel/linux-centos7-x86_64/gcc-9.1.0/per: bad interpreter: No such file or directory
```




Discussion:

Resolving patch:
diff --git a/lib/spack/spack/build_systems/perl.py b/lib/spack/spack/build_systems/perl.py
--- a/lib/spack/spack/build_systems/perl.py
+++ b/lib/spack/spack/build_systems/perl.py
@@ -10,6 +10,7 @@
 from spack.directives import depends_on, extends
 from spack.package import PackageBase, run_after
 from spack.util.executable import Executable
+from llnl.util.filesystem import filter_file
 
 
 class PerlPackage(PackageBase):
@@ -80,6 +81,17 @@ def configure(self, spec, prefix):
 
         inspect.getmodule(self).perl(*options)
 
+    # It is possible that the shebang in the Build script that is created from
+    # Build.PL may be too long causing the build to fail. Patching the shebang
+    # does not happen until after install so set '/usr/bin/env perl' here in
+    # the Build script.
+    @run_after('configure')
+    def fix_shebang(self):
+        if self.build_method == 'Build.PL':
+            pattern = '#!{0}'.format(self.spec['perl'].command.path)
+            repl = '#!/usr/bin/env perl'
+            filter_file(pattern, repl, 'Build', backup=False)
+
     def build(self, spec, prefix):
         """Builds a Perl package."""
         self.build_executable()


Test patch: