array("pipe", "w")), $pipes); $n = 0; while (($line = fgetcsv($pipes[1]))) { $n++; $dep = strtolower($line[0]); $depbase = basename($dep); /* ignore stuff in our build dir, but only if it is * one of our targets */ if (((in_array($depbase, $sapi_targets) || in_array($depbase, $ext_targets) || in_array($depbase, $pecl_targets)) || $depbase == $phpdll) && file_exists($GLOBALS['build_dir'] . "/$depbase")) { continue; } /* ignore some well-known system dlls */ if (in_array(basename($dep), $no_dist)) { continue; } else { $skip = false; foreach ($no_dist_re as $re) { if (preg_match(",$re,", basename($dep)) > 0) { $skip = true; break; } } if ($skip) { continue; } } if ($is_pecl) { if (!in_array($dep, $pecl_dll_deps)) { $pecl_dll_deps[] = $dep; } } else { if (!in_array($dep, $extra_dll_deps)) { $extra_dll_deps[] = $dep; } } if (!isset($per_module_deps[basename($module)]) || !in_array($dep, $per_module_deps[basename($module)])) { $per_module_deps[basename($module)][] = $dep; //recursively check dll dependencies get_depends($dep); } } fclose($pipes[1]); proc_close($proc); //echo "Module $module [$n lines]\n"; } function copy_file_list($source_dir, $dest_dir, $list) { global $is_debug, $dist_dir; foreach ($list as $item) { if (empty($item)) { continue; } elseif (!is_file($source_dir . DIRECTORY_SEPARATOR . $item)) { echo "WARNING: $item not found\n"; continue; } echo "Copying $item from $source_dir to $dest_dir\n"; copy($source_dir . DIRECTORY_SEPARATOR . $item, $dest_dir . DIRECTORY_SEPARATOR . $item); if ($is_debug) { $itemdb = preg_replace("/\.(exe|dll|lib)$/i", ".pdb", $item); if (file_exists("$source_dir/$itemdb")) { copy("$source_dir/$itemdb", "$dist_dir/dev/$itemdb"); } } if (preg_match("/\.(exe|dll)$/i", $item)) { get_depends($source_dir . '/' . $item); } } } function copy_text_file($source, $dest) { $text = file_get_contents($source); $text = preg_replace("/(\r\n?)|\n/", "\r\n", $text); $fp = fopen($dest, "w"); fwrite($fp, $text); fclose($fp); } /* very light-weight function to extract a single named file from * a gzipped tarball. This makes assumptions about the files * based on the PEAR info set in $packages. */ function extract_file_from_tarball($pkg, $filename, $dest_dir) /* {{{ */ { global $packages; $name = $pkg . '-' . $packages[$pkg]; $tarball = $dest_dir . "/" . $name . '.tgz'; $filename = $name . '/' . $filename; $destfilename = $dest_dir . "/" . basename($filename); $fp = gzopen($tarball, 'rb'); $done = false; do { /* read the header */ $hdr_data = gzread($fp, 512); if (strlen($hdr_data) == 0) break; $checksum = 0; for ($i = 0; $i < 148; $i++) $checksum += ord($hdr_data[$i]); for ($i = 148; $i < 156; $i++) $checksum += 32; for ($i = 156; $i < 512; $i++) $checksum += ord($hdr_data[$i]); $hdr = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $hdr_data); $hdr['checksum'] = octdec(trim($hdr['checksum'])); if ($hdr['checksum'] != $checksum) { echo "Checksum for $tarball $hdr[filename] is invalid\n"; print_r($hdr); return; } $hdr['size'] = octdec(trim($hdr['size'])); echo "File: $hdr[filename] $hdr[size]\n"; if ($filename == $hdr['filename']) { echo "Found the file we want\n"; $dest = fopen($destfilename, 'wb'); $x = stream_copy_to_stream($fp, $dest, $hdr['size']); fclose($dest); echo "Wrote $x bytes into $destfilename\n"; break; } /* skip body of the file */ $size = 512 * ceil((int)$hdr['size'] / 512); echo "Skipping $size bytes\n"; gzseek($fp, gztell($fp) + $size); } while (!$done); } /* }}} */ /* the core dll */ copy("$build_dir/php.exe", "$dist_dir/php.exe"); /* copy dll and its dependencies */ copy_file_list($build_dir, "$dist_dir", [$phpdll]); /* and the .lib goes into dev */ $phplib = str_replace(".dll", ".lib", $phpdll); copy("$build_dir/$phplib", "$dist_dir/dev/$phplib"); /* debug builds; copy the symbols too */ if ($is_debug) { $phppdb = str_replace(".dll", ".pdb", $phpdll); copy("$build_dir/$phppdb", "$dist_dir/dev/$phppdb"); } /* copy the sapi */ copy_file_list($build_dir, "$dist_dir", $sapi_targets); /* copy the extensions */ copy_file_list($build_dir, "$dist_dir/ext", $ext_targets); /* pecl sapi and extensions */ if(sizeof($pecl_targets)) { copy_file_list($build_dir, $pecl_dir, $pecl_targets); } /* populate reading material */ $text_files = array( "LICENSE" => "license.txt", "NEWS" => "news.txt", "README.md" => "README.md", "README.REDIST.BINS" => "readme-redist-bins.txt", "php.ini-development" => "php.ini-development", "php.ini-production" => "php.ini-production" ); foreach ($text_files as $src => $dest) { copy_text_file($src, $dist_dir . '/' . $dest); } /* general other files */ $general_files = array( "$GLOBALS[build_dir]\\deplister.exe" => "deplister.exe", ); foreach ($general_files as $src => $dest) { copy($src, $dist_dir . '/' . $dest); } /* include a snapshot identifier */ $branch = "HEAD"; // TODO - determine this from SVN branche name $fp = fopen("$dist_dir/snapshot.txt", "w"); $now = date("r"); fwrite($fp, << $deps) { if (in_array($modulename, $pecl_targets)) continue; fprintf($fp, "Module: %s\r\n", $modulename); fwrite($fp, "===========================\r\n"); foreach ($deps as $dll) { fprintf($fp, "\t%s\r\n", basename($dll)); } fwrite($fp, "\r\n"); } fclose($fp); /* Now add those dependencies */ foreach ($extra_dll_deps as $dll) { if (!file_exists($dll)) { /* try template dir */ $tdll = $snapshot_template . "/dlls/" . basename($dll); if (!file_exists($tdll)) { $tdll = $php_build_dir . '/bin/' . basename($dll); if (!file_exists($tdll)) { echo "WARNING: distro depends on $dll, but could not find it on your system\n"; continue; } } $dll = $tdll; } copy($dll, "$dist_dir/" . basename($dll)); } /* TODO: add sanity check and test if all required DLLs are present, per version This version works at least for 3.6, 3.8 and 4.0 (5.3-vc6, 5.3-vc9 and HEAD). Add ADD_DLLS to add extra DLLs like dynamic dependencies for standard deps. For example, libenchant.dll loads libenchant_myspell.dll or libenchant_ispell.dll */ $ENCHANT_DLLS = array( array('', 'glib-2.dll'), array('', 'gmodule-2.dll'), array('lib/enchant', 'libenchant_myspell.dll'), array('lib/enchant', 'libenchant_ispell.dll'), ); foreach ($ENCHANT_DLLS as $dll) { $dest = "$dist_dir/$dll[0]"; $filename = $dll[1]; if (!file_exists("$dest") || !is_dir("$dest")) { if (!mkdir("$dest", 0777, true)) { echo "WARNING: couldn't create '$dest' for enchant plugins "; } } if (!copy($php_build_dir . '/bin/' . $filename, "$dest/" . basename($filename))) { echo "WARNING: couldn't copy $filename into the dist dir"; } } $SASL_DLLS = $php_build_dir . "/bin/sasl2/sasl*.dll"; $fls = glob($SASL_DLLS); if (!empty($fls)) { $sasl_dest_dir = "$dist_dir/sasl2"; if (!file_exists($sasl_dest_dir) || !is_dir($sasl_dest_dir)) { if (!mkdir("$sasl_dest_dir", 0777, true)) { echo "WARNING: couldn't create '$sasl_dest_dir' for SASL2 auth plugins "; } } foreach ($fls as $fl) { if (!copy($fl, "$sasl_dest_dir/" . basename($fl))) { echo "WARNING: couldn't copy $fl into the $sasl_dest_dir"; } } } /* and those for pecl */ foreach ($pecl_dll_deps as $dll) { if (in_array($dll, $extra_dll_deps)) { /* already in main distro */ continue; } if (!file_exists($dll)) { /* try template dir */ $tdll = $snapshot_template . "/dlls/" . basename($dll); if (!file_exists($tdll)) { echo "WARNING: distro depends on $dll, but could not find it on your system\n"; continue; } $dll = $tdll; } copy($dll, "$pecl_dir/" . basename($dll)); } function copy_dir($source, $dest) { if (!is_dir($dest)) { if (!mkdir($dest)) { return false; } } $d = opendir($source); while (($f = readdir($d)) !== false) { if ($f == '.' || $f == '..' || $f == '.svn') { continue; } $fs = $source . '/' . $f; $fd = $dest . '/' . $f; if (is_dir($fs)) { copy_dir($fs, $fd); } else { copy($fs, $fd); } } closedir($d); } function copy_test_dir($directory, $dest) { if(substr($directory,-1) == '/') { $directory = substr($directory,0,-1); } if ($directory == 'tests' || $directory == 'examples') { if (!is_dir($dest . '/tests')) { mkdir($dest . '/tests', 0775, true); } copy_dir($directory, $dest . '/tests/'); return false; } if(!file_exists($directory) || !is_dir($directory)) { echo "failed... $directory\n"; return FALSE; } $directory_list = opendir($directory); while (FALSE !== ($file = readdir($directory_list))) { $full_path = $directory . '/' . $file; if($file != '.' && $file != '..' && $file != '.svn' && is_dir($full_path)) { if ($file == 'tests' || $file == 'examples') { if (!is_dir($dest . '/' . $full_path)) { mkdir($dest . '/' . $full_path , 0775, true); } copy_dir($full_path, $dest . '/' . $full_path . '/'); continue; } else { copy_test_dir($full_path, $dest); } } } closedir($directory_list); } function make_phar_dot_phar($dist_dir) { if (!extension_loaded('phar')) { return; } $path_to_phar = realpath(__DIR__ . '/../../ext/phar'); echo "Generating pharcommand.phar\n"; $phar = new Phar($dist_dir . '/pharcommand.phar', 0, 'pharcommand'); foreach (new DirectoryIterator($path_to_phar . '/phar') as $file) { if ($file->isDir() || $file == 'phar.php') { continue; } echo 'adding ', $file, "\n"; $phar[(string) $file] = file_get_contents($path_to_phar. '/phar/' . $file); } $phar->setSignatureAlgorithm(Phar::SHA1); $stub = file($path_to_phar . '/phar/phar.php'); unset($stub[0]); // remove hashbang $phar->setStub(implode('', $stub)); echo "Creating phar.phar.bat\n"; file_put_contents($dist_dir . '/phar.phar.bat', "\"%~dp0php.exe\" \"%~dp0pharcommand.phar\" %*\r\n"); } if (!is_dir($test_dir)) { mkdir($test_dir); } $dirs = array( 'ext', 'Sapi', 'Zend', 'tests' ); foreach ($dirs as $dir) { copy_test_dir($dir, $test_dir); } copy('run-tests.php', $test_dir . '/run-test.php'); /* change this next line to true to use good-old * hand-assembled go-pear-bundle from the snapshot template */ $use_pear_template = true; if (!$use_pear_template) { /* Let's do a PEAR-less pear setup */ mkdir("$dist_dir/PEAR"); mkdir("$dist_dir/PEAR/go-pear-bundle"); /* grab the bootstrap script */ echo "Downloading go-pear\n"; copy("https://pear.php.net/go-pear.phar", "$dist_dir/PEAR/go-pear.php"); /* import the package list -- sets $packages variable */ include "pear/go-pear-list.php"; /* download the packages into the destination */ echo "Fetching packages\n"; foreach ($packages as $name => $version) { $filename = "$name-$version.tgz"; $destfilename = "$dist_dir/PEAR/go-pear-bundle/$filename"; if (file_exists($destfilename)) continue; $url = "http://pear.php.net/get/$filename"; echo "Downloading $name from $url\n"; flush(); copy($url, $destfilename); } echo "Download complete. Extracting bootstrap files\n"; /* Now, we want PEAR.php, Getopt.php (Console_Getopt) and Tar.php (Archive_Tar) * broken out of the tarballs */ extract_file_from_tarball('PEAR', 'PEAR.php', "$dist_dir/PEAR/go-pear-bundle"); extract_file_from_tarball('Archive_Tar', 'Archive/Tar.php', "$dist_dir/PEAR/go-pear-bundle"); extract_file_from_tarball('Console_Getopt', 'Console/Getopt.php', "$dist_dir/PEAR/go-pear-bundle"); } /* add extras from the template dir */ if (file_exists($snapshot_template)) { $items = glob("$snapshot_template/*"); print_r($items); foreach ($items as $item) { $bi = basename($item); if (is_dir($item)) { if ($bi == 'dlls' || $bi == 'symbols') { continue; } else if ($bi == 'PEAR') { if ($use_pear_template) { /* copy to top level */ copy_dir($item, "$dist_dir/$bi"); } } else { /* copy that dir into extras */ copy_dir($item, "$dist_dir/extras/$bi"); } } else { if ($bi == 'go-pear.bat') { /* copy to top level */ copy($item, "$dist_dir/$bi"); } else { /* copy to extras */ copy($item, "$dist_dir/extras/$bi"); } } } /* copy c++ runtime */ $items = glob("$snapshot_template/dlls/*.CRT"); foreach ($items as $item) { $bi = basename($item); if (is_dir($item)) { copy_dir($item, "$dist_dir/$bi"); copy_dir($item, "$dist_dir/ext/$bi"); } } } else { echo "WARNING: you don't have a snapshot template, your dist will not be complete\n"; } make_phar_dot_phar($dist_dir); ?>