diff options
author | Toyohisa Kameyama <kameyama@riken.jp> | 2020-10-27 14:11:43 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-26 22:11:43 -0700 |
commit | bb00b1a7c9eae3d307f0a22dcccae9e33a5885d0 (patch) | |
tree | e5c4a9e189bac786687ba3bdb0d17374923a3049 | |
parent | cb07d9ddb1e744c8e0f1aded64ab3f5bf9e5bae3 (diff) | |
download | spack-bb00b1a7c9eae3d307f0a22dcccae9e33a5885d0.tar.gz spack-bb00b1a7c9eae3d307f0a22dcccae9e33a5885d0.tar.bz2 spack-bb00b1a7c9eae3d307f0a22dcccae9e33a5885d0.tar.xz spack-bb00b1a7c9eae3d307f0a22dcccae9e33a5885d0.zip |
sbang: add support for php (#18299)
PHP supports an initial shebang, but its comment syntax can't handle our 2-line
shebangs. So, we need to embed the 2nd-line shebang comment to look like a
PHP comment:
<?php #!/path/to/php ?>
This adds patching support to the sbang hook and support for
instrumenting php shebangs.
This also patches `phar`, which is a tool used to create php packages.
`phar` itself has to add sbangs to those packages (as phar archives
apparently contain UTF-8, as well as binary blobs), and `phar` sets a
checksum based on the contents of the package.
Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
-rwxr-xr-x | bin/sbang | 25 | ||||
-rw-r--r-- | lib/spack/spack/hooks/sbang.py | 4 | ||||
-rw-r--r-- | lib/spack/spack/test/sbang.py | 18 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/php/package.py | 23 | ||||
-rwxr-xr-x | var/spack/repos/builtin/packages/php/sbang.patch | 42 |
5 files changed, 105 insertions, 7 deletions
@@ -61,15 +61,23 @@ # Obviously, for this to work, `sbang` needs to have a short enough # path that *it* will run without hitting OS limits. # -# For Lua, scripts the second line can't start with #!, as # is not -# the comment character in lua (even though lua ignores #! on the -# *first* line of a script). So, instrument a lua script like this, -# using -- instead of # on the second line: +# For Lua, node, and php scripts, the second line can't start with #!, as +# # is not the comment character in these languages (though they all +# ignore #! on the *first* line of a script). So, instrument such scripts +# like this, using --, //, or <?php ... ?> instead of # on the second +# line, e.g.: # # 1 #!/bin/bash /path/to/sbang # 2 --!/long/path/to/lua with arguments -# 3 -# 4 print "success!" +# 3 print "success!" +# +# 1 #!/bin/bash /path/to/sbang +# 2 //!/long/path/to/node with arguments +# 3 print "success!" +# +# 1 #!/bin/bash /path/to/sbang +# 2 <?php #/long/path/to/php with arguments ?> +# 3 <?php echo "success!\n"; ?> # # How it works # ----------------------------- @@ -90,6 +98,9 @@ while read line && ((lines < 2)) ; do interpreter="${line#//!}" elif [[ "$line" = '--!'*lua* ]]; then interpreter="${line#--!}" + elif [[ "$line" = '<?php #!'*php* ]]; then + interpreter="${line#<?php\ \#!}" + interpreter="${interpreter%\ ?>}" fi lines=$((lines+1)) done < "$script" @@ -98,7 +109,7 @@ done < "$script" # #!/<spack-long-path>/perl -w # this is the interpreter line with all the parameters as a vector interpreter_v=(${interpreter}) -# this is the single interpreter path +# this is the single interpreter path interpreter_f="${interpreter_v[0]}" # Invoke any interpreter found, or raise an error if none was found. diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py index 324d5d4fbb..24d84db8af 100644 --- 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/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py index eeb68f20ab..c2d0adf4d2 100644 --- a/lib/spack/spack/test/sbang.py +++ b/lib/spack/spack/test/sbang.py @@ -30,6 +30,11 @@ node_line = "#!/this/" + ('x' * 200) + "/is/node\n" 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 @@ class ScriptDirectory(object): 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: diff --git a/var/spack/repos/builtin/packages/php/package.py b/var/spack/repos/builtin/packages/php/package.py index 714bfb0e8f..d5da45eb94 100644 --- 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') diff --git a/var/spack/repos/builtin/packages/php/sbang.patch b/var/spack/repos/builtin/packages/php/sbang.patch new file mode 100755 index 0000000000..aca17c8ff3 --- /dev/null +++ b/var/spack/repos/builtin/packages/php/sbang.patch @@ -0,0 +1,42 @@ +--- spack-src/ext/phar/phar/pharcommand.inc.org 2019-12-18 01:35:53.000000000 +0900 ++++ spack-src/ext/phar/phar/pharcommand.inc 2020-08-20 12:26:16.207347572 +0900 +@@ -68,6 +68,12 @@ + 'inf' => '<bang> Hash-bang line to start the archive (e.g. #!/usr/bin/php). The hash ' + .' mark itself \'#!\' and the newline character are optional.' + ), ++ 'z' => array( ++ 'typ' => 'any', ++ 'val' => NULL, ++ 'inf' => '<bang> Hash-bang line to start the archive for spack. The hash ' ++ .' mark itself \'#!\' and the newline character are optional.' ++ ), + 'c' => array( + 'typ' => 'compalg', + 'val' => NULL, +@@ -455,7 +461,7 @@ + */ + static function cli_cmd_arg_pack() + { +- $args = self::phar_args('abcFhilpsxy', 'pharnew'); ++ $args = self::phar_args('azbcFhilpsxy', 'pharnew'); + + $args[''] = array( + 'typ' => 'any', +@@ -560,6 +566,7 @@ + } + + $alias = $this->args['a']['val']; ++ $spack_hb = $this->args['z']['val']; + $hashbang = $this->args['b']['val']; + $archive = $this->args['f']['val']; + $hash = $this->args['h']['val']; +@@ -571,6 +578,9 @@ + $invregex = $this->args['x']['val']; + $input = $this->args['']['val']; + ++ if (isset($spack_hb)) { ++ $hashbang = "$spack_hb\n<?php #!$hashbang ?>"; ++ } + $hash = self::phar_check_hash($hash, $privkey); + + $phar = new Phar($archive, 0, $alias); |