From 5fe5c49b2d432ff2cf9974e58e8c8f799ec230be Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jan=20R=C4=99korajski?= Date: Thu, 2 Jan 2020 23:13:33 +0900 Subject: [PATCH] - move php macros and php-pearprov here from rpm package --- attr.php | 6 ++ macros.php | 193 ++++++++++++++++++++++++++++++++++++++++++ rpm-build-macros.spec | 36 ++++++++ rpm-php-provides | 20 +++++ rpm-php-requires | 82 ++++++++++++++++++ rpm-php-requires.php | 174 +++++++++++++++++++++++++++++++++++++ 6 files changed, 511 insertions(+) create mode 100644 attr.php create mode 100644 macros.php create mode 100644 rpm-php-provides create mode 100644 rpm-php-requires create mode 100644 rpm-php-requires.php diff --git a/attr.php b/attr.php new file mode 100644 index 0000000..42eb130 --- /dev/null +++ b/attr.php @@ -0,0 +1,6 @@ +%__php_provides %{_rpmconfigdir}/php.prov +# define 'php_req_new' in ~/.rpmmacros to use php version of req finder +%__php_requires env PHP_MIN_VERSION=%{?php_min_version} %{_rpmconfigdir}/php.req%{?php_req_new:.php} +%__php_magic ^PHP script.* +%__php_path \\.php$ +%__php_flags magic_and_path diff --git a/macros.php b/macros.php new file mode 100644 index 0000000..430bc83 --- /dev/null +++ b/macros.php @@ -0,0 +1,193 @@ +# PHP specific macro definitions. + +# name of php package +%php_name php%{?php_suffix} + +# use rpmbuild -D 'php_suffix 54' to build php extension for php 5.4 +# NOTE: error output must be empty. otherwise can't build pecl packages if no php*-devel is installed +%php_suffix %{expand:%%global php_suffix %(c=$(php-config --sysconfdir 2>/dev/null) || echo '' && echo ${c#/etc/php})%%{nil}}%php_suffix + +# phpXY, version always present for using current php version (in regards of php*-devel package) +%php_versuffix %{expand:%%global php_versuffix %((IFS=.; set -- $(php-config --version); echo $1$2))%%{nil}}%php_versuffix + +# php cli. version that php headers are installed for +%__php /usr/bin/php%{php_versuffix} + +%php_pear_dir /usr/share/pear +%php_data_dir /usr/share/php +%php_extensiondir %{expand:%%global php_extensiondir %(php-config --extension-dir 2>/dev/null || echo ERROR)}%php_extensiondir +%php_sysconfdir %{expand:%%global php_sysconfdir %(php-config --sysconfdir 2>/dev/null || echo ERROR)}%php_sysconfdir +%php_includedir %{expand:%%global php_includedir %(php-config --include-dir 2>/dev/null || echo ERROR)}%php_includedir + +# extract php/zend api versions +%php_major_version %{expand:%%global php_major_version %(awk '/#define PHP_MAJOR_VERSION/{print $3}' %{php_includedir}/main/php_version.h 2>/dev/null || echo ERROR)}%php_major_version +%php_minor_version %{expand:%%global php_minor_version %(awk '/#define PHP_MINOR_VERSION/{print $3}' %{php_includedir}/main/php_version.h 2>/dev/null || echo ERROR)}%php_minor_version +%php_api_version %{expand:%%global php_api_version %(awk '/#define PHP_API_VERSION/{print $3}' %{php_includedir}/main/php.h 2>/dev/null || echo ERROR)}%php_api_version +%php_pdo_api_version %{expand:%%global php_pdo_api_version %(awk '/#define PDO_DRIVER_API/{print $3}' %{php_includedir}/ext/pdo/php_pdo_driver.h 2>/dev/null || echo ERROR)}%php_pdo_api_version +%php_debug %{expand:%%global php_debug %(awk '/#define ZEND_DEBUG/{print $3}' %{php_includedir}/main/php_config.h 2>/dev/null || echo ERROR)}%php_debug +%zend_module_api %{expand:%%global zend_module_api %(awk '/#define ZEND_MODULE_API_NO/{print $3}' %{php_includedir}/Zend/zend_modules.h 2>/dev/null || echo ERROR)}%zend_module_api +%zend_extension_api %{expand:%%global zend_extension_api %(awk '/#define ZEND_EXTENSION_API_NO/{print $3}' %{php_includedir}/Zend/zend_extensions.h 2>/dev/null || echo ERROR)}%zend_extension_api +%_zend_zts %{expand:%%global _zend_zts %(Z=$(grep -sc '^#define ZTS 1' %{php_includedir}/main/php_config.h); echo ${Z:-ERROR})}%_zend_zts +# "_ts" if ZTS enabled, empty otherwise +%zend_zts %{expand:%%global _zend_zts_%{?_zend_zts} 1}%{?_zend_zts_1:_ts} + +# helper macro +%__php_api_requires() Requires: %{php_name}(%{expand:%1}) = %{expand:%{%{!?2:%{1}}%{?2}}} + +# macros for public use +# for php extensions (php-pecl) +%requires_php_extension %{__php_api_requires modules_api php_api_version} \ +%{__php_api_requires zend_module_api} \ +%{__php_api_requires debug php_debug} \ +%{__php_api_requires thread-safety _zend_zts} + +# for zend extensions +%requires_zend_extension %{__php_api_requires zend_module_api} \ +%{__php_api_requires zend_extension_api} \ +%{__php_api_requires debug php_debug} \ +%{__php_api_requires thread-safety _zend_zts} + +# for php pdo modules (php-pecl-PDO_*) +%requires_php_pdo_module %{__php_api_requires PDO_API php_pdo_api_version} + +# for using PHP post scripts. for PHP >= 5.0 +%php_webserver_restart \ +[ ! -f /etc/apache/conf.d/??_mod_php.conf ] || %service -q apache restart \ +[ ! -f /etc/httpd/conf.d/??_mod_php.conf ] || %service -q httpd restart \ +if [ -x /etc/rc.d/init.d/php-fcgi ]; then \ + PHP_FCGI_BINARY=; . /etc/sysconfig/php-fcgi 2>/dev/null \ + if [[ ${PHP_FCGI_BINARY:-php.fcgi} = *php.fcgi* ]]; then \ + %service -q php-fcgi restart \ + fi \ +fi \ +if [ -x /etc/rc.d/init.d/%{php_name}-fpm ]; then \ + %service -q %{php_name}-fpm restart \ +fi \ +%{nil} + +# for using php post scripts. for PHP >= 4.0 && PHP < 5.0 +%php4_webserver_restart \ +[ ! -f /etc/apache/conf.d/??_mod_php4.conf ] || %service -q apache restart \ +[ ! -f /etc/httpd/conf.d/??_mod_php4.conf ] || %service -q httpd restart \ +if [ -x /etc/rc.d/init.d/php-fcgi ]; then \ + PHP_FCGI_BINARY=; . /etc/sysconfig/php-fcgi 2>/dev/null \ + if [[ ${PHP_FCGI_BINARY:-php.fcgi} = *php4.fcgi* ]]; then \ + %service -q php-fcgi restart \ + fi \ +fi \ +%{nil} + +# PEAR install macros +# Author: Elan Ruusamäe +# +# Usage: +# %%pear_package_setup ... +# +# -a # - also unpack SOURCE#. for PEAR bootstrapping +# -n FMT - create builddir with FMT, instead of default %%{pearname}-%%{version} +# -z - unpack pear package and let pear use package.xml (not tarball) for install. for PEAR bootstrapping +# -D - pass -D to %setup (so the build dir is not removed) +# -c - register channel from local channel.xml file +# -d - pass -d arg to pearcmd +# +# unpack PEAR package to %%{_builddir}/FMT. package is extracted with already +# destination hierarchy. you should copy the tree to buildroot after +# patching/reorganizing with %%pear_package_install. +# +# additionally BUILDROOT is stripped from files and files are converted to UNIX +# line endings. +# +# the pear install process output is recorded to install.log, you should put it +# to %%doc for later debug or just for information. +# +# additionally additional-packages.txt is produced if it was detected that the +# package has optional dependencies. the file format is suitable of displaying +# in %%post of a package. you should put this file to %%doc. noautocompressdoc is +# automatically added for this file. + + +# records install.log and transforms PEAR names to PLD Linux rpm package names. +%__pear_install_log \ +tee install.log \ +# make post message of optional packages \ +grep -E 'can optionally use|Optional feature' install.log | sed -e 's,package "pear/,package "php-pear-,g;s,^pear/,php-pear-,;s,^pear/,php-pear-,' > optional-packages.txt \ +if [ -s optional-packages.txt ]; then \ + awk -F'"' '/use package/{print $2}' optional-packages.txt | sed -e "s,_,/,g;s,php-pear-, 'pear(,;s,$,.*)'," | tr -d '\\\n' > _noautoreq \ +else \ + rm -f optional-packages.txt \ +fi \ +%{nil} + +# Command invoking PEAR CLI +# Same as /usr/bin/pear, except we force GMT timezone +%__pear %__php -doutput_buffering=1 -dopen_basedir="" -dmemory_limit=-1 -ddate.timezone=GMT /usr/share/pear/pearcmd.php + +%pear_install(a:d:n:zD) \ +%__pear \\\ + -c %{builddir}/pearrc \\\ + -d doc_dir=/docs \\\ + -d temp_dir=/tmp \\\ + -d php_dir=%{-c:%{builddir}/}%{php_pear_dir} \\\ + -d bin_dir=%{_bindir} \\\ + -d data_dir=%{php_pear_dir}/data \\\ + -d test_dir=%{php_pear_dir}/tests \\\ + %{-d:%(echo "%{-d*}" | awk 'BEGIN{RS=","}{printf("-d %%s \\\\\\n\\t", $1)}')} \\\ + install \\\ + --packagingroot=%{builddir} \\\ + --offline \\\ + --nodeps \\\ + %{-f:--force} \\\ + %{!-z:%{S:%{-a*}%{!-a:0}}}%{-z:$_P} > .install.log || { c=$?; cat .install.log; exit $c; }; \ + %{-c:cp -a %{builddir}/%{builddir}/%{php_pear_dir} %{builddir}/%(dirname %{php_pear_dir}); rm -rf %{builddir}/%{builddir}; } \ +%{nil} + +# The main macro. +# using this macro will append optional-packages.txt to the nocompressdoc list +# as it's displayed to user after package install. and adding additional gzip +# dep is just waste ;) +%pear_package_setup(a:d:n:zDc:) \ +%define srcdir %{-n*}%{!-n:%{?_pearname}%{!?_pearname:%{pearname}}-%{version}} \ +%define builddir %{_builddir}/%{srcdir} \ +%setup -q -c -T %{-D:-D} -n %{srcdir} \ +%{-z:%{__tar} zxf %{S:0}; %{-a:%{__tar} zxf %{S:%{-a*}}}} \ +%{-z:_P=package2.xml; [ -f $_P ] || _P=package.xml; _N=%{srcdir}; mv $_P $_N; cd $_N} \ +%{-c:%{__pear} -c pearrc config-set php_dir %{builddir}/%{php_pear_dir}; %__pear -c %{builddir}/pearrc channel-add %{-c*}} \ +%pear_install \ +%{-z:cd ..} \ +%{__tar} --wildcards -zvxf %{S:0} package*.xml \ +cat %{-z:$_N/}.install.log | %__pear_install_log \ +%undos -f php,html,js,xml \ +%{!?_noautocompressdoc:%global _noautocompressdoc %{nil}}%{expand:%%global _noautocompressdoc %{_noautocompressdoc} optional-packages.txt} \ +%{!?_noautoprov:%global _noautoprov %{nil}}%{expand:%%global _noautoprov %{_noautoprov} 'pear(tests/.*)'} \ +%{nil} + +# Copies extracted PEAR package structure and PEAR registry to buildroot. +# Author: Elan Ruusamäe +%pear_package_install() \ +cp -a ./%{php_pear_dir}/{.registry,*} $RPM_BUILD_ROOT%{php_pear_dir} \ +# tests should not be packaged \ +%{__rm} -rf $RPM_BUILD_ROOT%{php_pear_dir}/tests \ +# cleanup backups \ +find $RPM_BUILD_ROOT%{php_pear_dir} '(' -name '*~' -o -name '*.orig' ')' | xargs -r rm -v \ +# help the developer out a little: \ +if [ -f _noautoreq ]; then \ + echo "AutoReqdep detected:" \ + echo "_noautoreq $(cat _noautoreq)" \ +fi \ +%{nil} + +# Print optional package info for pear packages +# Author: Elan Ruusamäe +# Usage: +# %post -p +# %%pear_package_print_optionalpackages +# +# Requirements: +# BuildRequires: rpmbuild(macros) >= 1.571 +%pear_package_print_optionalpackages \ +f = io.open("%{_docdir}/%{name}-%{version}/optional-packages.txt", "r") \ +if f then \ + for l in f:lines() do print(l); end \ + f:close() \ +end \ +%{nil} diff --git a/rpm-build-macros.spec b/rpm-build-macros.spec index ffc7683..18d03a6 100644 --- a/rpm-build-macros.spec +++ b/rpm-build-macros.spec @@ -23,6 +23,12 @@ Source21: macros.java Source22: rpm-java-requires Source23: eclipse-feature.xslt +Source30: attr.php +Source31: macros.php +Source32: rpm-php-provides +Source33: rpm-php-requires +Source34: rpm-php-requires.php + Patch0: disable-systemd.patch #Patchx: %{name}-pydebuginfo.patch BuildRequires: rpm >= 4.4.9-56 @@ -99,6 +105,24 @@ packages. Dodatkowe narzędzia do sprawdzania zależności kodu w Javie w pakietach RPM. +%package php-pearprov +Summary: Additional utilities for checking PHP PEAR provides/requires in RPM packages +Summary(pl.UTF-8): Dodatkowe narzędzia do sprawdzania zależności skryptów php w RPM +Group: Applications/File +Requires: %{name} = %{version}-%{release} +Requires: sed >= 4.0 +Suggests: php-pear-PHP_CompatInfo +Provides: rpm-php-pearprov +Obsoletes: php-pearprov + +%description php-pearprov +Additional utilities for checking PHP PEAR provides/requires in RPM +packages. + +%description php-pearprov -l pl.UTF-8 +Dodatkowe narzędzia do sprawdzenia zależności skryptów PHP PEAR w +pakietach RPM. + %prep %setup -qcT cp -p %{SOURCE0} . @@ -143,6 +167,11 @@ cat %{SOURCE21} %{SOURCE20} >$RPM_BUILD_ROOT%{_usrlibrpm}/macros.d/java install %{SOURCE22} $RPM_BUILD_ROOT%{_usrlibrpm}/java-find-requires install %{SOURCE23} $RPM_BUILD_ROOT%{_usrlibrpm}/eclipse-feature.xslt +cat %{SOURCE31} %{SOURCE30} >$RPM_BUILD_ROOT%{_usrlibrpm}/macros.d/php +cp -p %{SOURCE32} $RPM_BUILD_ROOT%{_usrlibrpm}/php.prov +cp -p %{SOURCE33} $RPM_BUILD_ROOT%{_usrlibrpm}/php.req +cp -p %{SOURCE34} $RPM_BUILD_ROOT%{_usrlibrpm}/php.req.php + %clean rm -rf $RPM_BUILD_ROOT @@ -151,6 +180,7 @@ rm -rf $RPM_BUILD_ROOT %{_usrlibrpm}/macros.build %{_usrlibrpm}/macros.d/java %{_usrlibrpm}/macros.d/kernel +%{_usrlibrpm}/macros.d/php %{_usrlibrpm}/macros.d/ruby %attr(755,root,root) %{_usrlibrpm}/service_generator.sh %attr(755,root,root) %{_usrlibrpm}/find-lang.sh @@ -165,3 +195,9 @@ rm -rf $RPM_BUILD_ROOT %defattr(644,root,root,755) %attr(755,root,root) %{_usrlibrpm}/java-find-requires %{_usrlibrpm}/eclipse-feature.xslt + +%files php-pearprov +%defattr(644,root,root,755) +%attr(755,root,root) %{_usrlibrpm}/php.prov +%attr(755,root,root) %{_usrlibrpm}/php.req +%attr(755,root,root) %{_usrlibrpm}/php.req.php diff --git a/rpm-php-provides b/rpm-php-provides new file mode 100644 index 0000000..a094cba --- /dev/null +++ b/rpm-php-provides @@ -0,0 +1,20 @@ +#!/usr/bin/perl +##################################################################### +# # +# Check system dependences between php-pear modules # +# # +# Pawe³ Go³aszewski # +# Micha³ Moskal # +# ------------------------------------------------------------------# +# TODO: # +##################################################################### + +$pear = "/usr/share/pear"; + +foreach (@ARGV ? @ARGV : <>) { + chomp; + $f = $_; + next unless ($f =~ /$pear.*\.php$/); + $f =~ s/.*$pear\///; + print "pear($f)\n"; +} diff --git a/rpm-php-requires b/rpm-php-requires new file mode 100644 index 0000000..2a3fb60 --- /dev/null +++ b/rpm-php-requires @@ -0,0 +1,82 @@ +#!/usr/bin/perl +##################################################################### +# # +# Check system dependences between php-pear modules # +# # +# Pawe³ Go³aszewski # +# Micha³ Moskal # +# ------------------------------------------------------------------# +# TODO: # +# - extension_loaded - dependencies. # +# - some clean-up... # +##################################################################### + +$pear = "/usr/share/pear"; + +@files = (); +%req = (); + +foreach (@ARGV ? $ARGV : <> ) { + chomp; + $f = $_; + push @files, $f; + # skip non-php files + next unless ($f =~ /\.php$/); + open(F, "< $f") or die; + + if ($f =~ /$pear/) { + $file_dir = $f; + $file_dir =~ s|.*$pear/||; + $file_dir =~ s|/[^/]*$||; + } else { + $file_dir = undef; + } + + while () { + # skip comments + next if (/^\s*(#|\/\/|\*|\/\*)/); + + while (/(\W|^)(require|include)(_once)? + \s* \(? \s* ("([^"]*)"|'([^']*)') + \s* \)? \s* ;/xg) { + if ($5 ne "") { + $x = $5; + } elsif ($6 ne "") { + $x = $6; + } else { + next; + } + + next if ($x =~ m|^\./| or $x =~ /\$/); + next unless ($x =~ /\.php$/); + $req{$x} = 1; + } + + next unless (defined $file_dir); + + while (/(\W|^)(require|include)(_once)? + \s* \(? \s* dirname \s* \( \s* __FILE__ \s* \) \s* \. \s* + ("([^"]*)"|'([^']*)') + \s* \)? \s* ;/xg) { + if ($5 ne "") { + $x = $5; + } elsif ($6 ne "") { + $x = $6; + } else { + next; + } + + next if ($x =~ /\$/); + next unless ($x =~ /\.php$/); + + $x = "$file_dir/$x"; + $x =~ s|/+|/|g; + $req{$x} = 1; + } + } +} + +f: for $f (keys %req) { + for $g (@files) { next f if ($g =~ /\Q$f\E$/); } + print "pear($f)\n"; +} diff --git a/rpm-php-requires.php b/rpm-php-requires.php new file mode 100644 index 0000000..b398029 --- /dev/null +++ b/rpm-php-requires.php @@ -0,0 +1,174 @@ +#!/usr/bin/php + (Perl version) + * Michał Moskal (Perl version) + * Elan Ruusamäe + * + * URL: + * + * Requires: php-pear-PHP_CompatInfo + * Requires: php-pcre + */ + +/** + * Produce pear(Path/To/File.php) deps + * Ported to PHP from Perl version of rpm-php-requires. + * + * @TODO: use tokenizer to parse php files. + */ +function peardeps($files) { + // files inside php_pear_dir have this prefix + $prefix = RPM_BUILD_ROOT. PHP_PEAR_DIR . DIRECTORY_SEPARATOR; + $length = strlen($prefix); + + $req = array(); + foreach ($files as $f) { + // skip non-php files + if (substr($f, -4) != '.php') { + continue; + } + + // subdir inside php_pear_dir + if (substr($f, 0, $length) == $prefix) { + $file_dir = dirname(substr($f, $length)); + } else { + $file_dir = null; + } + + foreach (file($f) as $line) { + // skip comments -- not perfect, matches "*" at start of line (very rare altho) + if (preg_match('/^\s*(#|\/\/|\*|\/\*)/', $line)) { + continue; + } + + if (preg_match("/(\W|^)(require|include)(_once)? + \s* \(? \s* + (\"([^\"]*)\"|'([^']*)') + \s* \)? \s* ;/x", $line, $m)) { + + if ($m[5]) { + $x = $m[5]; + } else if ($m[6]) { + $x = $m[6]; + } else { + continue 2; + } + + if (substr($x, 0, 2) == './' || substr($x, -1) == '$') { # XXX must be: CONTAINS DOLLAR + continue 2; + } + + if (substr($x, -4) != '.php') { + continue 2; + } + $req[$x] = 1; + continue 2; + } + + if (is_null($file_dir)) { + continue; + } + + if (preg_match("/(\W|^)(require|include)(_once)? + \s* \(? \s* dirname \s* \( \s* __FILE__ \s* \) \s* \. \s* + (\"([^\"]*)\"|'([^']*)') + \s* \)? \s* ;/x", $line, $m)) { + + if ($m[5]) { + $x = $m[5]; + } else if ($m[6]) { + $x = $m[6]; + } else { + continue 2; + } + + if (substr($x, -1) == '$') { # XXX must be: CONTAINS DOLLAR + continue 2; + } + if (substr($x, -4) != '.php') { + continue 2; + } + + $x = "$file_dir/$x"; + // remove double slashes + // TODO: resolve simpletest/test/../socket.php -> simpletest/socket.php + $x = str_replace("//", "/", $x); + $req[$x] = 1; + continue; + } + } + } + + foreach (array_keys($req) as $f) { + // skip self deps + if (array_key_exists($f, $files)) { + continue; + } + echo "pear($f)\n"; + } +} + +/** + * Produce dependencies for extensions using PEAR PHP_CompatInfo package. + */ +function extdeps($files) { + require_once 'PHP/CompatInfo.php'; + + $info = new PHP_CompatInfo('null'); + $res = $info->parseData($files); + + // minimum php version we accept + // "%define php_min_version 5.1.2" in spec to minimum version to be 5.1.2 + $version = max(PHP_MIN_VERSION, $res['version']); + + if (version_compare($version, '5.0.0', 'ge')) { + # force php- only deps when php5 + # XXX what about php-pecl- virtual provides? + $fmt = 'php-%s'; + $epoch = 4; + } else { + $fmt = 'php(%s)'; + $epoch = 3; + } + echo "php-common >= ", $epoch, ":", $version, "\n"; + + // process extensions + foreach ($res['extensions'] as $ext) { + // bz2 ext is in php-bzip2 package + if ($ext == 'bz2') { + $ext = 'bzip2'; + } + // libxml ext is in php-xml package + if ($ext == 'libxml') { + $ext = 'xml'; + } + + // these need to be lowercased + if (in_array($ext, array('SPL', 'PDO', 'SQLite', 'Reflection', 'SimpleXML'))) { + $ext = strtolower($ext); + } + + printf("$fmt\n", $ext); + } +} + +define('RPM_BUILD_ROOT', getenv('RPM_BUILD_ROOT')); +define('PHP_PEAR_DIR', '/usr/share/pear'); +define('PHP_MIN_VERSION', getenv('PHP_MIN_VERSION')); + +if ($argc > 1) { + $files = array_splice($argv, 1); +} else { + $files = explode(PHP_EOL, trim(file_get_contents('php://stdin'))); +} + +peardeps($files); +extdeps($files); -- 2.44.0