Source for file Builder.php
Documentation is available at Builder.php
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// $Id: Builder.php,v 1.16.2.3 2005/02/17 17:55:01 cellog Exp $
require_once 'PEAR/Common.php';
* Class to handle building (compiling) extensions.
class PEAR_Builder extends PEAR_Common
var $php_api_version = 0;
var $zend_module_api_no = 0;
var $zend_extension_api_no = 0;
var $extensions_built = array ();
var $current_callback = null;
* PEAR_Builder constructor.
* @param object $ui user interface object (instance of PEAR_Frontend_*)
function PEAR_Builder (&$ui)
$this->setFrontendObject ($ui);
* Build an extension from source on windows.
function _build_win32 ($descfile, $callback = null )
if (PEAR ::isError ($info = $this->infoFromDescriptionFile ($descfile))) {
return $this->raiseError (" could not chdir to $dir" );
$this->log (2 , " building in $dir" );
$dsp = $info['package']. '.dsp';
return $this->raiseError (" The DSP $dsp does not exist." );
// XXX TODO: make release build type configurable
$command = 'msdev '. $dsp. ' /MAKE "'. $info['package']. ' - Release"';
$this->current_callback = $callback;
$err = $this->_runCommand ($command, array (&$this, 'msdevCallback'));
if (PEAR ::isError ($err)) {
// figure out the build platform and type
if (preg_match('/.*?'. $info['package']. '\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
$buildtype = $matches[2 ];
if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) {
// there were errors in the build
return $this->raiseError ("There were errors during compilation.");
return $this->raiseError ("Did not understand the completion status returned from msdev.exe.");
// msdev doesn't tell us the output directory :/
// open the dsp, find /out and use that directory
// this regex depends on the build platform and type having been
// correctly identified above.
$regex = '/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
$info['package']. '\s-\s'.
if ($dsptext && preg_match($regex,$dsptext,$matches)) {
// what we get back is a relative path to the output file itself.
return $this->raiseError (" Could not retrieve output information from $dsp." );
if (@copy($outfile, " $dir/$out" )) {
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
function msdevCallback ($what, $data)
$this->_firstline = $data;
$this->_lastline = $data;
function _harvestInstDir ($dest_prefix, $dirname, &$built_files)
while (($ent = readdir($d)) !== false ) {
$full = $dirname . DIRECTORY_SEPARATOR . $ent;
if (!$this->_harvestInstDir (
$dest_prefix . DIRECTORY_SEPARATOR . $ent,
$dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
* Build an extension from source. Runs "phpize" in the source
* directory, but compiles in a temporary directory
* (/var/tmp/pear-build-USER/PACKAGE-VERSION).
* @param string $descfile path to XML package description file
* @param mixed $callback callback function used to report output,
* see PEAR_Builder::_runCommand for details
* @return array an array of associative arrays with built files,
* array( array( 'file' => '/path/to/ext.so',
* 'zend_mod_api' => YYYYMMDD,
* 'zend_ext_api' => YYYYMMDD ),
* @see PEAR_Builder::_runCommand
* @see PEAR_Common::infoFromDescriptionFile
function build ($descfile, $callback = null )
return $this->_build_win32 ($descfile,$callback);
return $this->raiseError ("building extensions not supported on this platform");
if (PEAR ::isError ($info = $this->infoFromDescriptionFile ($descfile))) {
return $this->raiseError (" could not chdir to $dir" );
$vdir = " $info[package]-$info[version]";
$this->log (2 , " building in $dir" );
$this->current_callback = $callback;
putenv('PATH=' . $this->config->get ('bin_dir') . ':' . getenv('PATH'));
$err = $this->_runCommand ("phpize", array (&$this, 'phpizeCallback'));
if (PEAR ::isError ($err)) {
return $this->raiseError ("`phpize' failed");
// {{{ start of interactive part
$configure_command = " $dir/configure";
if (isset ($info['configure_options'])) {
foreach ($info['configure_options'] as $o) {
list ($r) = $this->ui->userDialog ('build',
if (substr($o['name'], 0 , 5 ) == 'with-' &&
($r == 'yes' || $r == 'autodetect')) {
$configure_command .= " --$o[name]";
$configure_command .= " --$o[name]=". trim($r);
// }}} end of interactive part
// FIXME make configurable
$build_basedir = " /var/tmp/pear-build-$user";
$build_dir = " $build_basedir/$info[package]-$info[version]";
$inst_dir = " $build_basedir/install-$info[package]-$info[version]";
$this->log (1 , " building in $build_dir" );
return $this->raiseError (" could not create build dir: $build_dir" );
$this->addTempFile ($build_dir);
return $this->raiseError (" could not create temporary install dir: $inst_dir" );
$this->addTempFile ($inst_dir);
$make_command = getenv('MAKE');
" $make_command INSTALL_ROOT=\"$inst_dir\" install" ,
if (!@chdir($build_dir)) {
return $this->raiseError (" could not chdir to $build_dir" );
putenv('PHP_PEAR_VERSION=@PEAR-VER@');
foreach ($to_run as $cmd) {
$err = $this->_runCommand ($cmd, $callback);
if (PEAR ::isError ($err)) {
return $this->raiseError (" `$cmd' failed" );
return $this->raiseError ("no `modules' directory found");
$prefix = exec("php-config --prefix");
$this->_harvestInstDir ($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
* Message callback function used when running the "phpize"
* program. Extracts the API numbers used. Ignores other message
* types than "cmdoutput".
* @param string $what the type of message
* @param mixed $data the message
function phpizeCallback ($what, $data)
if ($what != 'cmdoutput') {
$this->log (1 , rtrim($data));
if (preg_match('/You should update your .aclocal.m4/', $data)) {
if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
$apino = (int) $matches[2 ];
if (isset ($this->$member)) {
//$msg = sprintf("%-22s : %d", $matches[1], $apino);
* Run an external command, using a message callback to report
* output. The command will be run through popen and output is
* reported for every line with a "cmdoutput" message with the
* line string, including newlines, as payload.
* @param string $command the command to run
* @param mixed $callback (optional) function to use as message
* @return bool whether the command was successful (exit code 0
* means success, any other means failure)
function _runCommand ($command, $callback = null )
$this->log (1 , " running: $command" );
$pp = @popen(" $command 2>&1" , "r");
return $this->raiseError (" failed to run `$command'" );
if ($callback && $callback[0 ]->debug == 1 ) {
$olddbg = $callback[0 ]->debug;
while ($line = fgets($pp, 1024 )) {
$this->log (2 , rtrim($line));
if ($callback && isset ($olddbg)) {
$callback[0 ]->debug = $olddbg;
function log ($level, $msg)
if ($this->current_callback) {
if ($this->debug >= $level) {
return PEAR_Common ::log ($level, $msg);
Documentation generated on Mon, 11 Mar 2019 14:23:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|