PageRenderTime 24ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/win32/build/mkdist.php

https://gitlab.com/renyunhuang/php-src
PHP | 574 lines | 404 code | 88 blank | 82 comment | 89 complexity | b3e783d18fff63b47f6589f10e3d0223 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. <?php # $Id$
  2. /* piece together a windows binary distro */
  3. $build_dir = $argv[1];
  4. $php_build_dir = $argv[2];
  5. $phpdll = $argv[3];
  6. $sapi_targets = explode(" ", $argv[4]);
  7. $ext_targets = explode(" ", $argv[5]);
  8. $pecl_targets = explode(" ", $argv[6]);
  9. $snapshot_template = $argv[7];
  10. $is_debug = preg_match("/^debug/i", $build_dir);
  11. echo "Making dist for $build_dir\n";
  12. $dist_dir = $build_dir . "/php-" . phpversion();
  13. $test_dir = $build_dir . "/php-test-pack-" . phpversion();
  14. $pecl_dir = $build_dir . "/pecl-" . phpversion();
  15. @mkdir($dist_dir);
  16. @mkdir("$dist_dir/ext");
  17. @mkdir("$dist_dir/dev");
  18. @mkdir("$dist_dir/extras");
  19. @mkdir($pecl_dir);
  20. /* figure out additional DLL's that are required */
  21. $extra_dll_deps = array();
  22. $per_module_deps = array();
  23. $pecl_dll_deps = array();
  24. function get_depends($module)
  25. {
  26. static $no_dist = array(
  27. /* windows system dlls that should not be bundled */
  28. 'advapi32.dll', 'comdlg32.dll', 'crypt32.dll', 'gdi32.dll', 'kernel32.dll', 'ntdll.dll',
  29. 'odbc32.dll', 'ole32.dll', 'oleaut32.dll', 'rpcrt4.dll',
  30. 'shell32.dll', 'shlwapi.dll', 'user32.dll', 'ws2_32.dll', 'ws2help.dll',
  31. 'comctl32.dll', 'winmm.dll', 'wsock32.dll', 'winspool.drv', 'msasn1.dll',
  32. 'secur32.dll', 'netapi32.dll',
  33. /* apache */
  34. 'apachecore.dll',
  35. /* apache 2 */
  36. 'libhttpd.dll', 'libapr.dll', 'libaprutil.dll','libapr-1.dll', 'libaprutil-1.dll',
  37. /* pi3web */
  38. 'piapi.dll', 'pi3api.dll',
  39. /* nsapi */
  40. 'ns-httpd30.dll', 'ns-httpd35.dll', 'ns-httpd36.dll', 'ns-httpd40.dll',
  41. /* oracle */
  42. 'oci.dll', 'ociw32.dll',
  43. /* sybase */
  44. 'libcs.dll', 'libct.dll',
  45. /* firebird */
  46. 'fbclient.dll',
  47. /* visual C++; mscvrt.dll is present on everyones system,
  48. * but the debug version (msvcrtd.dll) and those from visual studio.net
  49. * (msvcrt7x.dll) are not */
  50. 'msvcrt.dll',
  51. 'msvcr90.dll',
  52. 'wldap32.dll'
  53. );
  54. global $build_dir, $extra_dll_deps, $ext_targets, $sapi_targets, $pecl_targets, $phpdll, $per_module_deps, $pecl_dll_deps;
  55. $bd = strtolower(realpath($build_dir));
  56. $is_pecl = in_array($module, $pecl_targets);
  57. $cmd = "$GLOBALS[build_dir]\\deplister.exe \"$module\" \"$GLOBALS[build_dir]\"";
  58. $proc = proc_open($cmd,
  59. array(1 => array("pipe", "w")),
  60. $pipes);
  61. $n = 0;
  62. while (($line = fgetcsv($pipes[1]))) {
  63. $n++;
  64. $dep = strtolower($line[0]);
  65. $depbase = basename($dep);
  66. /* ignore stuff in our build dir, but only if it is
  67. * one of our targets */
  68. if (((in_array($depbase, $sapi_targets) ||
  69. in_array($depbase, $ext_targets) || in_array($depbase, $pecl_targets)) ||
  70. $depbase == $phpdll) && file_exists($GLOBALS['build_dir'] . "/$depbase")) {
  71. continue;
  72. }
  73. /* ignore some well-known system dlls */
  74. if (in_array(basename($dep), $no_dist)) {
  75. continue;
  76. }
  77. if ($is_pecl) {
  78. if (!in_array($dep, $pecl_dll_deps)) {
  79. $pecl_dll_deps[] = $dep;
  80. }
  81. } else {
  82. if (!in_array($dep, $extra_dll_deps)) {
  83. $extra_dll_deps[] = $dep;
  84. }
  85. }
  86. $per_module_deps[basename($module)][] = $dep;
  87. }
  88. fclose($pipes[1]);
  89. proc_close($proc);
  90. //echo "Module $module [$n lines]\n";
  91. }
  92. function copy_file_list($source_dir, $dest_dir, $list)
  93. {
  94. global $is_debug, $dist_dir;
  95. foreach ($list as $item) {
  96. if (empty($item)) {
  97. continue;
  98. } elseif (!is_file($source_dir . DIRECTORY_SEPARATOR . $item)) {
  99. echo "WARNING: $item not found\n";
  100. continue;
  101. }
  102. echo "Copying $item from $source_dir to $dest_dir\n";
  103. copy($source_dir . DIRECTORY_SEPARATOR . $item, $dest_dir . DIRECTORY_SEPARATOR . $item);
  104. if ($is_debug) {
  105. $itemdb = preg_replace("/\.(exe|dll|lib)$/i", ".pdb", $item);
  106. if (file_exists("$source_dir/$itemdb")) {
  107. copy("$source_dir/$itemdb", "$dist_dir/dev/$itemdb");
  108. }
  109. }
  110. if (preg_match("/\.(exe|dll)$/i", $item)) {
  111. get_depends($source_dir . '/' . $item);
  112. }
  113. }
  114. }
  115. function copy_text_file($source, $dest)
  116. {
  117. $text = file_get_contents($source);
  118. $text = preg_replace("/(\r\n?)|\n/", "\r\n", $text);
  119. $fp = fopen($dest, "w");
  120. fwrite($fp, $text);
  121. fclose($fp);
  122. }
  123. /* very light-weight function to extract a single named file from
  124. * a gzipped tarball. This makes assumptions about the files
  125. * based on the PEAR info set in $packages. */
  126. function extract_file_from_tarball($pkg, $filename, $dest_dir) /* {{{ */
  127. {
  128. global $packages;
  129. $name = $pkg . '-' . $packages[$pkg];
  130. $tarball = $dest_dir . "/" . $name . '.tgz';
  131. $filename = $name . '/' . $filename;
  132. $destfilename = $dest_dir . "/" . basename($filename);
  133. $fp = gzopen($tarball, 'rb');
  134. $done = false;
  135. do {
  136. /* read the header */
  137. $hdr_data = gzread($fp, 512);
  138. if (strlen($hdr_data) == 0)
  139. break;
  140. $checksum = 0;
  141. for ($i = 0; $i < 148; $i++)
  142. $checksum += ord($hdr_data{$i});
  143. for ($i = 148; $i < 156; $i++)
  144. $checksum += 32;
  145. for ($i = 156; $i < 512; $i++)
  146. $checksum += ord($hdr_data{$i});
  147. $hdr = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $hdr_data);
  148. $hdr['checksum'] = octdec(trim($hdr['checksum']));
  149. if ($hdr['checksum'] != $checksum) {
  150. echo "Checksum for $tarball $hdr[filename] is invalid\n";
  151. print_r($hdr);
  152. return;
  153. }
  154. $hdr['size'] = octdec(trim($hdr['size']));
  155. echo "File: $hdr[filename] $hdr[size]\n";
  156. if ($filename == $hdr['filename']) {
  157. echo "Found the file we want\n";
  158. $dest = fopen($destfilename, 'wb');
  159. $x = stream_copy_to_stream($fp, $dest, $hdr['size']);
  160. fclose($dest);
  161. echo "Wrote $x bytes into $destfilename\n";
  162. break;
  163. }
  164. /* skip body of the file */
  165. $size = 512 * ceil((int)$hdr['size'] / 512);
  166. echo "Skipping $size bytes\n";
  167. gzseek($fp, gztell($fp) + $size);
  168. } while (!$done);
  169. } /* }}} */
  170. /* the core dll */
  171. copy("$build_dir/php.exe", "$dist_dir/php.exe");
  172. copy("$build_dir/$phpdll", "$dist_dir/$phpdll");
  173. /* and the .lib goes into dev */
  174. $phplib = str_replace(".dll", ".lib", $phpdll);
  175. copy("$build_dir/$phplib", "$dist_dir/dev/$phplib");
  176. /* debug builds; copy the symbols too */
  177. if ($is_debug) {
  178. $phppdb = str_replace(".dll", ".pdb", $phpdll);
  179. copy("$build_dir/$phppdb", "$dist_dir/dev/$phppdb");
  180. }
  181. /* copy the sapi */
  182. copy_file_list($build_dir, "$dist_dir", $sapi_targets);
  183. /* copy the extensions */
  184. copy_file_list($build_dir, "$dist_dir/ext", $ext_targets);
  185. /* pecl sapi and extensions */
  186. if(sizeof($pecl_targets)) {
  187. copy_file_list($build_dir, $pecl_dir, $pecl_targets);
  188. }
  189. /* populate reading material */
  190. $text_files = array(
  191. "LICENSE" => "license.txt",
  192. "NEWS" => "news.txt",
  193. "README.REDIST.BINS" => "readme-redist-bins.txt",
  194. "php.ini-development" => "php.ini-development",
  195. "php.ini-production" => "php.ini-production",
  196. "win32/install.txt" => "install.txt",
  197. );
  198. foreach ($text_files as $src => $dest) {
  199. copy_text_file($src, $dist_dir . '/' . $dest);
  200. }
  201. /* general other files */
  202. $general_files = array(
  203. "php.gif" => "php.gif",
  204. "$GLOBALS[build_dir]\\deplister.exe" => "deplister.exe",
  205. );
  206. foreach ($general_files as $src => $dest) {
  207. copy($src, $dist_dir . '/' . $dest);
  208. }
  209. /* include a snapshot identifier */
  210. $branch = "HEAD"; // TODO - determine this from SVN branche name
  211. $fp = fopen("$dist_dir/snapshot.txt", "w");
  212. $now = date("r");
  213. $version = phpversion();
  214. fwrite($fp, <<<EOT
  215. This snapshot was automatically generated on
  216. $now
  217. Version: $version
  218. Branch: $branch
  219. Build: $build_dir
  220. EOT
  221. );
  222. /* list build-in extensions */
  223. $exts = get_loaded_extensions();
  224. fprintf($fp, "\r\nBuilt-in Extensions\r\n");
  225. fwrite($fp, "===========================\r\n");
  226. foreach ($exts as $ext) {
  227. fprintf($fp, "%s\r\n", $ext);
  228. }
  229. fwrite($fp, "\r\n\r\n");
  230. /* list dependencies */
  231. fprintf($fp, "Dependency information:\r\n");
  232. foreach ($per_module_deps as $modulename => $deps) {
  233. if (in_array($modulename, $pecl_targets))
  234. continue;
  235. fprintf($fp, "Module: %s\r\n", $modulename);
  236. fwrite($fp, "===========================\r\n");
  237. foreach ($deps as $dll) {
  238. fprintf($fp, "\t%s\r\n", basename($dll));
  239. }
  240. fwrite($fp, "\r\n");
  241. }
  242. fclose($fp);
  243. /* Now add those dependencies */
  244. foreach ($extra_dll_deps as $dll) {
  245. if (!file_exists($dll)) {
  246. /* try template dir */
  247. $tdll = $snapshot_template . "/dlls/" . basename($dll);
  248. if (!file_exists($tdll)) {
  249. $tdll = $php_build_dir . '/bin/' . basename($dll);
  250. if (!file_exists($tdll)) {
  251. echo "WARNING: distro depends on $dll, but could not find it on your system\n";
  252. continue;
  253. }
  254. }
  255. $dll = $tdll;
  256. }
  257. copy($dll, "$dist_dir/" . basename($dll));
  258. }
  259. /* TODO:
  260. add sanity check and test if all required DLLs are present, per version
  261. This version works at least for 3.6, 3.8 and 4.0 (5.3-vc6, 5.3-vc9 and HEAD).
  262. Add ADD_DLLS to add extra DLLs like dynamic dependencies for standard
  263. deps. For example, libenchant.dll loads libenchant_myspell.dll or
  264. libenchant_ispell.dll
  265. */
  266. $ICU_DLLS = $php_build_dir . '/bin/icu*.dll';
  267. foreach (glob($ICU_DLLS) as $filename) {
  268. copy($filename, "$dist_dir/" . basename($filename));
  269. }
  270. $ENCHANT_DLLS = array(
  271. array('', 'glib-2.dll'),
  272. array('', 'gmodule-2.dll'),
  273. array('lib/enchant', 'libenchant_myspell.dll'),
  274. array('lib/enchant', 'libenchant_ispell.dll'),
  275. );
  276. foreach ($ENCHANT_DLLS as $dll) {
  277. $dest = "$dist_dir/$dll[0]";
  278. $filename = $dll[1];
  279. if (!file_exists("$dest") || !is_dir("$dest")) {
  280. if (!mkdir("$dest", 0777, true)) {
  281. echo "WARNING: couldn't create '$dest' for enchant plugins ";
  282. }
  283. }
  284. if (!copy($php_build_dir . '/bin/' . $filename, "$dest/" . basename($filename))) {
  285. echo "WARNING: couldn't copy $filename into the dist dir";
  286. }
  287. }
  288. $SASL_DLLS = $php_build_dir . "/bin/sasl2/sasl*.dll";
  289. $fls = glob($SASL_DLLS);
  290. if (!empty($fls)) {
  291. $sasl_dest_dir = "$dist_dir/sasl2";
  292. if (!file_exists($sasl_dest_dir) || !is_dir($sasl_dest_dir)) {
  293. if (!mkdir("$sasl_dest_dir", 0777, true)) {
  294. echo "WARNING: couldn't create '$sasl_dest_dir' for SASL2 auth plugins ";
  295. }
  296. }
  297. foreach ($fls as $fl) {
  298. if (!copy($fl, "$sasl_dest_dir/" . basename($fl))) {
  299. echo "WARNING: couldn't copy $fl into the $sasl_dest_dir";
  300. }
  301. }
  302. }
  303. /* and those for pecl */
  304. foreach ($pecl_dll_deps as $dll) {
  305. if (in_array($dll, $extra_dll_deps)) {
  306. /* already in main distro */
  307. continue;
  308. }
  309. if (!file_exists($dll)) {
  310. /* try template dir */
  311. $tdll = $snapshot_template . "/dlls/" . basename($dll);
  312. if (!file_exists($tdll)) {
  313. echo "WARNING: distro depends on $dll, but could not find it on your system\n";
  314. continue;
  315. }
  316. $dll = $tdll;
  317. }
  318. copy($dll, "$pecl_dir/" . basename($dll));
  319. }
  320. function copy_dir($source, $dest)
  321. {
  322. if (!is_dir($dest)) {
  323. if (!mkdir($dest)) {
  324. return false;
  325. }
  326. }
  327. $d = opendir($source);
  328. while (($f = readdir($d)) !== false) {
  329. if ($f == '.' || $f == '..' || $f == '.svn') {
  330. continue;
  331. }
  332. $fs = $source . '/' . $f;
  333. $fd = $dest . '/' . $f;
  334. if (is_dir($fs)) {
  335. copy_dir($fs, $fd);
  336. } else {
  337. copy($fs, $fd);
  338. }
  339. }
  340. closedir($d);
  341. }
  342. function copy_test_dir($directory, $dest)
  343. {
  344. if(substr($directory,-1) == '/') {
  345. $directory = substr($directory,0,-1);
  346. }
  347. if ($directory == 'tests' || $directory == 'examples') {
  348. if (!is_dir($dest . '/tests')) {
  349. mkdir($dest . '/tests', 0775, true);
  350. }
  351. copy_dir($directory, $dest . '/tests/');
  352. return false;
  353. }
  354. if(!file_exists($directory) || !is_dir($directory)) {
  355. echo "failed... $directory\n";
  356. return FALSE;
  357. }
  358. $directory_list = opendir($directory);
  359. while (FALSE !== ($file = readdir($directory_list))) {
  360. $full_path = $directory . '/' . $file;
  361. if($file != '.' && $file != '..' && $file != '.svn' && is_dir($full_path)) {
  362. if ($file == 'tests' || $file == 'examples') {
  363. if (!is_dir($dest . '/' . $full_path)) {
  364. mkdir($dest . '/' . $full_path , 0775, true);
  365. }
  366. copy_dir($full_path, $dest . '/' . $full_path . '/');
  367. continue;
  368. } else {
  369. copy_test_dir($full_path, $dest);
  370. }
  371. }
  372. }
  373. closedir($directory_list);
  374. }
  375. function make_phar_dot_phar($dist_dir)
  376. {
  377. if (!extension_loaded('phar')) {
  378. return;
  379. }
  380. $path_to_phar = realpath(__DIR__ . '/../../ext/phar');
  381. echo "Generating pharcommand.phar\n";
  382. $phar = new Phar($dist_dir . '/pharcommand.phar', 0, 'pharcommand');
  383. foreach (new DirectoryIterator($path_to_phar . '/phar') as $file) {
  384. if ($file->isDir() || $file == 'phar.php') {
  385. continue;
  386. }
  387. echo 'adding ', $file, "\n";
  388. $phar[(string) $file] = file_get_contents($path_to_phar. '/phar/' . $file);
  389. }
  390. $phar->setSignatureAlgorithm(Phar::SHA1);
  391. $stub = file($path_to_phar . '/phar/phar.php');
  392. unset($stub[0]); // remove hashbang
  393. $phar->setStub(implode('', $stub));
  394. echo "Creating phar.phar.bat\n";
  395. file_put_contents($dist_dir . '/phar.phar.bat', "\"%~dp0php.exe\" \"%~dp0pharcommand.phar\" %*\r\n");
  396. }
  397. if (!is_dir($test_dir)) {
  398. mkdir($test_dir);
  399. }
  400. $dirs = array(
  401. 'ext',
  402. 'Sapi',
  403. 'Zend',
  404. 'tests'
  405. );
  406. foreach ($dirs as $dir) {
  407. copy_test_dir($dir, $test_dir);
  408. }
  409. copy('run-tests.php', $test_dir . '/run-test.php');
  410. /* change this next line to true to use good-old
  411. * hand-assembled go-pear-bundle from the snapshot template */
  412. $use_pear_template = true;
  413. if (!$use_pear_template) {
  414. /* Let's do a PEAR-less pear setup */
  415. mkdir("$dist_dir/PEAR");
  416. mkdir("$dist_dir/PEAR/go-pear-bundle");
  417. /* grab the bootstrap script */
  418. echo "Downloading go-pear\n";
  419. copy("http://pear.php.net/go-pear", "$dist_dir/PEAR/go-pear.php");
  420. /* import the package list -- sets $packages variable */
  421. include "pear/go-pear-list.php";
  422. /* download the packages into the destination */
  423. echo "Fetching packages\n";
  424. foreach ($packages as $name => $version) {
  425. $filename = "$name-$version.tgz";
  426. $destfilename = "$dist_dir/PEAR/go-pear-bundle/$filename";
  427. if (file_exists($destfilename))
  428. continue;
  429. $url = "http://pear.php.net/get/$filename";
  430. echo "Downloading $name from $url\n";
  431. flush();
  432. copy($url, $destfilename);
  433. }
  434. echo "Download complete. Extracting bootstrap files\n";
  435. /* Now, we want PEAR.php, Getopt.php (Console_Getopt) and Tar.php (Archive_Tar)
  436. * broken out of the tarballs */
  437. extract_file_from_tarball('PEAR', 'PEAR.php', "$dist_dir/PEAR/go-pear-bundle");
  438. extract_file_from_tarball('Archive_Tar', 'Archive/Tar.php', "$dist_dir/PEAR/go-pear-bundle");
  439. extract_file_from_tarball('Console_Getopt', 'Console/Getopt.php', "$dist_dir/PEAR/go-pear-bundle");
  440. }
  441. /* add extras from the template dir */
  442. if (file_exists($snapshot_template)) {
  443. $items = glob("$snapshot_template/*");
  444. print_r($items);
  445. foreach ($items as $item) {
  446. $bi = basename($item);
  447. if (is_dir($item)) {
  448. if ($bi == 'dlls' || $bi == 'symbols') {
  449. continue;
  450. } else if ($bi == 'PEAR') {
  451. if ($use_pear_template) {
  452. /* copy to top level */
  453. copy_dir($item, "$dist_dir/$bi");
  454. }
  455. } else {
  456. /* copy that dir into extras */
  457. copy_dir($item, "$dist_dir/extras/$bi");
  458. }
  459. } else {
  460. if ($bi == 'go-pear.bat') {
  461. /* copy to top level */
  462. copy($item, "$dist_dir/$bi");
  463. } else {
  464. /* copy to extras */
  465. copy($item, "$dist_dir/extras/$bi");
  466. }
  467. }
  468. }
  469. /* copy c++ runtime */
  470. $items = glob("$snapshot_template/dlls/*.CRT");
  471. foreach ($items as $item) {
  472. $bi = basename($item);
  473. if (is_dir($item)) {
  474. copy_dir($item, "$dist_dir/$bi");
  475. copy_dir($item, "$dist_dir/ext/$bi");
  476. }
  477. }
  478. } else {
  479. echo "WARNING: you don't have a snapshot template, your dist will not be complete\n";
  480. }
  481. make_phar_dot_phar($dist_dir);
  482. ?>