Редакция 69 | Только различия | Учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 69 | Редакция 94 | ||
---|---|---|---|
1 | <?php
|
1 | <?php
|
2 | /**
|
2 | /**
|
3 | * PEAR_Builder for building PHP extensions (PECL packages)
|
3 | * PEAR_Builder for building PHP extensions (PECL packages)
|
4 | *
|
4 | *
|
5 | * PHP versions 4 and 5
|
5 | * PHP versions 4 and 5
|
6 | *
|
6 | *
|
7 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
7 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
8 | * that is available through the world-wide-web at the following URI:
|
8 | * that is available through the world-wide-web at the following URI:
|
9 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
9 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
10 | * the PHP License and are unable to obtain it through the web, please
|
10 | * the PHP License and are unable to obtain it through the web, please
|
11 | * send a note to license@php.net so we can mail you a copy immediately.
|
11 | * send a note to license@php.net so we can mail you a copy immediately.
|
12 | *
|
12 | *
|
13 | * @category pear
|
13 | * @category pear
|
14 | * @package PEAR
|
14 | * @package PEAR
|
15 | * @author Stig Bakken <ssb@php.net>
|
15 | * @author Stig Bakken <ssb@php.net>
|
16 | * @author Greg Beaver <cellog@php.net>
|
16 | * @author Greg Beaver <cellog@php.net>
|
17 | * @copyright 1997-2008 The PHP Group
|
17 | * @copyright 1997-2008 The PHP Group
|
18 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
18 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
19 | * @version CVS: $Id: Builder.php,v 1.34 2008/05/12 23:43:21 cellog Exp $
|
19 | * @version CVS: $Id: Builder.php,v 1.34 2008/05/12 23:43:21 cellog Exp $
|
20 | * @link http://pear.php.net/package/PEAR
|
20 | * @link http://pear.php.net/package/PEAR
|
21 | * @since File available since Release 0.1
|
21 | * @since File available since Release 0.1
|
22 | *
|
22 | *
|
23 | * TODO: log output parameters in PECL command line
|
23 | * TODO: log output parameters in PECL command line
|
24 | * TODO: msdev path in configuration
|
24 | * TODO: msdev path in configuration
|
25 | */
|
25 | */
|
26 | 26 | ||
27 | /**
|
27 | /**
|
28 | * Needed for extending PEAR_Builder
|
28 | * Needed for extending PEAR_Builder
|
29 | */
|
29 | */
|
30 | require_once 'PEAR/Common.php'; |
30 | require_once 'PEAR/Common.php'; |
31 | require_once 'PEAR/PackageFile.php'; |
31 | require_once 'PEAR/PackageFile.php'; |
32 | /**
|
32 | /**
|
33 | * Class to handle building (compiling) extensions.
|
33 | * Class to handle building (compiling) extensions.
|
34 | *
|
34 | *
|
35 | * @category pear
|
35 | * @category pear
|
36 | * @package PEAR
|
36 | * @package PEAR
|
37 | * @author Stig Bakken <ssb@php.net>
|
37 | * @author Stig Bakken <ssb@php.net>
|
38 | * @author Greg Beaver <cellog@php.net>
|
38 | * @author Greg Beaver <cellog@php.net>
|
39 | * @copyright 1997-2008 The PHP Group
|
39 | * @copyright 1997-2008 The PHP Group
|
40 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
40 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
41 | * @version Release: 1.7.2
|
41 | * @version Release: 1.7.2
|
42 | * @link http://pear.php.net/package/PEAR
|
42 | * @link http://pear.php.net/package/PEAR
|
43 | * @since Class available since PHP 4.0.2
|
43 | * @since Class available since PHP 4.0.2
|
44 | * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php
|
44 | * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php
|
45 | */
|
45 | */
|
46 | class PEAR_Builder extends PEAR_Common |
46 | class PEAR_Builder extends PEAR_Common |
47 | {
|
47 | {
|
48 | // {{{ properties
|
48 | // {{{ properties
|
49 | 49 | ||
50 | var $php_api_version = 0; |
50 | var $php_api_version = 0; |
51 | var $zend_module_api_no = 0; |
51 | var $zend_module_api_no = 0; |
52 | var $zend_extension_api_no = 0; |
52 | var $zend_extension_api_no = 0; |
53 | 53 | ||
54 | var $extensions_built = array(); |
54 | var $extensions_built = array(); |
55 | 55 | ||
56 | /**
|
56 | /**
|
57 | * @var string Used for reporting when it is not possible to pass function
|
57 | * @var string Used for reporting when it is not possible to pass function
|
58 | * via extra parameter, e.g. log, msdevCallback
|
58 | * via extra parameter, e.g. log, msdevCallback
|
59 | */
|
59 | */
|
60 | var $current_callback = null; |
60 | var $current_callback = null; |
61 | 61 | ||
62 | // used for msdev builds
|
62 | // used for msdev builds
|
63 | var $_lastline = null; |
63 | var $_lastline = null; |
64 | var $_firstline = null; |
64 | var $_firstline = null; |
65 | // }}}
|
65 | // }}}
|
66 | // {{{ constructor
|
66 | // {{{ constructor
|
67 | 67 | ||
68 | /**
|
68 | /**
|
69 | * PEAR_Builder constructor.
|
69 | * PEAR_Builder constructor.
|
70 | *
|
70 | *
|
71 | * @param object $ui user interface object (instance of PEAR_Frontend_*)
|
71 | * @param object $ui user interface object (instance of PEAR_Frontend_*)
|
72 | *
|
72 | *
|
73 | * @access public
|
73 | * @access public
|
74 | */
|
74 | */
|
75 | function PEAR_Builder(&$ui) |
75 | function PEAR_Builder(&$ui) |
76 | {
|
76 | {
|
77 | parent::PEAR_Common(); |
77 | parent::PEAR_Common(); |
78 | $this->setFrontendObject($ui); |
78 | $this->setFrontendObject($ui); |
79 | }
|
79 | }
|
80 | 80 | ||
81 | // }}}
|
81 | // }}}
|
82 | 82 | ||
83 | // {{{ _build_win32()
|
83 | // {{{ _build_win32()
|
84 | 84 | ||
85 | /**
|
85 | /**
|
86 | * Build an extension from source on windows.
|
86 | * Build an extension from source on windows.
|
87 | * requires msdev
|
87 | * requires msdev
|
88 | */
|
88 | */
|
89 | function _build_win32($descfile, $callback = null) |
89 | function _build_win32($descfile, $callback = null) |
90 | {
|
90 | {
|
91 | if (is_object($descfile)) { |
91 | if (is_object($descfile)) { |
92 | $pkg = $descfile; |
92 | $pkg = $descfile; |
93 | $descfile = $pkg->getPackageFile(); |
93 | $descfile = $pkg->getPackageFile(); |
94 | } else { |
94 | } else { |
95 | $pf = &new PEAR_PackageFile($this->config, $this->debug); |
95 | $pf = &new PEAR_PackageFile($this->config, $this->debug); |
96 | $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
96 | $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
97 | if (PEAR::isError($pkg)) { |
97 | if (PEAR::isError($pkg)) { |
98 | return $pkg; |
98 | return $pkg; |
99 | }
|
99 | }
|
100 | }
|
100 | }
|
101 | $dir = dirname($descfile); |
101 | $dir = dirname($descfile); |
102 | $old_cwd = getcwd(); |
102 | $old_cwd = getcwd(); |
103 | 103 | ||
104 | if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { |
104 | if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { |
105 | return $this->raiseError("could not chdir to $dir"); |
105 | return $this->raiseError("could not chdir to $dir"); |
106 | }
|
106 | }
|
107 | // packages that were in a .tar have the packagefile in this directory
|
107 | // packages that were in a .tar have the packagefile in this directory
|
108 | $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); |
108 | $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); |
109 | if (file_exists($dir) && is_dir($vdir)) { |
109 | if (file_exists($dir) && is_dir($vdir)) { |
110 | if (chdir($vdir)) { |
110 | if (chdir($vdir)) { |
111 | $dir = getcwd(); |
111 | $dir = getcwd(); |
112 | } else { |
112 | } else { |
113 | return $this->raiseError("could not chdir to " . realpath($vdir)); |
113 | return $this->raiseError("could not chdir to " . realpath($vdir)); |
114 | }
|
114 | }
|
115 | }
|
115 | }
|
116 | 116 | ||
117 | $this->log(2, "building in $dir"); |
117 | $this->log(2, "building in $dir"); |
118 | 118 | ||
119 | $dsp = $pkg->getPackage().'.dsp'; |
119 | $dsp = $pkg->getPackage().'.dsp'; |
120 | if (!file_exists("$dir/$dsp")) { |
120 | if (!file_exists("$dir/$dsp")) { |
121 | return $this->raiseError("The DSP $dsp does not exist."); |
121 | return $this->raiseError("The DSP $dsp does not exist."); |
122 | }
|
122 | }
|
123 | // XXX TODO: make release build type configurable
|
123 | // XXX TODO: make release build type configurable
|
124 | $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"'; |
124 | $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"'; |
125 | 125 | ||
126 | $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); |
126 | $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); |
127 | if (PEAR::isError($err)) { |
127 | if (PEAR::isError($err)) { |
128 | return $err; |
128 | return $err; |
129 | }
|
129 | }
|
130 | 130 | ||
131 | // figure out the build platform and type
|
131 | // figure out the build platform and type
|
132 | $platform = 'Win32'; |
132 | $platform = 'Win32'; |
133 | $buildtype = 'Release'; |
133 | $buildtype = 'Release'; |
134 | if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { |
134 | if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { |
135 | $platform = $matches[1]; |
135 | $platform = $matches[1]; |
136 | $buildtype = $matches[2]; |
136 | $buildtype = $matches[2]; |
137 | }
|
137 | }
|
138 | 138 | ||
139 | if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) { |
139 | if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) { |
140 | if ($matches[2]) { |
140 | if ($matches[2]) { |
141 | // there were errors in the build
|
141 | // there were errors in the build
|
142 | return $this->raiseError("There were errors during compilation."); |
142 | return $this->raiseError("There were errors during compilation."); |
143 | }
|
143 | }
|
144 | $out = $matches[1]; |
144 | $out = $matches[1]; |
145 | } else { |
145 | } else { |
146 | return $this->raiseError("Did not understand the completion status returned from msdev.exe."); |
146 | return $this->raiseError("Did not understand the completion status returned from msdev.exe."); |
147 | }
|
147 | }
|
148 | 148 | ||
149 | // msdev doesn't tell us the output directory :/
|
149 | // msdev doesn't tell us the output directory :/
|
150 | // open the dsp, find /out and use that directory
|
150 | // open the dsp, find /out and use that directory
|
151 | $dsptext = join(file($dsp),''); |
151 | $dsptext = join(file($dsp),''); |
152 | 152 | ||
153 | // this regex depends on the build platform and type having been
|
153 | // this regex depends on the build platform and type having been
|
154 | // correctly identified above.
|
154 | // correctly identified above.
|
155 | $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. |
155 | $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. |
156 | $pkg->getPackage().'\s-\s'. |
156 | $pkg->getPackage().'\s-\s'. |
157 | $platform.'\s'. |
157 | $platform.'\s'. |
158 | $buildtype.'").*?'. |
158 | $buildtype.'").*?'. |
159 | '\/out:"(.*?)"/is'; |
159 | '\/out:"(.*?)"/is'; |
160 | 160 | ||
161 | if ($dsptext && preg_match($regex,$dsptext,$matches)) { |
161 | if ($dsptext && preg_match($regex,$dsptext,$matches)) { |
162 | // what we get back is a relative path to the output file itself.
|
162 | // what we get back is a relative path to the output file itself.
|
163 | $outfile = realpath($matches[2]); |
163 | $outfile = realpath($matches[2]); |
164 | } else { |
164 | } else { |
165 | return $this->raiseError("Could not retrieve output information from $dsp."); |
165 | return $this->raiseError("Could not retrieve output information from $dsp."); |
166 | }
|
166 | }
|
167 | // realpath returns false if the file doesn't exist
|
167 | // realpath returns false if the file doesn't exist
|
168 | if ($outfile && copy($outfile, "$dir/$out")) { |
168 | if ($outfile && copy($outfile, "$dir/$out")) { |
169 | $outfile = "$dir/$out"; |
169 | $outfile = "$dir/$out"; |
170 | }
|
170 | }
|
171 | 171 | ||
172 | $built_files[] = array( |
172 | $built_files[] = array( |
173 | 'file' => "$outfile", |
173 | 'file' => "$outfile", |
174 | 'php_api' => $this->php_api_version, |
174 | 'php_api' => $this->php_api_version, |
175 | 'zend_mod_api' => $this->zend_module_api_no, |
175 | 'zend_mod_api' => $this->zend_module_api_no, |
176 | 'zend_ext_api' => $this->zend_extension_api_no, |
176 | 'zend_ext_api' => $this->zend_extension_api_no, |
177 | ); |
177 | ); |
178 | 178 | ||
179 | return $built_files; |
179 | return $built_files; |
180 | }
|
180 | }
|
181 | // }}}
|
181 | // }}}
|
182 | 182 | ||
183 | // {{{ msdevCallback()
|
183 | // {{{ msdevCallback()
|
184 | function msdevCallback($what, $data) |
184 | function msdevCallback($what, $data) |
185 | {
|
185 | {
|
186 | if (!$this->_firstline) |
186 | if (!$this->_firstline) |
187 | $this->_firstline = $data; |
187 | $this->_firstline = $data; |
188 | $this->_lastline = $data; |
188 | $this->_lastline = $data; |
189 | call_user_func($this->current_callback, $what, $data); |
189 | call_user_func($this->current_callback, $what, $data); |
190 | }
|
190 | }
|
191 | // }}}
|
191 | // }}}
|
192 | 192 | ||
193 | // {{{ _harventInstDir
|
193 | // {{{ _harventInstDir
|
194 | /**
|
194 | /**
|
195 | * @param string
|
195 | * @param string
|
196 | * @param string
|
196 | * @param string
|
197 | * @param array
|
197 | * @param array
|
198 | * @access private
|
198 | * @access private
|
199 | */
|
199 | */
|
200 | function _harvestInstDir($dest_prefix, $dirname, &$built_files) |
200 | function _harvestInstDir($dest_prefix, $dirname, &$built_files) |
201 | {
|
201 | {
|
202 | $d = opendir($dirname); |
202 | $d = opendir($dirname); |
203 | if (!$d) |
203 | if (!$d) |
204 | return false; |
204 | return false; |
205 | 205 | ||
206 | $ret = true; |
206 | $ret = true; |
207 | while (($ent = readdir($d)) !== false) { |
207 | while (($ent = readdir($d)) !== false) { |
208 | if ($ent{0} == '.') |
208 | if ($ent{0} == '.') |
209 | continue; |
209 | continue; |
210 | 210 | ||
211 | $full = $dirname . DIRECTORY_SEPARATOR . $ent; |
211 | $full = $dirname . DIRECTORY_SEPARATOR . $ent; |
212 | if (is_dir($full)) { |
212 | if (is_dir($full)) { |
213 | if (!$this->_harvestInstDir( |
213 | if (!$this->_harvestInstDir( |
214 | $dest_prefix . DIRECTORY_SEPARATOR . $ent, |
214 | $dest_prefix . DIRECTORY_SEPARATOR . $ent, |
215 | $full, $built_files)) { |
215 | $full, $built_files)) { |
216 | $ret = false; |
216 | $ret = false; |
217 | break; |
217 | break; |
218 | }
|
218 | }
|
219 | } else { |
219 | } else { |
220 | $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; |
220 | $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; |
221 | $built_files[] = array( |
221 | $built_files[] = array( |
222 | 'file' => $full, |
222 | 'file' => $full, |
223 | 'dest' => $dest, |
223 | 'dest' => $dest, |
224 | 'php_api' => $this->php_api_version, |
224 | 'php_api' => $this->php_api_version, |
225 | 'zend_mod_api' => $this->zend_module_api_no, |
225 | 'zend_mod_api' => $this->zend_module_api_no, |
226 | 'zend_ext_api' => $this->zend_extension_api_no, |
226 | 'zend_ext_api' => $this->zend_extension_api_no, |
227 | ); |
227 | ); |
228 | }
|
228 | }
|
229 | }
|
229 | }
|
230 | closedir($d); |
230 | closedir($d); |
231 | return $ret; |
231 | return $ret; |
232 | }
|
232 | }
|
233 | 233 | ||
234 | // }}}
|
234 | // }}}
|
235 | 235 | ||
236 | // {{{ build()
|
236 | // {{{ build()
|
237 | 237 | ||
238 | /**
|
238 | /**
|
239 | * Build an extension from source. Runs "phpize" in the source
|
239 | * Build an extension from source. Runs "phpize" in the source
|
240 | * directory, but compiles in a temporary directory
|
240 | * directory, but compiles in a temporary directory
|
241 | * (/var/tmp/pear-build-USER/PACKAGE-VERSION).
|
241 | * (/var/tmp/pear-build-USER/PACKAGE-VERSION).
|
242 | *
|
242 | *
|
243 | * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
|
243 | * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
|
244 | * a PEAR_PackageFile object
|
244 | * a PEAR_PackageFile object
|
245 | *
|
245 | *
|
246 | * @param mixed $callback callback function used to report output,
|
246 | * @param mixed $callback callback function used to report output,
|
247 | * see PEAR_Builder::_runCommand for details
|
247 | * see PEAR_Builder::_runCommand for details
|
248 | *
|
248 | *
|
249 | * @return array an array of associative arrays with built files,
|
249 | * @return array an array of associative arrays with built files,
|
250 | * format:
|
250 | * format:
|
251 | * array( array( 'file' => '/path/to/ext.so',
|
251 | * array( array( 'file' => '/path/to/ext.so',
|
252 | * 'php_api' => YYYYMMDD,
|
252 | * 'php_api' => YYYYMMDD,
|
253 | * 'zend_mod_api' => YYYYMMDD,
|
253 | * 'zend_mod_api' => YYYYMMDD,
|
254 | * 'zend_ext_api' => YYYYMMDD ),
|
254 | * 'zend_ext_api' => YYYYMMDD ),
|
255 | * ... )
|
255 | * ... )
|
256 | *
|
256 | *
|
257 | * @access public
|
257 | * @access public
|
258 | *
|
258 | *
|
259 | * @see PEAR_Builder::_runCommand
|
259 | * @see PEAR_Builder::_runCommand
|
260 | */
|
260 | */
|
261 | function build($descfile, $callback = null) |
261 | function build($descfile, $callback = null) |
262 | {
|
262 | {
|
263 | $this->current_callback = $callback; |
263 | $this->current_callback = $callback; |
264 | if (PEAR_OS == "Windows") { |
264 | if (PEAR_OS == "Windows") { |
265 | return $this->_build_win32($descfile,$callback); |
265 | return $this->_build_win32($descfile,$callback); |
266 | }
|
266 | }
|
267 | if (PEAR_OS != 'Unix') { |
267 | if (PEAR_OS != 'Unix') { |
268 | return $this->raiseError("building extensions not supported on this platform"); |
268 | return $this->raiseError("building extensions not supported on this platform"); |
269 | }
|
269 | }
|
270 | if (is_object($descfile)) { |
270 | if (is_object($descfile)) { |
271 | $pkg = $descfile; |
271 | $pkg = $descfile; |
272 | $descfile = $pkg->getPackageFile(); |
272 | $descfile = $pkg->getPackageFile(); |
273 | if (is_a($pkg, 'PEAR_PackageFile_v1')) { |
273 | if (is_a($pkg, 'PEAR_PackageFile_v1')) { |
274 | $dir = dirname($descfile); |
274 | $dir = dirname($descfile); |
275 | } else { |
275 | } else { |
276 | $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); |
276 | $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); |
277 | // automatically delete at session end
|
277 | // automatically delete at session end
|
278 | $this->addTempFile($dir); |
278 | $this->addTempFile($dir); |
279 | }
|
279 | }
|
280 | } else { |
280 | } else { |
281 | $pf = &new PEAR_PackageFile($this->config); |
281 | $pf = &new PEAR_PackageFile($this->config); |
282 | $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
282 | $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
283 | if (PEAR::isError($pkg)) { |
283 | if (PEAR::isError($pkg)) { |
284 | return $pkg; |
284 | return $pkg; |
285 | }
|
285 | }
|
286 | $dir = dirname($descfile); |
286 | $dir = dirname($descfile); |
287 | }
|
287 | }
|
288 | $old_cwd = getcwd(); |
288 | $old_cwd = getcwd(); |
289 | if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { |
289 | if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { |
290 | return $this->raiseError("could not chdir to $dir"); |
290 | return $this->raiseError("could not chdir to $dir"); |
291 | }
|
291 | }
|
292 | $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); |
292 | $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); |
293 | if (is_dir($vdir)) { |
293 | if (is_dir($vdir)) { |
294 | chdir($vdir); |
294 | chdir($vdir); |
295 | }
|
295 | }
|
296 | $dir = getcwd(); |
296 | $dir = getcwd(); |
297 | $this->log(2, "building in $dir"); |
297 | $this->log(2, "building in $dir"); |
298 | putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); |
298 | putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); |
299 | $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); |
299 | $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); |
300 | if (PEAR::isError($err)) { |
300 | if (PEAR::isError($err)) { |
301 | return $err; |
301 | return $err; |
302 | }
|
302 | }
|
303 | if (!$err) { |
303 | if (!$err) { |
304 | return $this->raiseError("`phpize' failed"); |
304 | return $this->raiseError("`phpize' failed"); |
305 | }
|
305 | }
|
306 | 306 | ||
307 | // {{{ start of interactive part
|
307 | // {{{ start of interactive part
|
308 | $configure_command = "$dir/configure"; |
308 | $configure_command = "$dir/configure"; |
309 | $configure_options = $pkg->getConfigureOptions(); |
309 | $configure_options = $pkg->getConfigureOptions(); |
310 | if ($configure_options) { |
310 | if ($configure_options) { |
311 | foreach ($configure_options as $o) { |
311 | foreach ($configure_options as $o) { |
312 | $default = array_key_exists('default', $o) ? $o['default'] : null; |
312 | $default = array_key_exists('default', $o) ? $o['default'] : null; |
313 | list($r) = $this->ui->userDialog('build', |
313 | list($r) = $this->ui->userDialog('build', |
314 | array($o['prompt']), |
314 | array($o['prompt']), |
315 | array('text'), |
315 | array('text'), |
316 | array($default)); |
316 | array($default)); |
317 | if (substr($o['name'], 0, 5) == 'with-' && |
317 | if (substr($o['name'], 0, 5) == 'with-' && |
318 | ($r == 'yes' || $r == 'autodetect')) { |
318 | ($r == 'yes' || $r == 'autodetect')) { |
319 | $configure_command .= " --$o[name]"; |
319 | $configure_command .= " --$o[name]"; |
320 | } else { |
320 | } else { |
321 | $configure_command .= " --$o[name]=".trim($r); |
321 | $configure_command .= " --$o[name]=".trim($r); |
322 | }
|
322 | }
|
323 | }
|
323 | }
|
324 | }
|
324 | }
|
325 | // }}} end of interactive part
|
325 | // }}} end of interactive part
|
326 | 326 | ||
327 | // FIXME make configurable
|
327 | // FIXME make configurable
|
328 | if(!$user=getenv('USER')){ |
328 | if(!$user=getenv('USER')){ |
329 | $user='defaultuser'; |
329 | $user='defaultuser'; |
330 | }
|
330 | }
|
331 | $build_basedir = "/var/tmp/pear-build-$user"; |
331 | $build_basedir = "/var/tmp/pear-build-$user"; |
332 | $build_dir = "$build_basedir/$vdir"; |
332 | $build_dir = "$build_basedir/$vdir"; |
333 | $inst_dir = "$build_basedir/install-$vdir"; |
333 | $inst_dir = "$build_basedir/install-$vdir"; |
334 | $this->log(1, "building in $build_dir"); |
334 | $this->log(1, "building in $build_dir"); |
335 | if (is_dir($build_dir)) { |
335 | if (is_dir($build_dir)) { |
336 | System::rm(array('-rf', $build_dir)); |
336 | System::rm(array('-rf', $build_dir)); |
337 | }
|
337 | }
|
338 | if (!System::mkDir(array('-p', $build_dir))) { |
338 | if (!System::mkDir(array('-p', $build_dir))) { |
339 | return $this->raiseError("could not create build dir: $build_dir"); |
339 | return $this->raiseError("could not create build dir: $build_dir"); |
340 | }
|
340 | }
|
341 | $this->addTempFile($build_dir); |
341 | $this->addTempFile($build_dir); |
342 | if (!System::mkDir(array('-p', $inst_dir))) { |
342 | if (!System::mkDir(array('-p', $inst_dir))) { |
343 | return $this->raiseError("could not create temporary install dir: $inst_dir"); |
343 | return $this->raiseError("could not create temporary install dir: $inst_dir"); |
344 | }
|
344 | }
|
345 | $this->addTempFile($inst_dir); |
345 | $this->addTempFile($inst_dir); |
346 | 346 | ||
347 | if (getenv('MAKE')) { |
347 | if (getenv('MAKE')) { |
348 | $make_command = getenv('MAKE'); |
348 | $make_command = getenv('MAKE'); |
349 | } else { |
349 | } else { |
350 | $make_command = 'make'; |
350 | $make_command = 'make'; |
351 | }
|
351 | }
|
352 | $to_run = array( |
352 | $to_run = array( |
353 | $configure_command, |
353 | $configure_command, |
354 | $make_command, |
354 | $make_command, |
355 | "$make_command INSTALL_ROOT=\"$inst_dir\" install", |
355 | "$make_command INSTALL_ROOT=\"$inst_dir\" install", |
356 | "find \"$inst_dir\" | xargs ls -dils"
|
356 | "find \"$inst_dir\" | xargs ls -dils"
|
357 | ); |
357 | ); |
358 | if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { |
358 | if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { |
359 | return $this->raiseError("could not chdir to $build_dir"); |
359 | return $this->raiseError("could not chdir to $build_dir"); |
360 | }
|
360 | }
|
361 | putenv('PHP_PEAR_VERSION=1.7.2'); |
361 | putenv('PHP_PEAR_VERSION=1.7.2'); |
362 | foreach ($to_run as $cmd) { |
362 | foreach ($to_run as $cmd) { |
363 | $err = $this->_runCommand($cmd, $callback); |
363 | $err = $this->_runCommand($cmd, $callback); |
364 | if (PEAR::isError($err)) { |
364 | if (PEAR::isError($err)) { |
365 | chdir($old_cwd); |
365 | chdir($old_cwd); |
366 | return $err; |
366 | return $err; |
367 | }
|
367 | }
|
368 | if (!$err) { |
368 | if (!$err) { |
369 | chdir($old_cwd); |
369 | chdir($old_cwd); |
370 | return $this->raiseError("`$cmd' failed"); |
370 | return $this->raiseError("`$cmd' failed"); |
371 | }
|
371 | }
|
372 | }
|
372 | }
|
373 | if (!($dp = opendir("modules"))) { |
373 | if (!($dp = opendir("modules"))) { |
374 | chdir($old_cwd); |
374 | chdir($old_cwd); |
375 | return $this->raiseError("no `modules' directory found"); |
375 | return $this->raiseError("no `modules' directory found"); |
376 | }
|
376 | }
|
377 | $built_files = array(); |
377 | $built_files = array(); |
378 | $prefix = exec("php-config --prefix"); |
378 | $prefix = exec("php-config --prefix"); |
379 | $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); |
379 | $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); |
380 | chdir($old_cwd); |
380 | chdir($old_cwd); |
381 | return $built_files; |
381 | return $built_files; |
382 | }
|
382 | }
|
383 | 383 | ||
384 | // }}}
|
384 | // }}}
|
385 | // {{{ phpizeCallback()
|
385 | // {{{ phpizeCallback()
|
386 | 386 | ||
387 | /**
|
387 | /**
|
388 | * Message callback function used when running the "phpize"
|
388 | * Message callback function used when running the "phpize"
|
389 | * program. Extracts the API numbers used. Ignores other message
|
389 | * program. Extracts the API numbers used. Ignores other message
|
390 | * types than "cmdoutput".
|
390 | * types than "cmdoutput".
|
391 | *
|
391 | *
|
392 | * @param string $what the type of message
|
392 | * @param string $what the type of message
|
393 | * @param mixed $data the message
|
393 | * @param mixed $data the message
|
394 | *
|
394 | *
|
395 | * @return void
|
395 | * @return void
|
396 | *
|
396 | *
|
397 | * @access public
|
397 | * @access public
|
398 | */
|
398 | */
|
399 | function phpizeCallback($what, $data) |
399 | function phpizeCallback($what, $data) |
400 | {
|
400 | {
|
401 | if ($what != 'cmdoutput') { |
401 | if ($what != 'cmdoutput') { |
402 | return; |
402 | return; |
403 | }
|
403 | }
|
404 | $this->log(1, rtrim($data)); |
404 | $this->log(1, rtrim($data)); |
405 | if (preg_match('/You should update your .aclocal.m4/', $data)) { |
405 | if (preg_match('/You should update your .aclocal.m4/', $data)) { |
406 | return; |
406 | return; |
407 | }
|
407 | }
|
408 | $matches = array(); |
408 | $matches = array(); |
409 | if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { |
409 | if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { |
410 | $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); |
410 | $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); |
411 | $apino = (int)$matches[2]; |
411 | $apino = (int)$matches[2]; |
412 | if (isset($this->$member)) { |
412 | if (isset($this->$member)) { |
413 | $this->$member = $apino; |
413 | $this->$member = $apino; |
414 | //$msg = sprintf("%-22s : %d", $matches[1], $apino);
|
414 | //$msg = sprintf("%-22s : %d", $matches[1], $apino);
|
415 | //$this->log(1, $msg);
|
415 | //$this->log(1, $msg);
|
416 | }
|
416 | }
|
417 | }
|
417 | }
|
418 | }
|
418 | }
|
419 | 419 | ||
420 | // }}}
|
420 | // }}}
|
421 | // {{{ _runCommand()
|
421 | // {{{ _runCommand()
|
422 | 422 | ||
423 | /**
|
423 | /**
|
424 | * Run an external command, using a message callback to report
|
424 | * Run an external command, using a message callback to report
|
425 | * output. The command will be run through popen and output is
|
425 | * output. The command will be run through popen and output is
|
426 | * reported for every line with a "cmdoutput" message with the
|
426 | * reported for every line with a "cmdoutput" message with the
|
427 | * line string, including newlines, as payload.
|
427 | * line string, including newlines, as payload.
|
428 | *
|
428 | *
|
429 | * @param string $command the command to run
|
429 | * @param string $command the command to run
|
430 | *
|
430 | *
|
431 | * @param mixed $callback (optional) function to use as message
|
431 | * @param mixed $callback (optional) function to use as message
|
432 | * callback
|
432 | * callback
|
433 | *
|
433 | *
|
434 | * @return bool whether the command was successful (exit code 0
|
434 | * @return bool whether the command was successful (exit code 0
|
435 | * means success, any other means failure)
|
435 | * means success, any other means failure)
|
436 | *
|
436 | *
|
437 | * @access private
|
437 | * @access private
|
438 | */
|
438 | */
|
439 | function _runCommand($command, $callback = null) |
439 | function _runCommand($command, $callback = null) |
440 | {
|
440 | {
|
441 | $this->log(1, "running: $command"); |
441 | $this->log(1, "running: $command"); |
442 | $pp = popen("$command 2>&1", "r"); |
442 | $pp = popen("$command 2>&1", "r"); |
443 | if (!$pp) { |
443 | if (!$pp) { |
444 | return $this->raiseError("failed to run `$command'"); |
444 | return $this->raiseError("failed to run `$command'"); |
445 | }
|
445 | }
|
446 | if ($callback && $callback[0]->debug == 1) { |
446 | if ($callback && $callback[0]->debug == 1) { |
447 | $olddbg = $callback[0]->debug; |
447 | $olddbg = $callback[0]->debug; |
448 | $callback[0]->debug = 2; |
448 | $callback[0]->debug = 2; |
449 | }
|
449 | }
|
450 | 450 | ||
451 | while ($line = fgets($pp, 1024)) { |
451 | while ($line = fgets($pp, 1024)) { |
452 | if ($callback) { |
452 | if ($callback) { |
453 | call_user_func($callback, 'cmdoutput', $line); |
453 | call_user_func($callback, 'cmdoutput', $line); |
454 | } else { |
454 | } else { |
455 | $this->log(2, rtrim($line)); |
455 | $this->log(2, rtrim($line)); |
456 | }
|
456 | }
|
457 | }
|
457 | }
|
458 | if ($callback && isset($olddbg)) { |
458 | if ($callback && isset($olddbg)) { |
459 | $callback[0]->debug = $olddbg; |
459 | $callback[0]->debug = $olddbg; |
460 | }
|
460 | }
|
461 | if (is_resource($pp)) { |
461 | if (is_resource($pp)) { |
462 | $exitcode = pclose($pp); |
462 | $exitcode = pclose($pp); |
463 | } else { |
463 | } else { |
464 | $exitcode = -1; |
464 | $exitcode = -1; |
465 | }
|
465 | }
|
466 | return ($exitcode == 0); |
466 | return ($exitcode == 0); |
467 | }
|
467 | }
|
468 | 468 | ||
469 | // }}}
|
469 | // }}}
|
470 | // {{{ log()
|
470 | // {{{ log()
|
471 | 471 | ||
472 | function log($level, $msg) |
472 | function log($level, $msg) |
473 | {
|
473 | {
|
474 | if ($this->current_callback) { |
474 | if ($this->current_callback) { |
475 | if ($this->debug >= $level) { |
475 | if ($this->debug >= $level) { |
476 | call_user_func($this->current_callback, 'output', $msg); |
476 | call_user_func($this->current_callback, 'output', $msg); |
477 | }
|
477 | }
|
478 | return; |
478 | return; |
479 | }
|
479 | }
|
480 | return PEAR_Common::log($level, $msg); |
480 | return PEAR_Common::log($level, $msg); |
481 | }
|
481 | }
|
482 | 482 | ||
483 | // }}}
|
483 | // }}}
|
484 | }
|
484 | }
|
485 | 485 | ||
486 | ?>
|
486 | ?>
|
487 | 487 |