Repository: spack/spack

Issue:
Installation issue: php
### Spack version
```console
$ spack --version
0.14.0-245-847d5d3
```

### Steps to reproduce the issue
NB: I had to apply the fixes in #15435 and updated the version to 7.4.4 to get the build to work without errors on sqlite3.

I followed @adamjstewart's suggestion in #15435 to run the install with `-d` so the following output is long, though limited to the failing steps. It's certainly an issue with the shebang
fixup, but I can't track down which file(s) are causing the issue. If anyone can give me hints, happy to fix/track down further

```console
$ spack -d install php
...
==> [2020-03-18-14:08:46.269623, 23586] Warning: Module file already exists : skipping creation
file : /storage/epp2/epp_software/spack-devel/share/spack/modules/linux-centos7-skylake/php-7.4.4-gcc-9.3.0-wtyw6jf
spec : php@7.4.4%gcc@9.3.0 arch=linux-centos7-skylake ^autoconf@2.69%gcc@9.3.0 arch=linux-centos7-skylake ^automake@1.16.1%gcc@9.3.0 arch=linux-centos7-skylake ^bison@3.4.2%gcc@9.3.0 patches=89aa362716d898edd0b5c6ae4208dc1b6992887774848a09e8021afd676f7d61 arch=linux-centos7-skylake ^bzip2@1.0.8%gcc@9.3.0+shared arch=linux-centos7-skylake ^diffutils@3.7%gcc@9.3.0 arch=linux-centos7-skylake ^findutils@4.6.0%gcc@9.3.0 patches=84b916c0bf8c51b7e7b28417692f0ad3e7030d1f3c248ba77c42ede5c1c5d11e,bd9e4e5cc280f9753ae14956c4e4aa17fe7a210f55dd6c84aa60b12d106d47a2 arch=linux-centos7-skylake ^flex@2.6.4%gcc@9.3.0+lex patches=09c22e5c6fef327d3e48eb23f0d610dcd3a35ab9207f12e0f875701c677978d3 arch=linux-centos7-skylake ^gettext@0.20.1%gcc@9.3.0+bzip2+curses+git~libunistring+libxml2+tar+xz arch=linux-centos7-skylake ^help2man@1.47.11%gcc@9.3.0 arch=linux-centos7-skylake ^libiconv@1.16%gcc@9.3.0 arch=linux-centos7-skylake ^libsigsegv@2.12%gcc@9.3.0 arch=linux-centos7-skylake ^libtool@2.4.6%gcc@9.3.0 arch=linux-centos7-skylake ^libxml2@2.9.9%gcc@9.3.0~python arch=linux-centos7-skylake ^m4@1.4.18%gcc@9.3.0 patches=3877ab548f88597ab2327a2230ee048d2d07ace1062efe81fc92e91b7f39cd00,fc9b61654a3ba1a8d6cd78ce087e7c96366c290bc8d2c299f09828d793b853c8 +sigsegv arch=linux-centos7-skylake ^ncurses@6.2%gcc@9.3.0~symlinks+termlib arch=linux-centos7-skylake ^perl@5.16.3%gcc@9.3.0+cpanm patches=0eac10ed90aeb0459ad8851f88081d439a4e41978e586ec743069e8b059370ac +shared+threads arch=linux-centos7-skylake ^pkgconf@1.6.3%gcc@9.3.0 arch=linux-centos7-skylake ^re2c@1.2.1%gcc@9.3.0 arch=linux-centos7-skylake ^readline@8.0%gcc@9.3.0 arch=linux-centos7-skylake ^sqlite@3.30.1%gcc@9.3.0~column_metadata+fts~functions~rtree arch=linux-centos7-skylake ^tar@1.32%gcc@9.3.0 arch=linux-centos7-skylake ^texinfo@6.5%gcc@9.3.0 patches=12f6edb0c6b270b8c8dba2ce17998c580db01182d871ee32b7b6e4129bd1d23a,1732115f651cff98989cb0215d8f64da5e0f7911ebf0c13b064920f088f2ffe1 arch=linux-centos7-skylake ^xz@5.2.4%gcc@9.3.0 arch=linux-centos7-skylake ^zlib@1.2.11%gcc@9.3.0+optimize+pic+shared arch=linux-centos7-skylake
==> [2020-03-18-14:08:46.605448, 23586] WRITE LOCK (spack-stage-php-7.4.4-wtyw6jfmd4h7jwbgg6ujc6asmxlf2roa): /tmp/username/spack-stage/.lock[6107926064061561343:1] [Releasing] 
==> [2020-03-18-14:08:46.605571, 23586] WRITE LOCK (spack-stage-php-7.4.4-wtyw6jfmd4h7jwbgg6ujc6asmxlf2roa): /tmp/username/spack-stage/.lock[6107926064061561343:1] [Released at 14:08:46.605551] 
==> [2020-03-18-14:08:46.616149, 23523] Error: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte

/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py:818, in child_process:
        815            tb_string = traceback.format_exc()
        816
        817            # build up some context from the offending package so we can
  >>    818            # show that, too.
        819            package_context = get_package_context(tb)
        820
        821            build_log = None

See build log for details:
  /tmp/username/spack-stage/spack-stage-php-7.4.4-wtyw6jfmd4h7jwbgg6ujc6asmxlf2roa/spack-build-out.txt

Traceback (most recent call last):
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py", line 801, in child_process
    return_value = function()
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/installer.py", line 1120, in build_process
    spack.hooks.post_install(pkg.spec)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/__init__.py", line 59, in __call__
    hook(*args, **kwargs)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 115, in post_install
    filter_shebangs_in_directory(directory, filenames)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 102, in filter_shebangs_in_directory
    filter_shebang(path)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 40, in filter_shebang
    original = original.decode(encoding='UTF-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte
==> [2020-03-18-14:08:46.616385, 23523] Error: Failed to install php due to ChildError: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte
/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py:818, in child_process:
        815            tb_string = traceback.format_exc()
        816
        817            # build up some context from the offending package so we can
  >>    818            # show that, too.
        819            package_context = get_package_context(tb)
        820
        821            build_log = None

See build log for details:
  /tmp/username/spack-stage/spack-stage-php-7.4.4-wtyw6jfmd4h7jwbgg6ujc6asmxlf2roa/spack-build-out.txt
Traceback (most recent call last):
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py", line 801, in child_process
    return_value = function()
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/installer.py", line 1120, in build_process
    spack.hooks.post_install(pkg.spec)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/__init__.py", line 59, in __call__
    hook(*args, **kwargs)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 115, in post_install
    filter_shebangs_in_directory(directory, filenames)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 102, in filter_shebangs_in_directory
    filter_shebang(path)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 40, in filter_shebang
    original = original.decode(encoding='UTF-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte

==> [2020-03-18-14:08:46.616495, 23523] Flagging php as failed: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte
/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py:818, in child_process:
        815            tb_string = traceback.format_exc()
        816
        817            # build up some context from the offending package so we can
  >>    818            # show that, too.
        819            package_context = get_package_context(tb)
        820
        821            build_log = None

See build log for details:
  /tmp/username/spack-stage/spack-stage-php-7.4.4-wtyw6jfmd4h7jwbgg6ujc6asmxlf2roa/spack-build-out.txt
Traceback (most recent call last):
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py", line 801, in child_process
    return_value = function()
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/installer.py", line 1120, in build_process
    spack.hooks.post_install(pkg.spec)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/__init__.py", line 59, in __call__
    hook(*args, **kwargs)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 115, in post_install
    filter_shebangs_in_directory(directory, filenames)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 102, in filter_shebangs_in_directory
    filter_shebang(path)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 40, in filter_shebang
    original = original.decode(encoding='UTF-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte

==> [2020-03-18-14:08:46.619790, 23523] WRITE LOCK (php): /storage/epp2/epp_software/spack-devel/opt/spack/.spack-db/prefix_failures[6519162299755759610:1] [Acquiring] 
==> [2020-03-18-14:08:46.621240, 23523] write locking [6519162299755759610:1]: timeout None sec
==> [2020-03-18-14:08:46.621833, 23523] WRITE LOCK (php): /storage/epp2/epp_software/spack-devel/opt/spack/.spack-db/prefix_failures[6519162299755759610:1] [Acquired at 14:08:46.621807] 
==> [2020-03-18-14:08:46.621940, 23523] READ LOCK (database): /storage/epp2/epp_software/spack-devel/opt/spack/.spack-db/lock[0:0] [Acquiring] 
==> [2020-03-18-14:08:46.623453, 23523] read locking [0:0]: timeout 3 sec
==> [2020-03-18-14:08:46.623837, 23523] READ LOCK (database): /storage/epp2/epp_software/spack-devel/opt/spack/.spack-db/lock[0:0] [Acquired at 14:08:46.623818] 
==> [2020-03-18-14:08:46.632693, 23523] READ LOCK (database): /storage/epp2/epp_software/spack-devel/opt/spack/.spack-db/lock[0:0] [Releasing] 
==> [2020-03-18-14:08:46.633711, 23523] READ LOCK (database): /storage/epp2/epp_software/spack-devel/opt/spack/.spack-db/lock[0:0] [Released at 14:08:46.633688] 
==> [2020-03-18-14:08:48.101447, 23523] ChildError: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte
/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py:818, in child_process:
        815            tb_string = traceback.format_exc()
        816
        817            # build up some context from the offending package so we can
  >>    818            # show that, too.
        819            package_context = get_package_context(tb)
        820
        821            build_log = None

See build log for details:
  /tmp/username/spack-stage/spack-stage-php-7.4.4-wtyw6jfmd4h7jwbgg6ujc6asmxlf2roa/spack-build-out.txt
Traceback (most recent call last):
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/build_environment.py", line 801, in child_process
    return_value = function()
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/installer.py", line 1120, in build_process
    spack.hooks.post_install(pkg.spec)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/__init__.py", line 59, in __call__
    hook(*args, **kwargs)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 115, in post_install
    filter_shebangs_in_directory(directory, filenames)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 102, in filter_shebangs_in_directory
    filter_shebang(path)
  File "/storage/epp2/epp_software/spack-devel/lib/spack/spack/hooks/sbang.py", line 40, in filter_shebang
    original = original.decode(encoding='UTF-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 1462: invalid start byte

```

### Platform and user environment
```commandline
$ uname -a 
Linux hostname 3.10.0-1062.12.1.el7.x86_64 #1 SMP Tue Feb 4 23:02:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -d
Description:	CentOS Linux release 7.7.1908 (Core)
``` 
- `compilers.yaml`
  - Only change is that gcc@9.4.0 is installed by spack and then added to `compilers.yaml`, so `php` and deps are building with this compiler.

### Additional information

### General information

- [x] I have run `spack --version` and reported the version of Spack
- [x] I have searched the issues of this repo and believe this is not a duplicate



Discussion:

Resolving patch:
diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py
--- a/lib/spack/spack/hooks/sbang.py
+++ b/lib/spack/spack/hooks/sbang.py
@@ -64,6 +64,10 @@ def filter_shebang(path):
     if re.search(r'^#!(/[^/\n]*)*lua\b', original):
         original = re.sub(r'^#', '--', original)
 
+    # Use <?php #! instead of #! on second line for php.
+    if re.search(r'^#!(/[^/\n]*)*php\b', original):
+        original = re.sub(r'^#', '<?php #', original) + ' ?>'
+
     # Use //! instead of #! on second line for node.js.
     if re.search(r'^#!(/[^/\n]*)*node\b', original):
         original = re.sub(r'^#', '//', original)
diff --git a/var/spack/repos/builtin/packages/php/package.py b/var/spack/repos/builtin/packages/php/package.py
--- a/var/spack/repos/builtin/packages/php/package.py
+++ b/var/spack/repos/builtin/packages/php/package.py
@@ -5,6 +5,8 @@
 
 from spack import *
 
+import spack.hooks.sbang as sbang
+
 
 class Php(AutotoolsPackage):
     """
@@ -36,6 +38,27 @@ class Php(AutotoolsPackage):
     depends_on('libxml2')
     depends_on('sqlite')
 
+    patch('sbang.patch')
+
+    def patch(self):
+        """
+        phar sbang is added before build phase.
+        Because phar is php script with binary data
+        (Not UTF-8 text file) And phar is embeded own sha1 checksum.
+        """
+        shebang_limit = 127
+
+        if len(self.prefix.bin.php) + 2 <= shebang_limit:
+            return
+
+        new_sbang_line = '#!/bin/bash %s' % sbang.sbang_install_path()
+        original_bang = '-b "$(PHP_PHARCMD_BANG)"'
+        makefile = join_path('ext', 'phar', 'Makefile.frag')
+        filter_file(
+            original_bang,
+            original_bang + ' -z "{0}"'.format(new_sbang_line),
+            makefile, string=True)
+
     def autoreconf(self, spec, prefix):
         bash = which('bash')
         bash('./buildconf', '--force')


Test patch:
diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py
--- a/lib/spack/spack/test/sbang.py
+++ b/lib/spack/spack/test/sbang.py
@@ -30,6 +30,11 @@
 node_in_text      = ("line\n") * 100 + "lua\n" + ("line\n" * 100)
 node_line_patched = "//!/this/" + ('x' * 200) + "/is/node\n"
 sbang_line        = '#!/bin/bash %s/bin/sbang\n' % spack.store.layout.root
+php_line         = "#!/this/" + ('x' * 200) + "/is/php\n"
+php_in_text      = ("line\n") * 100 + "php\n" + ("line\n" * 100)
+php_line_patched = "<?php #!/this/" + ('x' * 200) + "/is/php\n"
+php_line_patched2 = "?>\n"
+sbang_line        = '#!/bin/bash %s/bin/sbang\n' % spack.store.layout.root
 last_line         = "last!\n"
 
 
@@ -79,6 +84,19 @@ def __init__(self):
             f.write(node_in_text)
             f.write(last_line)
 
+        # php script with long shebang
+        self.php_shebang = os.path.join(self.tempdir, 'php')
+        with open(self.php_shebang, 'w') as f:
+            f.write(php_line)
+            f.write(last_line)
+
+        # php script with long shebang
+        self.php_textbang = os.path.join(self.tempdir, 'php_in_text')
+        with open(self.php_textbang, 'w') as f:
+            f.write(short_line)
+            f.write(php_in_text)
+            f.write(last_line)
+
         # Script already using sbang.
         self.has_sbang = os.path.join(self.tempdir, 'shebang')
         with open(self.has_sbang, 'w') as f: