public function __construct()
{
// init variant builders
$this->variants['all'] = '--enable-all';
$this->variants['dba'] = '--enable-dba';
$this->variants['ipv6'] = '--enable-ipv6';
$this->variants['dom'] = '--enable-dom';
$this->variants['calendar'] = '--enable-calendar';
$this->variants['wddx'] = '--enable-wddx';
$this->variants['static'] = '--enable-static';
$this->variants['inifile'] = '--enable-inifile';
$this->variants['inline'] = '--enable-inline-optimization';
$this->variants['cli'] = '--enable-cli';
$this->variants['ftp'] = '--enable-ftp';
$this->variants['filter'] = '--enable-filter';
$this->variants['gcov'] = '--enable-gcov';
$this->variants['zts'] = '--enable-maintainer-zts';
$this->variants['json'] = '--enable-json';
$this->variants['hash'] = '--enable-hash';
$this->variants['exif'] = '--enable-exif';
$this->variants['mbstring'] = '--enable-mbstring';
$this->variants['mbregex'] = '--enable-mbregex';
$this->variants['libgcc'] = '--enable-libgcc';
// $this->variants['gd-jis'] = '--enable-gd-jis-conv';
$this->variants['pdo'] = '--enable-pdo';
$this->variants['posix'] = '--enable-posix';
$this->variants['embed'] = '--enable-embed';
$this->variants['sockets'] = '--enable-sockets';
$this->variants['debug'] = '--enable-debug';
$this->variants['phpdbg'] = '--enable-phpdbg';
$this->variants['zip'] = '--enable-zip';
$this->variants['bcmath'] = '--enable-bcmath';
$this->variants['fileinfo'] = '--enable-fileinfo';
$this->variants['ctype'] = '--enable-ctype';
$this->variants['cgi'] = '--enable-cgi';
$this->variants['soap'] = '--enable-soap';
$this->variants['gcov'] = '--enable-gcov';
$this->variants['pcntl'] = '--enable-pcntl';
$this->variants['phar'] = '--enable-phar';
$this->variants['session'] = '--enable-session';
$this->variants['tokenizer'] = '--enable-tokenizer';
// opcache was added since 5.6
$this->variants['opcache'] = '--enable-opcache';
$this->variants['imap'] = '--with-imap-ssl';
$this->variants['tidy'] = '--with-tidy';
$this->variants['kerberos'] = '--with-kerberos';
$this->variants['xmlrpc'] = '--with-xmlrpc';
$this->variants['fpm'] = function (Build $build, $prefix = null) {
$opts = array('--enable-fpm');
if ($bin = Utils::findBin('systemctl') && Utils::findIncludePrefix('systemd/sd-daemon.h')) {
$opts[] = '--with-fpm-systemd';
}
return $opts;
};
$this->variants['dtrace'] = function (Build $build, $prefix = null) {
// if dtrace is supported
/*
if ($prefix = Utils::findIncludePrefix('sys/sdt.h')) {
return "--enable-dtrace";
}
*/
return '--enable-dtrace';
};
$this->variants['pcre'] = function (Build $build, $prefix = null) {
if ($prefix) {
return array('--with-pcre-regex', "--with-pcre-dir={$prefix}");
}
if ($prefix = Utils::findIncludePrefix('pcre.h')) {
return array('--with-pcre-regex', "--with-pcre-dir={$prefix}");
}
if ($bin = Utils::findBin('brew')) {
if ($prefix = exec_line("{$bin} --prefix pcre")) {
if (file_exists($prefix)) {
return array('--with-pcre-regex', "--with-pcre-dir={$prefix}");
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
return array('--with-pcre-regex');
};
$this->variants['mhash'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-mhash={$prefix}";
}
if ($prefix = Utils::findIncludePrefix('mhash.h')) {
return "--with-mhash={$prefix}";
}
if ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix mhash")) {
if (file_exists($output)) {
return "--with-mhash={$output}";
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
return '--with-mhash';
// let autotool to find it.
};
$this->variants['mcrypt'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-mcrypt={$prefix}";
}
if ($prefix = Utils::findIncludePrefix('mcrypt.h')) {
return "--with-mcrypt={$prefix}";
}
if ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix mcrypt")) {
if (file_exists($output)) {
return "--with-mcrypt={$output}";
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
return '--with-mcrypt';
// let autotool to find it.
};
$this->variants['zlib'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-zlib={$prefix}";
}
if ($prefix = Utils::findIncludePrefix('zlib.h')) {
return "--with-zlib={$prefix}";
}
return;
};
$this->variants['curl'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-curl={$prefix}";
}
if ($prefix = Utils::findIncludePrefix('curl/curl.h')) {
return "--with-curl={$prefix}";
}
if ($prefix = Utils::getPkgConfigPrefix('libcurl')) {
return "--with-curl={$prefix}";
}
if ($bin = Utils::findBin('brew')) {
if ($prefix = exec_line("{$bin} --prefix curl")) {
if (file_exists($prefix)) {
return "--with-curl={$prefix}";
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
if ($bin = Utils::findBin('curl-config')) {
if ($prefix = exec_line("{$bin} --prefix")) {
if (file_exists($prefix)) {
return "--with-curl={$prefix}";
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
return;
};
/*
Users might prefer readline over libedit because only readline supports
readline_list_history() (http://www.php.net/readline-list-history).
On the other hand we want libedit to be the default because its license
is compatible with PHP's which means PHP can be distributable.
related issue https://github.com/phpbrew/phpbrew/issues/497
The default libreadline version that comes with OS X is too old and
seems to be missing symbols like rl_mark, rl_pending_input,
rl_history_list, rl_on_new_line. This is not detected by ./configure
So we should prefer macports/homebrew library than the system readline library.
@see https://bugs.php.net/bug.php?id=48608
*/
$this->variants['readline'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-readline={$prefix}";
}
if ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix readline")) {
if (file_exists($output)) {
return '--with-readline=' . $output;
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
if ($prefix = Utils::findIncludePrefix('readline' . DIRECTORY_SEPARATOR . 'readline.h')) {
return '--with-readline=' . $prefix;
}
return '--with-readline';
};
/*
* editline is conflict with readline
*
* one must tap the homebrew/dupes to use this formula
*
* brew tap homebrew/dupes
*/
$this->variants['editline'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-libedit={$prefix}";
} elseif ($prefix = Utils::findIncludePrefix('editline' . DIRECTORY_SEPARATOR . 'readline.h')) {
return "--with-libedit={$prefix}";
} elseif ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix libedit")) {
if (file_exists($output)) {
return '--with-libedit=' . $output;
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
} else {
echo "prefix of libedit not found, please run 'brew tap homebrew/dupes' to get the formula\n";
}
}
return '--with-libedit';
};
/*
* It looks like gd won't be compiled without "shared"
*
* Suggested options is +gd=shared,{prefix}
*
* Issue: gd.so: undefined symbol: gdImageCreateFromWebp might happend
*
* Adding --with-libpath=lib or --with-libpath=lib/x86_64-linux-gnu
* might solve the gd issue.
*
* The configure script in ext/gd detects libraries by something like
* test -f $PREFIX/$LIBPATH/libxxx.a, where $PREFIX is what you passed
* in --with-xxxx-dir and $LIBPATH can varies in different OS.
*
* By adding --with-libpath, you can set it up properly.
*
* @see https://github.com/phpbrew/phpbrew/issues/461
*/
$this->variants['gd'] = function (Build $build, $prefix = null) {
$opts = array();
if ($prefix) {
$opts[] = "--with-gd={$prefix}";
} elseif ($prefix = Utils::findIncludePrefix('gd.h')) {
$opts[] = "--with-gd=shared,{$prefix}";
} elseif ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix gd")) {
if (file_exists($output)) {
$opts[] = "--with-gd=shared,{$output}";
} else {
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
}
$opts[] = '--enable-gd-native-ttf';
if ($prefix = Utils::findIncludePrefix('jpeglib.h')) {
$opts[] = "--with-jpeg-dir={$prefix}";
} elseif ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix libjpeg")) {
if (file_exists($output)) {
$opts[] = "--with-jpeg-dir={$output}";
} else {
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
}
if ($prefix = Utils::findIncludePrefix('png.h', 'libpng12/pngconf.h')) {
$opts[] = "--with-png-dir={$prefix}";
} elseif ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix libpng")) {
if (file_exists($output)) {
$opts[] = "--with-png-dir={$output}";
} else {
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
}
// the freetype-dir option does not take prefix as its value,
// it takes the freetype.h directory as its value.
//
// from configure:
// for path in $i/include/freetype2/freetype/freetype.h
if ($prefix = Utils::findIncludePrefix('freetype2/freetype.h')) {
$opts[] = "--with-freetype-dir={$prefix}";
} elseif ($prefix = Utils::findIncludePrefix('freetype2/freetype/freetype.h')) {
$opts[] = "--with-freetype-dir={$prefix}";
} elseif ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix freetype", $output, $retval)) {
if (file_exists($output)) {
$opts[] = "--with-freetype-dir={$output}";
} else {
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
}
return $opts;
};
/*
--enable-intl
To build the extension you need to install the » ICU library, version
4.0.0 or newer is required.
This extension is bundled with PHP as of PHP version 5.3.0.
Alternatively, the PECL version of this extension may be used with all
PHP versions greater than 5.2.0 (5.2.4+ recommended).
This requires --with-icu-dir=/....
Please note prefix must provide {prefix}/bin/icu-config for autoconf
to find the related icu-config binary, or the configure will fail.
Issue: https://github.com/phpbrew/phpbrew/issues/433
*/
$this->variants['intl'] = function (Build $build) {
$opts = array('--enable-intl');
// If icu variant is not set, and --with-icu-dir could not been found in the extra options
$icuOption = $build->settings->grepExtraOptionsByPattern('#--with-icu-dir#');
if (!$build->settings->isEnabledVariant('icu') || empty($icuOption)) {
if ($bin = Utils::findBin('icu-config')) {
/*
* let autoconf find it's own icu-config
* The build-in acinclude.m4 will find the icu-config from $PATH:/usr/local/bin
*/
} elseif ($prefix = Utils::getPkgConfigPrefix('icu-i18n')) {
// For macports or linux
$opts[] = '--with-icu-dir=' . $prefix;
} elseif ($bin = Utils::findBin('brew')) {
// For homebrew
if ($output = exec_line("{$bin} --prefix icu4c")) {
if (file_exists($output)) {
$opts[] = "--with-icu-dir={$output}";
} else {
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
}
}
return $opts;
};
/*
* icu variant
*
* @deprecated this variant is deprecated since icu is a part of intl
* extension. however, we kept this variant for user to customize the icu path
*/
$this->variants['icu'] = function (Build $build, $val = null) {
if ($val) {
return '--with-icu-dir=' . $val;
}
};
/*
* --with-openssl option
*
* --with-openssh=shared
* --with-openssl=[dir]
*
* On ubuntu you need to install libssl-dev
*/
$this->variants['openssl'] = function (Build $build, $val = null) {
if ($val) {
return "--with-openssl={$val}";
}
if ($prefix = Utils::findIncludePrefix('openssl/opensslv.h')) {
return "--with-openssl={$prefix}";
}
// Special detection and fallback for homebrew openssl
// @see https://github.com/phpbrew/phpbrew/issues/607
if ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix openssl")) {
if (file_exists($output)) {
return "--with-openssl={$output}";
}
echo "prefix {$output} doesn't exist.";
}
}
if ($prefix = Utils::getPkgConfigPrefix('openssl')) {
return "--with-openssl={$prefix}";
}
$possiblePrefixes = array('/usr/local/opt/openssl');
$foundPrefixes = array_filter($possiblePrefixes, 'file_exists');
if (count($foundPrefixes) > 0) {
return '--with-openssl=' . $foundPrefixes[0];
}
// This will create openssl.so file for dynamic loading.
echo 'Compiling with openssl=shared, please install libssl-dev or openssl header files if you need';
return '--with-openssl';
};
/*
quote from the manual page:
> MySQL Native Driver is a replacement for the MySQL Client Library
> (libmysqlclient). MySQL Native Driver is part of the official PHP
> sources as of PHP 5.3.0.
> The MySQL database extensions MySQL extension, mysqli and PDO MYSQL all
> communicate with the MySQL server. In the past, this was done by the
> extension using the services provided by the MySQL Client Library. The
> extensions were compiled against the MySQL Client Library in order to
> use its client-server protocol.
> With MySQL Native Driver there is now an alternative, as the MySQL
> database extensions can be compiled to use MySQL Native Driver instead
> of the MySQL Client Library.
mysqlnd should be prefered over the native client library.
--with-mysql[=DIR] Include MySQL support. DIR is the MySQL base
directory. If mysqlnd is passed as DIR,
the MySQL native driver will be used [/usr/local]
--with-mysqli[=FILE] Include MySQLi support. FILE is the path
to mysql_config. If mysqlnd is passed as FILE,
the MySQL native driver will be used [mysql_config]
--with-pdo-mysql[=DIR] PDO: MySQL support. DIR is the MySQL base directoy
If mysqlnd is passed as DIR, the MySQL native
native driver will be used [/usr/local]
--with-mysql deprecated in 7.0
--enable-mysqlnd Enable mysqlnd explicitly, will be done implicitly
when required by other extensions
mysqlnd was added since php 5.3
*/
$this->variants['mysql'] = function (Build $build, $prefix = 'mysqlnd') {
$opts = array();
if ($build->compareVersion('7.0') < 0) {
$opts[] = "--with-mysql={$prefix}";
}
/*
if ($build->compareVersion('5.4') > 0) {
$opts[] = "--enable-mysqlnd";
}
*/
$opts[] = "--with-mysqli={$prefix}";
if ($build->hasVariant('pdo')) {
$opts[] = "--with-pdo-mysql={$prefix}";
}
$foundSock = false;
if ($bin = Utils::findBin('mysql_config')) {
if ($output = exec_line("{$bin} --socket")) {
$foundSock = true;
$opts[] = "--with-mysql-sock={$output}";
}
}
if (!$foundSock) {
$possiblePaths = array('/opt/local/var/run/mysql57/mysqld.sock', '/opt/local/var/run/mysql56/mysqld.sock', '/opt/local/var/run/mysql55/mysqld.sock', '/opt/local/var/run/mysql54/mysqld.sock', '/tmp/mysql.sock', '/var/run/mysqld/mysqld.sock', '/var/mysql/mysql.sock');
foreach ($possiblePaths as $path) {
if (file_exists($path)) {
$opts[] = '--with-mysql-sock=' . $path;
break;
}
}
}
return $opts;
};
$this->variants['sqlite'] = function (Build $build, $prefix = null) {
$opts = array('--with-sqlite3' . ($prefix ? "={$prefix}" : ''));
if ($build->hasVariant('pdo')) {
$opts[] = '--with-pdo-sqlite';
}
return $opts;
};
/**
* The --with-pgsql=[DIR] and --with-pdo-pgsql=[DIR] requires [DIR]/bin/pg_config to be found.
*/
$this->variants['pgsql'] = function (Build $build, $prefix = null) {
$opts = array();
// The names are used from macports
if ($prefix) {
$opts[] = "--with-pgsql={$prefix}";
if ($build->hasVariant('pdo')) {
$opts[] = "--with-pdo-pgsql={$prefix}";
}
return $opts;
}
$bin = Utils::findBin('pg_config');
if (!$bin) {
$bin = first_existing_executable(array('/opt/local/lib/postgresql95/bin/pg_config', '/opt/local/lib/postgresql94/bin/pg_config', '/opt/local/lib/postgresql93/bin/pg_config', '/opt/local/lib/postgresql92/bin/pg_config', '/Library/PostgreSQL/9.5/bin/pg_config', '/Library/PostgreSQL/9.4/bin/pg_config', '/Library/PostgreSQL/9.3/bin/pg_config', '/Library/PostgreSQL/9.2/bin/pg_config', '/Library/PostgreSQL/9.1/bin/pg_config'));
}
if ($bin) {
$opts[] = "--with-pgsql=" . dirname($bin);
if ($build->hasVariant('pdo')) {
$opts[] = "--with-pdo-pgsql=" . dirname($bin);
}
return $opts;
}
$opts[] = "--with-pgsql";
if ($build->hasVariant('pdo')) {
$opts[] = '--with-pdo-pgsql';
}
return $opts;
};
$this->variants['xml'] = function (Build $build) {
$options = array('--enable-dom', '--enable-libxml', '--enable-simplexml', '--enable-xml', '--enable-xmlreader', '--enable-xmlwriter', '--with-xsl');
do {
if ($bin = Utils::findBin('brew')) {
// for brew, it could be "/usr/local/opt/libxml2"
// or "/usr/local/Cellar/libxml2/2.9.3" before install.
if ($output = exec_line("{$bin} --prefix libxml2")) {
if (file_exists($output)) {
$options[] = "--with-libxml-dir={$output}";
break;
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
if ($prefix = Utils::getPkgConfigPrefix('libxml')) {
$options[] = "--with-libxml-dir={$prefix}";
break;
}
if ($prefix = Utils::findIncludePrefix('libxml2/libxml/globals.h')) {
$options[] = "--with-libxml-dir={$prefix}";
break;
}
if ($prefix = Utils::findLibPrefix('libxml2.a')) {
$options[] = "--with-libxml-dir={$prefix}";
break;
}
} while (0);
return $options;
};
$this->variants['xml_all'] = $this->variants['xml'];
$this->variants['apxs2'] = function (Build $build, $prefix = null) {
$a = '--with-apxs2';
if ($prefix) {
return '--with-apxs2=' . $prefix;
}
if ($bin = Utils::findBinByPrefix('apxs2')) {
return '--with-apxs2=' . $bin;
} elseif ($bin = Utils::findBinByPrefix('apxs')) {
return '--with-apxs2=' . $bin;
}
/* Special paths for homebrew */
$possiblePaths = array('/usr/local/opt/httpd24/bin/apxs', '/usr/local/opt/httpd23/bin/apxs', '/usr/local/opt/httpd22/bin/apxs', '/usr/local/opt/httpd21/bin/apxs', '/usr/local/sbin/apxs', '/usr/local/bin/apxs', '/usr/sbin/apxs', '/usr/bin/apxs');
if ($path = first_existing_executable($possiblePaths)) {
$opts[] = "--with-apxs2={$path}";
}
return $a;
// fallback to autoconf finder
};
$this->variants['gettext'] = function (Build $build, $prefix = null) {
if ($prefix) {
return '--with-gettext=' . $prefix;
}
if ($prefix = Utils::findIncludePrefix('libintl.h')) {
return '--with-gettext=' . $prefix;
}
if ($bin = Utils::findBin('brew')) {
if ($output = exec_line("{$bin} --prefix gettext")) {
if (file_exists($output)) {
return "--with-gettext={$output}";
}
echo "homebrew prefix '{$output}' doesn't exist. you forgot to install?\n";
}
}
return '--with-gettext';
};
$this->variants['iconv'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-iconv={$prefix}";
}
/*
* php can't be compile with --with-iconv=/usr because it uses giconv
*
* https://bugs.php.net/bug.php?id=48451
*
// detect include path for iconv.h
if ( $prefix = Utils::find_include_prefix('giconv.h', 'iconv.h') ) {
return "--with-iconv=$prefix";
}
*/
return '--with-iconv';
};
$this->variants['bz2'] = function ($build, $prefix = null) {
if ($prefix) {
return "--with-bz2={$prefix}";
}
if ($prefix = Utils::findIncludePrefix('bzlib.h')) {
return "--with-bz2={$prefix}";
}
return '--with-bz2';
};
$this->variants['ipc'] = function (Build $build) {
return array('--enable-shmop', '--enable-sysvsem', '--enable-sysvshm', '--enable-sysvmsg');
};
$this->variants['gmp'] = function (Build $build, $prefix = null) {
if ($prefix) {
return "--with-gmp={$prefix}";
}
if ($prefix = Utils::findIncludePrefix('gmp.h')) {
return "--with-gmp={$prefix}";
}
return '--with-gmp';
// let autotool to find it.
};
// merge virtual variants with config file
$customVirtualVariants = Config::getConfigParam('variants');
$customVirtualVariantsToAdd = array();
if (!empty($customVirtualVariants)) {
foreach ($customVirtualVariants as $key => $extension) {
// The extension might be null
if (!empty($extension)) {
$customVirtualVariantsToAdd[$key] = array_keys($extension);
}
}
}
$this->virtualVariants = array_merge($customVirtualVariantsToAdd, $this->virtualVariants);
// create +everything variant
$this->virtualVariants['everything'] = array_diff(array_keys($this->variants), array('apxs2', 'all'));
}