상속: implements Serializabl\Serializable
예제 #1
0
 public function check(Build $build)
 {
     $apxs = $build->getVariant('apxs2');
     // trying to find apxs binary in case it wasn't explicitly specified (+apxs variant without path)
     if ($apxs === true) {
         $apxs = Utils::findbin('apxs');
         $this->logger->debug("Found apxs2 binary: {$apxs}");
     }
     if (!is_executable($apxs)) {
         throw new Exception("apxs binary is not executable: {$apxs}");
     }
     // use apxs to check module dir permission
     if ($apxs && ($libdir = trim(Utils::pipeExecute("{$apxs} -q LIBEXECDIR")))) {
         if (false === is_writable($libdir)) {
             $this->logger->error("Apache module dir {$libdir} is not writable.\nPlease consider using chmod to change the folder permission:");
             $this->logger->error("    \$ sudo chmod -R oga+rw {$libdir}");
             $this->logger->error("Warnings: the command above is not safe for public systems. please use with discretion.");
             throw new Exception();
         }
     }
     if ($apxs && ($confdir = trim(Utils::pipeExecute("{$apxs} -q SYSCONFDIR")))) {
         if (false === is_writable($confdir)) {
             $this->logger->error("Apache conf dir {$confdir} is not writable for phpbrew.");
             $this->logger->error("Please consider using chmod to change the folder permission: ");
             $this->logger->error("    \$ sudo chmod -R oga+rw {$confdir}");
             $this->logger->error("Warnings: the command above is not safe for public systems. please use with discretion.");
             throw new Exception();
         }
     }
 }
예제 #2
0
 public function testPatch()
 {
     if (PHP_OS !== "Darwin") {
         return $this->markTestSkipped('openssl DSO patch test only runs on darwin platform');
     }
     $logger = new Logger();
     $logger->setQuiet();
     $fromVersion = '5.5.17';
     $sourceFixtureDirectory = getenv('PHPBREW_FIXTURES_PHP_DIR') . DIRECTORY_SEPARATOR . $fromVersion;
     $sourceDirectory = getenv('PHPBREW_BUILD_PHP_DIR');
     $this->setupBuildDirectory($fromVersion);
     $build = new Build($fromVersion);
     $build->setSourceDirectory($sourceDirectory);
     $build->enableVariant('openssl');
     $this->assertTrue($build->hasVariant('openssl'), 'openssl enabled');
     $patch = new OpenSSLDSOPatch();
     $matched = $patch->match($build, $logger);
     $this->assertTrue($matched, 'patch matched');
     $patchedCount = $patch->apply($build, $logger);
     $this->assertEquals(10, $patchedCount);
     /*
             We can't assume the file equals because the test may be run on different platform and openssl may be installed 
             into different locations.
     
             $sourceExpectedDirectory = getenv('PHPBREW_EXPECTED_PHP_DIR') . DIRECTORY_SEPARATOR . '5.5.17-openssl-dso-patch';
             $this->assertFileEquals($sourceExpectedDirectory. '/Makefile', $sourceDirectory . '/Makefile');
     */
 }
예제 #3
0
 public function install(Build $build)
 {
     $this->info('Installing...');
     if ($this->options->sudo) {
         $cmd = new CommandBuilder('sudo make install');
         if (!$this->options->dryrun) {
             $code = $cmd->passthru($lastline);
             if ($code !== 0) {
                 throw new SystemCommandException("Install failed: {$lastline}", $build, $build->getBuildLogPath());
             }
         }
     } else {
         $cmd = new CommandBuilder('make install');
         $cmd->setAppendLog(true);
         $cmd->setLogPath($build->getBuildLogPath());
         $cmd->setStdout($this->options->{'stdout'});
         if (!$this->options->dryrun) {
             $code = $cmd->execute($lastline);
             if ($code !== 0) {
                 throw new SystemCommandException("Install failed: {$lastline}", $build, $build->getBuildLogPath());
             }
         }
     }
     $build->setState(Build::STATE_INSTALL);
 }
예제 #4
0
 public function testPatch()
 {
     $logger = new Logger();
     $logger->setQuiet();
     $fromVersion = '5.3.29';
     $sourceFixtureDirectory = getenv('PHPBREW_FIXTURES_PHP_DIR') . DIRECTORY_SEPARATOR . $fromVersion;
     $sourceDirectory = getenv('PHPBREW_BUILD_PHP_DIR');
     if (!is_dir($sourceDirectory)) {
         return $this->markTestSkipped("{$sourceDirectory} does not exist.");
     }
     // Copy the source Makefile to the Makefile
     // copy($sourceFixtureDirectory . '/Makefile', $sourceDirectory . '/Makefile');
     $this->setupBuildDirectory($fromVersion);
     $build = new Build($fromVersion);
     $build->setSourceDirectory($sourceDirectory);
     $build->enableVariant('intl');
     $this->assertTrue($build->hasVariant('intl'), 'intl enabled');
     $patch = new IntlWith64bitPatch();
     $matched = $patch->match($build, $logger);
     $this->assertTrue($matched, 'patch matched');
     $patchedCount = $patch->apply($build, $logger);
     $this->assertEquals(3, $patchedCount);
     $sourceExpectedDirectory = getenv('PHPBREW_EXPECTED_PHP_DIR') . DIRECTORY_SEPARATOR . $fromVersion;
     $this->assertFileEquals($sourceExpectedDirectory . '/Makefile', $sourceDirectory . '/Makefile');
 }
예제 #5
0
 public function check(Build $build)
 {
     $apxs = $build->getVariant('apxs2');
     // trying to find apxs binary in case it wasn't explicitly specified (+apxs variant without path)
     if ($apxs === true) {
         $apxs = Utils::findbin('apxs');
         $this->logger->debug("Found apxs2 binary: {$apxs}");
     }
     if (!is_executable($apxs)) {
         throw new Exception("apxs binary is not executable: {$apxs}");
     }
     // use apxs to check module dir permission
     if ($apxs && ($libdir = trim(Utils::pipeExecute("{$apxs} -q LIBEXECDIR")))) {
         if (false === is_writable($libdir)) {
             throw new Exception("Apache module dir {$libdir} is not writable.\nPlease consider using chmod or sudo.");
         }
     }
     if ($apxs && ($confdir = trim(Utils::pipeExecute("{$apxs} -q SYSCONFDIR")))) {
         if (false === is_writable($confdir)) {
             $msg = array();
             $msg[] = "Apache conf dir {$confdir} is not writable for phpbrew.";
             $msg[] = "Please consider using chmod or sudo: ";
             $msg[] = "    \$ sudo chmod -R og+rw {$confdir}";
             throw new Exception(join("\n", $msg));
         }
     }
 }
예제 #6
0
 public function run(Build $build, $targets = array())
 {
     if ($build->getState() >= Build::STATE_BUILD) {
         $this->info("===> Already built, skipping...");
         return;
     }
     $this->info("===> Building...");
     $cmd = new CommandBuilder('make');
     $cmd->setAppendLog(true);
     $cmd->setLogPath($build->getBuildLogPath());
     $cmd->setStdout($this->options->{'stdout'});
     if (!empty($targets)) {
         foreach ($targets as $t) {
             $cmd->addArg($t);
         }
     }
     if ($this->options->nice) {
         $cmd->nice($this->options->nice);
     }
     if ($makeJobs = $this->options->{'jobs'}) {
         $cmd->addArg("-j{$makeJobs}");
     }
     $this->debug($cmd->getCommand());
     if (!$this->options->dryrun) {
         $startTime = microtime(true);
         $code = $cmd->execute();
         if ($code != 0) {
             throw new SystemCommandException('Make failed.', $build, $build->getBuildLogPath());
         }
         $buildTime = round((microtime(true) - $startTime) / 60, 1);
         $this->info("Build finished: {$buildTime} minutes.");
     }
     $build->setState(Build::STATE_BUILD);
 }
예제 #7
0
 /**
  * Unpacks the source tarball file.
  *
  * @param string $targetFilePath absolute file path
  * @param string $extractDir     (the build dir)
  */
 public function extract(Build $build, $targetFilePath, $extractDir = null)
 {
     if (empty($extractDir)) {
         $extractDir = dirname($targetFilePath);
     }
     $extractDirTemp = $extractDir . DIRECTORY_SEPARATOR . 'tmp.' . time();
     if (!file_exists($extractDirTemp)) {
         mkdir($extractDirTemp, 0755, true);
     }
     // This converts: '/opt/phpbrew/distfiles/php-7.0.2.tar.bz2'
     //        to just '/opt/phpbrew/tmp/distfiles/php-7.0.2'
     $distBasename = preg_replace('#\\.tar\\.(gz|bz2)$#', '', basename($targetFilePath));
     $extractedDirTemp = $extractDirTemp . DIRECTORY_SEPARATOR . $distBasename;
     $extractedDir = $extractDir . DIRECTORY_SEPARATOR . $build->getName();
     if ($build->getState() >= Build::STATE_EXTRACT && file_exists($extractedDir . DIRECTORY_SEPARATOR . 'configure')) {
         $this->info('===> Distribution file was successfully extracted, skipping...');
         return $extractedDir;
     }
     // NOTICE: Always extract to tmp directory prevent incomplete extraction
     $this->info("===> Extracting {$targetFilePath} to {$extractedDirTemp}");
     $lastline = system('tar -C ' . escapeshellarg($extractDirTemp) . ' -xf ' . escapeshellarg($targetFilePath), $ret);
     if ($ret !== 0) {
         throw new SystemCommandException("Extract failed: {$lastline}", $build);
     }
     clearstatcache(true);
     if (!is_dir($extractedDirTemp)) {
         // retry with github extracted dir path
         $extractedDirTemp = $extractDirTemp . DIRECTORY_SEPARATOR . 'php-src-' . $distBasename;
         if (!is_dir($extractedDirTemp)) {
             throw new SystemCommandException("Unable to find {$extractedDirTemp}", $build);
         }
     }
     if (is_dir($extractedDir)) {
         $this->info("===> Found existing build directory, removing {$extractedDir} ...");
         $lastline = system('rm -rf ' . escapeshellarg($extractedDir), $ret);
         if ($ret !== 0) {
             throw new SystemCommandException("Unable to remove {$extractedDir}: {$lastline}", $build);
         }
     }
     $this->info("===> Moving {$extractedDirTemp} to {$extractedDir}");
     if (!rename($extractedDirTemp, $extractedDir)) {
         throw new SystemCommandException("Unable to move {$extractedDirTemp} to {$extractedDir}", $build);
     }
     @rmdir($extractDirTemp);
     $build->setState(Build::STATE_EXTRACT);
     return $extractedDir;
     /*
      * XXX: unless we have a fast way to verify the extraction.
     if ($this->options->force || ! file_exists($extractedDir . DIRECTORY_SEPARATOR . 'configure')) {
         $this->info("===> Extracting $targetFilePath...");
         system("tar -C $dir -xjf $targetFilePath", $ret);
         if ($ret != 0) {
             die('Extract failed.');
         }
     } else {
         $this->info("Found existing $extractedDir, Skip extracting.");
     }
     */
 }
예제 #8
0
 public function deregister(Build $build)
 {
     $file = $this->baseDir . DIRECTORY_SEPARATOR . $build->getName();
     if (file_exists($file)) {
         unlink($file);
         return true;
     }
     return false;
 }
예제 #9
0
 public function testApply()
 {
     $version = '5.3.29';
     $fixture = new TemporaryFileFixture($this, getenv('PHPBREW_FIXTURES_PHP_DIR') . "/{$version}/Makefile.in");
     $fixture->withFile('Makefile', function ($self, $fixturePath) use($version) {
         $build = new Build($version);
         $build->setSourceDirectory(dirname($fixturePath));
         $patch = new RegexpPatch($self->logger, $build, array(basename($fixturePath)), array(RegexpPatchRule::always('/LIBTOOL/', '')));
         $patch->apply();
         $self->assertFileEquals($fixturePath, getenv('PHPBREW_EXPECTED_PHP_DIR') . '/5.3.29/Makefile.in');
     });
 }
예제 #10
0
 /**
  * Unpacks the source tarball file.
  *
  * @param string $targetFilePath absolute file path
  */
 public function extract(Build $build, $targetFilePath, $extractDir = NULL)
 {
     $extractDirTemp = Config::getTempFileDir();
     if (!$extractDir) {
         $extractDir = dirname($targetFilePath);
     }
     $extractedDirTemp = $extractDirTemp . DIRECTORY_SEPARATOR . preg_replace('#\\.tar\\.(gz|bz2)$#', '', basename($targetFilePath));
     $extractedDir = $extractDir . DIRECTORY_SEPARATOR . $build->getName();
     if ($build->getState() >= Build::STATE_EXTRACT && file_exists($extractedDir . DIRECTORY_SEPARATOR . 'configure')) {
         $this->info("===> Distribution file was successfully extracted, skipping...");
         return $extractedDir;
     }
     // NOTICE: Always extract to prevent incomplete extraction
     $this->info("===> Extracting {$targetFilePath} to {$extractedDirTemp}");
     system("tar -C {$extractDirTemp} -xf {$targetFilePath}", $ret);
     if ($ret != 0) {
         throw new RuntimeException('Extract failed.');
     }
     clearstatcache(true);
     if (!is_dir($extractedDirTemp)) {
         // retry with github extracted dir path
         $extractedDirTemp = $extractDirTemp . DIRECTORY_SEPARATOR . 'php-src-' . preg_replace('#\\.tar\\.(gz|bz2)$#', '', basename($targetFilePath));
         if (!is_dir($extractedDirTemp)) {
             throw new RuntimeException("Unable to find {$extractedDirTemp}");
         }
     }
     if (is_dir($extractedDir)) {
         $this->info("===> Removing {$extractedDir}");
         system("rm -rf {$extractedDir}", $ret);
         if ($ret !== 0) {
             throw new RuntimeException("Unable to remove {$extractedDir}.");
         }
     }
     $this->info("===> Moving {$extractedDirTemp} to {$extractedDir}");
     if (!rename($extractedDirTemp, $extractedDir)) {
         throw new RuntimeException("Unable to move {$extractedDirTemp} to {$extractedDir}");
     }
     $build->setState(Build::STATE_EXTRACT);
     return $extractedDir;
     /*
      * XXX: unless we have a fast way to verify the extraction.
     if ($this->options->force || ! file_exists($extractedDir . DIRECTORY_SEPARATOR . 'configure')) {
         $this->info("===> Extracting $targetFilePath...");
         system("tar -C $dir -xjf $targetFilePath", $ret);
         if ($ret != 0) {
             die('Extract failed.');
         }
     } else {
         $this->info("Found existing $extractedDir, Skip extracting.");
     }
     */
 }
예제 #11
0
 public function install(Build $build)
 {
     $this->info("Installing...");
     $cmd = new CommandBuilder('make install');
     $cmd->setAppendLog(true);
     $cmd->setLogPath($build->getBuildLogPath());
     $cmd->setStdout($this->options->{'stdout'});
     if (!$this->options->dryrun) {
         $code = $cmd->execute();
         if ($code != 0) {
             throw new SystemCommandException('Install failed.', $build->getBuildLogPath());
         }
     }
     $build->setState(Build::STATE_INSTALL);
 }
예제 #12
0
 public function run(Build $build, $nice = null)
 {
     $this->info("Testing...");
     $cmd = new CommandBuilder('make test');
     if ($nice) {
         $cmd->nice($nice);
     }
     $cmd->setAppendLog(true);
     $cmd->setLogPath($build->getBuildLogPath());
     $cmd->setStdout($this->options->{'stdout'});
     $this->debug('' . $cmd);
     $code = $cmd->execute();
     if ($code != 0) {
         throw new RuntimeException('Test failed.');
     }
 }
예제 #13
0
 public function run(Build $build, $nice = null)
 {
     $this->info('===> Running tests...');
     $cmd = new CommandBuilder('make test');
     if ($nice) {
         $cmd->nice($nice);
     }
     $cmd->setAppendLog(true);
     $cmd->setLogPath($build->getBuildLogPath());
     $cmd->setStdout($this->options->{'stdout'});
     putenv('NO_INTERACTION=1');
     $this->debug('' . $cmd);
     $code = $cmd->execute($lastline);
     if ($code !== 0) {
         throw new SystemCommandException("Test failed: {$lastline}", $build);
     }
 }
예제 #14
0
 public function run(Build $build = NULL)
 {
     $dirs = array();
     $dirs[] = Config::getPhpbrewRoot();
     $dirs[] = Config::getPhpbrewHome();
     $dirs[] = Config::getBuildDir();
     $dirs[] = Config::getDistFileDir();
     $dirs[] = Config::getVariantsDir();
     if ($build) {
         $dirs[] = Config::getInstallPrefix() . DIRECTORY_SEPARATOR . $build->getName();
     }
     foreach ($dirs as $dir) {
         if (!file_exists($dir)) {
             $this->logger->debug("Creating directory {$dir}");
             mkdir($dir, 0755, true);
         }
     }
 }
예제 #15
0
 public function execute($version)
 {
     $buildDir = Config::getBuildDir() . DIRECTORY_SEPARATOR . $version;
     if ($this->options->all) {
         if (!file_exists($buildDir)) {
             $this->logger->info("Source directory " . $buildDir . " does not exist.");
         } else {
             $this->logger->info("Source directory " . $buildDir . " found, deleting...");
             Utils::recursive_unlink($buildDir, $this->logger);
         }
     } else {
         $make = new MakeTask($this->logger);
         $make->setQuiet();
         $build = new Build($version);
         $build->setSourceDirectory($buildDir);
         if ($make->clean($build)) {
             $this->logger->info("Distribution is cleaned up. Woof! ");
         }
     }
 }
예제 #16
0
 public function run(Build $build)
 {
     if (!file_exists($build->getSourceDirectory() . DIRECTORY_SEPARATOR . 'configure')) {
         $this->debug("configure file not found, running './buildconf --force'...");
         $lastline = system('./buildconf --force', $status);
         if ($status !== 0) {
             throw new SystemCommandException("buildconf error: {$lastline}", $build);
         }
     }
     foreach ((array) $this->options->patch as $patchPath) {
         // copy patch file to here
         $this->info("===> Applying patch file from {$patchPath} ...");
         // Search for strip parameter
         for ($i = 0; $i <= 16; ++$i) {
             ob_start();
             system("patch -p{$i} --dry-run < {$patchPath}", $return);
             ob_end_clean();
             if ($return === 0) {
                 system("patch -p{$i} < {$patchPath}");
                 break;
             }
         }
     }
     // let's apply patch for libphp{php version}.so (apxs)
     if ($build->isEnabledVariant('apxs2')) {
         $apxs2Checker = new \PhpBrew\Tasks\Apxs2CheckTask($this->logger);
         $apxs2Checker->check($build, $this->options);
     }
     if (!$this->options->{'no-patch'}) {
         $this->logger->info('===> Checking patches...');
         $patches = array();
         $patches[] = new Apache2ModuleNamePatch();
         foreach ($patches as $patch) {
             $this->logger->info('Checking patch for ' . $patch->desc());
             if ($patch->match($build, $this->logger)) {
                 $patched = $patch->apply($build, $this->logger);
                 $this->logger->info("{$patched} changes patched.");
             }
         }
     }
 }
예제 #17
0
 public function check(Build $build)
 {
     $apxs = $build->getVariant('apxs2');
     if (!$apxs) {
         $apxs = Utils::findbin('apxs');
     }
     $this->logger->debug("Found apxs2 sbin: {$apxs}");
     // use apxs to check module dir permission
     if ($apxs && ($libdir = trim(Utils::pipeExecute("{$apxs} -q LIBEXECDIR")))) {
         if (false === is_writable($libdir)) {
             $msg = array();
             throw new Exception("Apache module dir {$libdir} is not writable.\nPlease consider using chmod or sudo.");
         }
     }
     if ($apxs && ($confdir = trim(Utils::pipeExecute("{$apxs} -q SYSCONFDIR")))) {
         if (false === is_writable($confdir)) {
             $msg = array();
             $msg[] = "Apache conf dir {$confdir} is not writable for phpbrew.";
             $msg[] = "Please consider using chmod or sudo: ";
             $msg[] = "    \$ sudo chmod -R og+rw {$confdir}";
             throw new Exception(join("\n", $msg));
         }
     }
 }
예제 #18
0
 public function testPatch()
 {
     $logger = new Logger();
     $logger->setQuiet();
     $fromVersion = '5.5.17';
     $sourceFixtureDirectory = getenv('PHPBREW_FIXTURES_PHP_DIR') . DIRECTORY_SEPARATOR . $fromVersion;
     $sourceDirectory = getenv('PHPBREW_BUILD_PHP_DIR');
     if (!is_dir($sourceDirectory)) {
         return $this->markTestSkipped("{$sourceDirectory} does not exist.");
     }
     $this->setupBuildDirectory($fromVersion);
     $build = new Build($fromVersion);
     $build->setSourceDirectory($sourceDirectory);
     $build->enableVariant('apxs2');
     $this->assertTrue($build->hasVariant('apxs2'), 'apxs2 enabled');
     $patch = new Apache2ModuleNamePatch();
     $matched = $patch->match($build, $logger);
     $this->assertTrue($matched, 'patch matched');
     $patchedCount = $patch->apply($build, $logger);
     $this->assertEquals(107, $patchedCount);
     $sourceExpectedDirectory = getenv('PHPBREW_EXPECTED_PHP_DIR') . DIRECTORY_SEPARATOR . '5.5.17-apxs-patch';
     $this->assertFileEquals($sourceExpectedDirectory . '/Makefile.global', $sourceDirectory . '/Makefile.global');
     $this->assertFileEquals($sourceExpectedDirectory . '/configure', $sourceDirectory . '/configure');
 }
예제 #19
0
 public function testMysqlPdoVariant()
 {
     $variants = new PhpBrew\VariantBuilder();
     ok($variants);
     $build = new PhpBrew\Build('5.3.0');
     $build->enableVariant('pdo');
     $build->enableVariant('mysql');
     $build->enableVariant('sqlite');
     $build->resolveVariants();
     $options = $variants->build($build);
     $this->assertContains('--enable-pdo', $options);
     $this->assertContains('--with-mysql=mysqlnd', $options);
     $this->assertContains('--with-mysqli=mysqlnd', $options);
     $this->assertContains('--with-pdo-mysql=mysqlnd', $options);
     $this->assertContains('--with-pdo-sqlite', $options);
 }
예제 #20
0
    public function execute($version)
    {
        if (extension_loaded('posix') && posix_getuid() === 0) {
            $this->logger->warn("*WARNING* You're runing phpbrew as root/sudo. Unless you're going to install\nsystem-wide phpbrew or this might cause problems.");
            sleep(3);
        }
        $distUrl = null;
        $versionInfo = array();
        $releaseList = ReleaseList::getReadyInstance($this->options);
        $versionDslParser = new VersionDslParser();
        $clean = new MakeTask($this->logger, $this->options);
        $clean->setQuiet();
        if ($root = $this->options->root) {
            Config::setPhpbrewRoot($root);
        }
        if ($home = $this->options->home) {
            Config::setPhpbrewHome($home);
        }
        if ('latest' === strtolower($version)) {
            $version = $releaseList->getLatestVersion();
        }
        // this should point to master or the latest version branch yet to be released
        if ('next' === strtolower($version)) {
            $version = 'github.com/php/php-src:master';
        }
        if ($info = $versionDslParser->parse($version)) {
            $version = $info['version'];
            $distUrl = $info['url'];
            // always redownload when installing from github master
            // beware to keep this behavior after clean up the TODO below
            $this->options['force']->setValue(true);
        } else {
            // TODO ↓ clean later ↓ d.d.d versions should be part of the DSL too
            $version = preg_replace('/^php-/', '', $version);
            $versionInfo = $releaseList->getVersion($version);
            if (!$versionInfo) {
                throw new Exception("Version {$version} not found.");
            }
            $version = $versionInfo['version'];
            $distUrlPolicy = new DistributionUrlPolicy();
            if ($this->options->mirror) {
                $distUrlPolicy->setMirrorSite($this->options->mirror);
            }
            $distUrl = $distUrlPolicy->buildUrl($version, $versionInfo['filename'], $versionInfo['museum']);
        }
        // get options and variants for building php
        // and skip the first argument since it's the target version.
        $args = func_get_args();
        array_shift($args);
        // shift the version name
        $semanticOptions = $this->parseSemanticOptions($args);
        $buildAs = isset($semanticOptions['as']) ? $semanticOptions['as'] : $this->options->name;
        $buildLike = isset($semanticOptions['like']) ? $semanticOptions['like'] : $this->options->like;
        // convert patch to realpath
        if ($this->options->patch) {
            $patchPaths = array();
            foreach ($this->options->patch as $patch) {
                /* @var \SplFileInfo $patch */
                $patchPath = realpath($patch);
                if ($patchPath !== false) {
                    $patchPaths[(string) $patch] = $patchPath;
                }
            }
            // rewrite patch paths
            $this->options->keys['patch']->value = $patchPaths;
        }
        // Initialize the build object, contains the information to build php.
        $build = new Build($version, $buildAs);
        $installPrefix = Config::getInstallPrefix() . DIRECTORY_SEPARATOR . $build->getName();
        if (!file_exists($installPrefix)) {
            mkdir($installPrefix, 0755, true);
        }
        $build->setInstallPrefix($installPrefix);
        // find inherited variants
        if ($buildLike) {
            if ($parentBuild = Build::findByName($buildLike)) {
                $this->logger->info("===> Loading build settings from {$buildLike}");
                $build->loadVariantInfo($parentBuild->settings->toArray());
            }
        }
        $msg = "===> phpbrew will now build {$build->getVersion()}";
        if ($buildLike) {
            $msg .= ' using variants from ' . $buildLike;
        }
        if (isset($semanticOptions['using'])) {
            $msg .= ' plus custom variants: ' . implode(', ', $semanticOptions['using']);
            $args = array_merge($args, $semanticOptions['using']);
        }
        if ($buildAs) {
            $msg .= ' as ' . $buildAs;
        }
        $this->logger->info($msg);
        if (!empty($args)) {
            $this->logger->debug("---> Parsing variants from command arguments '" . implode(' ', $args) . "'");
        }
        // ['extra_options'] => the extra options to be passed to ./configure command
        // ['enabled_variants'] => enabeld variants
        // ['disabled_variants'] => disabled variants
        $variantInfo = VariantParser::parseCommandArguments($args);
        $build->loadVariantInfo($variantInfo);
        // load again
        // assume +default variant if no build config is given and warn about that
        if (!$variantInfo['enabled_variants']) {
            $build->setBuildSettings(new DefaultBuildSettings());
            $this->logger->notice("You haven't set any variant. A default set of extensions will be installed for the minimum requirement:");
            $this->logger->notice('[' . implode(', ', array_keys($build->getVariants())) . ']');
            $this->logger->notice("Please run 'phpbrew variants' for more information.\n");
        }
        if (preg_match('/5\\.3\\./', $version)) {
            $this->logger->notice('PHP 5.3 requires +intl, enabled by default.');
            $build->enableVariant('intl');
        }
        // always add +xml by default unless --without-pear is present
        // TODO: This can be done by "-pear"
        if (!in_array('--without-pear', $variantInfo['extra_options'])) {
            $build->enableVariant('xml');
        }
        $this->logger->info('===> Loading and resolving variants...');
        $removedVariants = $build->loadVariantInfo($variantInfo);
        if (!empty($removedVariants)) {
            $this->logger->debug('Removed variants: ' . implode(',', $removedVariants));
        }
        $prepareTask = new PrepareDirectoryTask($this->logger, $this->options);
        $prepareTask->run($build);
        // Move to to build directory, because we are going to download distribution.
        $buildDir = $this->options->{'build-dir'} ?: Config::getBuildDir();
        if (!file_exists($buildDir)) {
            mkdir($buildDir, 0755, true);
        }
        $variantBuilder = new VariantBuilder();
        $configureOptions = $variantBuilder->build($build);
        $distFileDir = Config::getDistFileDir();
        $downloadTask = new DownloadTask($this->logger, $this->options);
        $targetFilePath = $downloadTask->download($distUrl, $distFileDir, isset($versionInfo['md5']) ? $versionInfo['md5'] : null);
        if (!file_exists($targetFilePath)) {
            throw new SystemCommandException("Download failed, {$targetFilePath} does not exist.", $build);
        }
        unset($downloadTask);
        $extractTask = new ExtractTask($this->logger, $this->options);
        $targetDir = $extractTask->extract($build, $targetFilePath, $buildDir);
        if (!file_exists($targetDir)) {
            throw new SystemCommandException("Extract failed, {$targetDir} does not exist.", $build);
        }
        unset($extractTask);
        // Update build source directory
        $this->logger->debug('Source Directory: ' . realpath($targetDir));
        $build->setSourceDirectory($targetDir);
        if (!$this->options->{'no-clean'} && file_exists($targetDir . DIRECTORY_SEPARATOR . 'Makefile')) {
            $this->logger->info('Found existing Makefile, running make clean to ensure everything will be rebuilt.');
            $this->logger->info("You can append --no-clean option after the install command if you don't want to rebuild.");
            $clean->clean($build);
        }
        // Change directory to the downloaded source directory.
        chdir($targetDir);
        // Write variants info.
        $variantInfoFile = $build->getInstallPrefix() . DIRECTORY_SEPARATOR . 'phpbrew.variants';
        $this->logger->debug("Writing variant info to {$variantInfoFile}");
        if (false === $build->writeVariantInfoFile($variantInfoFile)) {
            $this->logger->warn("Can't store variant info.");
        }
        $buildLogFile = $build->getBuildLogPath();
        if (!$this->options->{'no-configure'}) {
            $configureTask = new BeforeConfigureTask($this->logger, $this->options);
            $configureTask->run($build);
            unset($configureTask);
            // trigger __destruct
            $configureTask = new ConfigureTask($this->logger, $this->options);
            $configureTask->run($build, $configureOptions);
            unset($configureTask);
            // trigger __destruct
            $configureTask = new AfterConfigureTask($this->logger, $this->options);
            $configureTask->run($build);
            unset($configureTask);
            // trigger __destruct
        }
        $buildTask = new BuildTask($this->logger, $this->options);
        $buildTask->run($build);
        unset($buildTask);
        // trigger __destruct
        if ($this->options->{'test'}) {
            $testTask = new TestTask($this->logger, $this->options);
            $testTask->run($build);
            unset($testTask);
            // trigger __destruct
        }
        if (!$this->options->{'no-install'}) {
            $installTask = new InstallTask($this->logger, $this->options);
            $installTask->install($build);
            unset($installTask);
            // trigger __destruct
        }
        if ($this->options->{'post-clean'}) {
            $clean->clean($build);
        }
        $dsym = new DSymTask($this->logger, $this->options);
        $dsym->patch($build, $this->options);
        // copy php-fpm config
        $this->logger->info('---> Creating php-fpm.conf');
        $etcDirectory = $build->getEtcDirectory();
        $fpmUnixSocket = $build->getInstallPrefix() . "/var/run/php-fpm.sock";
        $this->installAs("{$etcDirectory}/php-fpm.conf.default", "{$etcDirectory}/php-fpm.conf");
        $this->installAs("{$etcDirectory}/php-fpm.d/www.conf.default", "{$etcDirectory}/php-fpm.d/www.conf");
        $patchingFiles = array("{$etcDirectory}/php-fpm.d/www.conf", "{$etcDirectory}/php-fpm.conf");
        foreach ($patchingFiles as $patchingFile) {
            if (file_exists($patchingFile)) {
                $this->logger->info("---> Found {$patchingFile}");
                // Patch pool listen unix
                // The original config was below:
                //
                // listen = 127.0.0.1:9000
                //
                // See http://php.net/manual/en/install.fpm.configuration.php for more details
                $ini = file_get_contents($patchingFile);
                $this->logger->info("---> Patching default fpm pool listen path to {$fpmUnixSocket}");
                $ini = preg_replace('/^listen = .*$/m', "listen = {$fpmUnixSocket}\n", $ini);
                file_put_contents($patchingFile, $ini);
                break;
            }
        }
        $this->logger->info('---> Creating php.ini');
        $phpConfigPath = $build->getSourceDirectory() . DIRECTORY_SEPARATOR . ($this->options->production ? 'php.ini-production' : 'php.ini-development');
        $this->logger->info("---> Copying {$phpConfigPath} ");
        if (file_exists($phpConfigPath) && !$this->options->dryrun) {
            $targetConfigPath = $etcDirectory . DIRECTORY_SEPARATOR . 'php.ini';
            if (file_exists($targetConfigPath)) {
                $this->logger->notice("Found existing {$targetConfigPath}.");
            } else {
                // TODO: Move this to PhpConfigPatchTask
                // move config file to target location
                copy($phpConfigPath, $targetConfigPath);
            }
            if (!$this->options->{'no-patch'}) {
                $config = parse_ini_file($targetConfigPath, true);
                $configContent = file_get_contents($targetConfigPath);
                $patched = false;
                if (!isset($config['date']['timezone'])) {
                    $this->logger->info('---> Found date.timezone is not set, patching...');
                    // Replace current timezone
                    if ($timezone = ini_get('date.timezone')) {
                        $this->logger->info("---> Found date.timezone, patching config timezone with {$timezone}");
                        $configContent = preg_replace('/^;?date.timezone\\s*=\\s*.*/im', "date.timezone = {$timezone}", $configContent);
                    }
                    $patched = true;
                }
                if (!isset($config['phar']['readonly'])) {
                    $pharReadonly = ini_get('phar.readonly');
                    // 0 or "" means readonly is disabled manually
                    if (!$pharReadonly) {
                        $this->logger->info('---> Disabling phar.readonly option.');
                        $configContent = preg_replace('/^;?phar.readonly\\s*=\\s*.*/im', 'phar.readonly = 0', $configContent);
                    }
                }
                // turn off detect_encoding for 5.3
                if ($build->compareVersion('5.4') < 0) {
                    $this->logger->info("---> Turn off detect_encoding for php 5.3.*");
                    $configContent = $configContent . "\ndetect_unicode = Off\n";
                }
                file_put_contents($targetConfigPath, $configContent);
            }
        }
        if ($build->isEnabledVariant('pear')) {
            $this->logger->info('Initializing pear config...');
            $home = Config::getHome();
            @mkdir("{$home}/tmp/pear/temp", 0755, true);
            @mkdir("{$home}/tmp/pear/cache_dir", 0755, true);
            @mkdir("{$home}/tmp/pear/download_dir", 0755, true);
            system("pear config-set temp_dir {$home}/tmp/pear/temp");
            system("pear config-set cache_dir {$home}/tmp/pear/cache_dir");
            system("pear config-set download_dir {$home}/tmp/pear/download_dir");
            $this->logger->info('Enabling pear auto-discover...');
            system('pear config-set auto_discover 1');
        }
        $this->logger->debug('Source directory: ' . $targetDir);
        $buildName = $build->getName();
        $this->logger->info("Congratulations! Now you have PHP with {$version} as {$buildName}");
        if ($build->isEnabledVariant('pdo') && $build->isEnabledVariant('mysql')) {
            echo <<<EOT

* We found that you enabled 'mysql' variant, you might need to setup your
  'pdo_mysql.default_socket' or 'mysqli.default_socket' in your php.ini file.

EOT;
        }
        if (isset($targetConfigPath)) {
            echo <<<EOT

* To configure your installed PHP further, you can edit the config file at
    {$targetConfigPath}

EOT;
        }
        // If the bashrc file is not found, it means 'init' command didn't get
        // a chance to be executed.
        if (!file_exists(Config::getHome() . DIRECTORY_SEPARATOR . 'bashrc')) {
            echo <<<EOT

* WARNING:
  You haven't run 'phpbrew init' yet! Be sure to setup your phpbrew to use your own php(s)
  Please run 'phpbrew init' to setup your phpbrew in place.

EOT;
        }
        // If the environment variable is not defined, it means users didn't
        // setup ther .bashrc or .zshrc
        if (!getenv('PHPBREW_HOME')) {
            echo <<<EOT

* WARNING:
  You haven't setup your .bashrc file to load phpbrew shell script yet!
  Please run 'phpbrew init' to see the steps!

EOT;
        }
        echo <<<EOT

To use the newly built PHP, try the line(s) below:

    \$ phpbrew use {$buildName}

Or you can use switch command to switch your default php to {$buildName}:

    \$ phpbrew switch {$buildName}

Enjoy!

EOT;
    }
예제 #21
0
파일: Builder.php 프로젝트: bensb/phpbrew
 public function configure(\PhpBrew\Build $build)
 {
     $variantBuilder = new VariantBuilder();
     $extra = $build->getExtraOptions();
     if (!file_exists('configure')) {
         $this->logger->debug("configure file not found, running buildconf script...");
         system('./buildconf') !== false or die('buildconf error');
     }
     // build configure args
     // XXX: support variants
     $cmd = new CommandBuilder('./configure');
     // putenv('CFLAGS=-O3');
     $prefix = $build->getInstallPrefix();
     $args[] = "--prefix=" . $prefix;
     $args[] = "--with-config-file-path={$prefix}/etc";
     $args[] = "--with-config-file-scan-dir={$prefix}/var/db";
     $args[] = "--with-pear={$prefix}/lib/php";
     // this is to support pear
     $build->enableVariant('xml');
     $variantOptions = $variantBuilder->build($build);
     if ($variantOptions) {
         $args = array_merge($args, $variantOptions);
     }
     $this->logger->debug('Enabled variants: ' . join(', ', array_keys($build->getVariants())));
     $this->logger->debug('Disabled variants: ' . join(', ', array_keys($build->getDisabledVariants())));
     if ($patchFiles = $this->options->patch) {
         foreach ($patchFiles as $patchFile) {
             // copy patch file to here
             $this->logger->info("===> Applying patch file from {$patchFile} ...");
             system("patch -p0 < {$patchFile}");
         }
     }
     // let's apply patch for libphp{php version}.so (apxs)
     if ($build->isEnabledVariant('apxs2')) {
         $apxs2Checker = new \PhpBrew\Tasks\Apxs2CheckTask($this->logger);
         $apxs2Checker->check($build);
         $apxs2Patch = new \PhpBrew\Tasks\Apxs2PatchTask($this->logger);
         $apxs2Patch->patch($build, $this->options);
     }
     foreach ($extra as $a) {
         $args[] = $a;
     }
     $cmd->args($args);
     $this->logger->info("===> Configuring {$build->version}...");
     $cmd->append = false;
     $cmd->stdout = Config::getVersionBuildLogPath($build->name);
     echo "\n\n";
     echo "Use tail command to see what's going on:\n";
     echo "   \$ tail -f {$cmd->stdout}\n\n\n";
     $this->logger->debug($cmd->getCommand());
     if ($this->options->nice) {
         $cmd->nice($this->options->nice);
     }
     $cmd->execute() !== false or die('Configure failed.');
     // Then patch Makefile for PHP 5.3.x on 64bit system.
     $currentVersion = preg_replace('/[^\\d]*(\\d+).(\\d+).*/i', '$1.$2', $this->version);
     if (Utils::support64bit() && version_compare($currentVersion, '5.3', '==')) {
         $this->logger->info("===> Applying patch file for php5.3.x on 64bit machine.");
         system('sed -i \'/^BUILD_/ s/\\$(CC)/\\$(CXX)/g\' Makefile');
         system('sed -i \'/EXTRA_LIBS = /s|$| -lstdc++|\' Makefile');
     }
 }
예제 #22
0
 /**
  * A test case for `neutral' virtual variant.
  */
 public function testNeutralVirtualVariant()
 {
     $variants = new VariantBuilder();
     $build = new Build('5.3.0');
     // $build->setVersion('5.3.0');
     $build->enableVariant('neutral');
     $build->resolveVariants();
     $options = $variants->build($build);
     // ignore `--with-libdir` because this option should be set depending on client environments.
     $actual = array_filter($options, function ($option) {
         return !preg_match("/^--with-libdir/", $option);
     });
     $this->assertEquals(array(), $actual);
 }
예제 #23
0
 /**
  * @param  \PhpBrew\Build $build
  * @return bool
  */
 public function check(Build $build)
 {
     $phpbin = $build->getBinDirectory() . DIRECTORY_SEPARATOR . 'php';
     $dSYM = $build->getBinDirectory() . DIRECTORY_SEPARATOR . 'php.dSYM';
     return !file_exists($phpbin) && file_exists($dSYM);
 }
예제 #24
0
 /**
  * Build variants to configure options from php build object.
  *
  * @param Build $build The build object, contains version information
  *
  * @return array|void
  * @throws \Exception
  */
 public function build(Build $build)
 {
     $customVirtualVariants = Config::getConfigParam('variants');
     foreach (array_keys($build->getVariants()) as $variantName) {
         if (isset($customVirtualVariants[$variantName])) {
             foreach ($customVirtualVariants[$variantName] as $lib => $params) {
                 if (is_array($params)) {
                     $this->variants[$lib] = $params;
                 }
             }
         }
     }
     // reset builtList
     $this->builtList = array();
     // reset built options
     if ($build->hasVariant('all') || $build->hasVariant('neutral')) {
         $this->options = array();
     } else {
         // build common options
         $this->options = array('--disable-all', '--enable-phar', '--enable-session', '--enable-short-tags', '--enable-tokenizer', '--with-pcre-regex');
         if ($prefix = Utils::findIncludePrefix('zlib.h')) {
             $this->addOptions('--with-zlib=' . $prefix);
         }
     }
     if ($prefix = Utils::findLibPrefix('x86_64-linux-gnu')) {
         $this->addOptions("--with-libdir=lib/x86_64-linux-gnu");
     } elseif ($prefix = Utils::findLibPrefix('i386-linux-gnu')) {
         $this->addOptions("--with-libdir=lib/i386-linux-gnu");
     }
     // enable/expand virtual variants
     foreach ($this->virtualVariants as $name => $variantNames) {
         if ($build->isEnabledVariant($name)) {
             foreach ($variantNames as $subVariantName) {
                 // enable the sub-variant only if it's not already enabled
                 // in order to not override a non-default value with the default
                 if (!$build->isEnabledVariant($subVariantName)) {
                     $build->enableVariant($subVariantName);
                 }
             }
             // it's a virtual variant, can not be built by buildVariant
             // method.
             $build->removeVariant($name);
         }
     }
     // Remove these enabled variant for disabled variants.
     $build->resolveVariants();
     // before we build these options from variants,
     // we need to check the enabled and disabled variants
     $this->checkConflicts($build);
     foreach ($build->getVariants() as $feature => $userValue) {
         if ($options = $this->buildVariant($build, $feature, $userValue)) {
             $this->addOptions($options);
         }
     }
     foreach ($build->getDisabledVariants() as $feature => $true) {
         if ($options = $this->buildDisableVariant($build, $feature)) {
             $this->addOptions($options);
         }
     }
     /*
     $opts = array_merge( $opts ,
         $this->getVersionSpecificOptions($version) );
     */
     $options = array_merge(array(), $this->options);
     // reset options
     $this->options = array();
     return $options;
 }
예제 #25
0
 public function run(Build $build, $variantOptions)
 {
     $extra = $build->getExtraOptions();
     $prefix = $build->getInstallPrefix();
     // append cflags
     if ($this->optimizationLevel) {
         $o = $this->optimizationLevel;
         $cflags = getenv('CFLAGS');
         putenv("CFLAGS={$cflags} -O{$o}");
         $_ENV['CFLAGS'] = "{$cflags} -O{$o}";
     }
     $args = array();
     if (!$this->options->{'no-config-cache'}) {
         // $args[] = "-C"; // project wise cache (--config-cache)
         $args[] = '--cache-file=' . escapeshellarg(Config::getCacheDir() . DIRECTORY_SEPARATOR . 'config.cache');
     }
     $args[] = '--prefix=' . $prefix;
     if ($this->options->{'user-config'}) {
         $args[] = "--with-config-file-path={$prefix}/etc";
         $args[] = "--with-config-file-scan-dir={$prefix}/var/db";
     } else {
         $args[] = "--with-config-file-path={$prefix}/etc";
         $args[] = "--with-config-file-scan-dir={$prefix}/var/db";
     }
     if ($variantOptions) {
         $args = array_merge($args, $variantOptions);
     }
     $this->debug('Enabled variants: [' . implode(', ', array_keys($build->getVariants())) . ']');
     $this->debug('Disabled variants: [' . implode(', ', array_keys($build->getDisabledVariants())) . ']');
     // todo: move to pear variant
     $args[] = "--with-pear={$prefix}/lib/php";
     // Options for specific versions
     // todo: extract to BuildPlan class: PHP53 BuildPlan, PHP54 BuildPlan, PHP55 BuildPlan ?
     if ($build->compareVersion('5.4') == -1) {
         // copied from https://github.com/Homebrew/homebrew-php/blob/master/Formula/php53.rb
         $args[] = '--enable-sqlite-utf8';
         $args[] = '--enable-zend-multibyte';
     } elseif ($build->compareVersion('5.6') == -1) {
         $args[] = '--enable-zend-signals';
     }
     foreach ($extra as $a) {
         $args[] = $a;
     }
     $cmd = new CommandBuilder('./configure');
     $cmd->args($args);
     $buildLogPath = $build->getBuildLogPath();
     if (file_exists($buildLogPath)) {
         $newPath = $buildLogPath . '.' . filemtime($buildLogPath);
         $this->info("Found existing build.log, renaming it to {$newPath}");
         rename($buildLogPath, $newPath);
     }
     $this->info("===> Configuring {$build->version}...");
     $cmd->setAppendLog(true);
     $cmd->setLogPath($buildLogPath);
     $cmd->setStdout($this->options->{'stdout'});
     if (!$this->options->{'stdout'}) {
         $this->logger->info("\n");
         $this->logger->info("Use tail command to see what's going on:");
         $this->logger->info("   \$ tail -F {$buildLogPath}\n\n");
     }
     $this->debug($cmd->buildCommand());
     if ($this->options->nice) {
         $cmd->nice($this->options->nice);
     }
     if (!$this->options->dryrun) {
         $code = $cmd->execute($lastline);
         if ($code !== 0) {
             throw new SystemCommandException("Configure failed: {$lastline}", $build, $buildLogPath);
         }
     }
     $build->setState(Build::STATE_CONFIGURE);
 }
예제 #26
0
    public function execute($version)
    {
        if (!preg_match('/^php-/', $version)) {
            $version = 'php-' . $version;
        }
        $version = $this->getLatestMinorVersion($version, $this->options->old);
        $options = $this->options;
        $logger = $this->logger;
        // get options and variants for building php
        $args = func_get_args();
        // the first argument is the target version.
        array_shift($args);
        $name = $this->options->name ?: $version;
        // find inherited variants
        $inheritedVariants = array();
        if ($this->options->like) {
            $inheritedVariants = VariantParser::getInheritedVariants($this->options->like);
        }
        // ['extra_options'] => the extra options to be passed to ./configure command
        // ['enabled_variants'] => enabeld variants
        // ['disabled_variants'] => disabled variants
        $variantInfo = VariantParser::parseCommandArguments($args, $inheritedVariants);
        $info = PhpSource::getVersionInfo($version, $this->options->old);
        if (!$info) {
            throw new Exception("Version {$version} not found.");
        }
        $prepare = new PrepareDirectoryTask($this->logger);
        $prepare->prepareForVersion($version);
        // convert patch to realpath
        if ($this->options->patch) {
            $patchPaths = array();
            foreach ($this->options->patch as $patch) {
                /** @var \SplFileInfo $patch */
                $patchPath = realpath($patch);
                if ($patchPath !== false) {
                    $patchPaths[(string) $patch] = $patchPath;
                }
            }
            // rewrite patch paths
            $this->options->keys['patch']->value = $patchPaths;
        }
        // Move to to build directory, because we are going to download distribution.
        $buildDir = Config::getBuildDir();
        chdir($buildDir);
        $download = new DownloadTask($this->logger);
        $targetDir = $download->downloadByVersionString($version, $this->options->old, $this->options->force);
        if (!file_exists($targetDir)) {
            throw new Exception("Download failed.");
        }
        // Change directory to the downloaded source directory.
        chdir($targetDir);
        $buildPrefix = Config::getVersionBuildPrefix($version);
        if (!file_exists($buildPrefix)) {
            mkdir($buildPrefix, 0755, true);
        }
        // write variants info.
        $variantInfoFile = $buildPrefix . DIRECTORY_SEPARATOR . 'phpbrew.variants';
        $this->logger->debug("Writing variant info to {$variantInfoFile}");
        file_put_contents($variantInfoFile, serialize($variantInfo));
        // The build object, contains the information to build php.
        $build = new Build($version, $name, $buildPrefix);
        $build->setInstallPrefix($buildPrefix);
        $build->setSourceDirectory($targetDir);
        $builder = new Builder($targetDir, $version);
        $builder->logger = $this->logger;
        $builder->options = $this->options;
        $this->logger->debug('Build Directory: ' . realpath($targetDir));
        foreach ($variantInfo['enabled_variants'] as $name => $value) {
            $build->enableVariant($name, $value);
        }
        foreach ($variantInfo['disabled_variants'] as $name => $value) {
            $build->disableVariant($name);
            if ($build->hasVariant($name)) {
                $this->logger->warn("Removing variant {$name} since we've disabled it from command.");
                $build->removeVariant($name);
            }
        }
        $build->setExtraOptions($variantInfo['extra_options']);
        if ($options->clean) {
            $clean = new CleanTask($this->logger);
            $clean->cleanByVersion($version);
        }
        $buildLogFile = Config::getVersionBuildLogPath($version);
        $configure = new \PhpBrew\Tasks\ConfigureTask($this->logger);
        $configure->configure($build, $this->options);
        $buildTask = new BuildTask($this->logger);
        $buildTask->setLogPath($buildLogFile);
        $buildTask->build($build, $this->options);
        if ($options->{'test'}) {
            $test = new TestTask($this->logger);
            $test->setLogPath($buildLogFile);
            $test->test($build, $this->options);
        }
        $install = new InstallTask($this->logger);
        $install->setLogPath($buildLogFile);
        $install->install($build, $this->options);
        if ($options->{'post-clean'}) {
            $clean = new CleanTask($this->logger);
            $clean->cleanByVersion($version);
        }
        /** POST INSTALLATION **/
        $dsym = new DSymTask($this->logger);
        $dsym->patch($build, $this->options);
        // copy php-fpm config
        $this->logger->info("---> Creating php-fpm.conf");
        $phpFpmConfigPath = "sapi/fpm/php-fpm.conf";
        $phpFpmTargetConfigPath = Config::getVersionEtcPath($version) . DIRECTORY_SEPARATOR . 'php-fpm.conf';
        if (file_exists($phpFpmConfigPath)) {
            if (!file_exists($phpFpmTargetConfigPath)) {
                copy($phpFpmConfigPath, $phpFpmTargetConfigPath);
            } else {
                $this->logger->notice("Found existing {$phpFpmTargetConfigPath}.");
            }
        }
        $phpConfigPath = $options->production ? 'php.ini-production' : 'php.ini-development';
        $this->logger->info("---> Copying {$phpConfigPath} ");
        if (file_exists($phpConfigPath)) {
            $targetConfigPath = Config::getVersionEtcPath($version) . DIRECTORY_SEPARATOR . 'php.ini';
            if (file_exists($targetConfigPath)) {
                $this->logger->notice("Found existing {$targetConfigPath}.");
            } else {
                // TODO: Move this to PhpConfigPatchTask
                // move config file to target location
                copy($phpConfigPath, $targetConfigPath);
                // replace current timezone
                $timezone = ini_get('date.timezone');
                $pharReadonly = ini_get('phar.readonly');
                if ($timezone || $pharReadonly) {
                    // patch default config
                    $content = file_get_contents($targetConfigPath);
                    if ($timezone) {
                        $this->logger->info("---> Found date.timezone, patch config timezone with {$timezone}");
                        $content = preg_replace('/^date.timezone\\s*=\\s*.*/im', "date.timezone = {$timezone}", $content);
                    }
                    if (!$pharReadonly) {
                        $this->logger->info("---> Disable phar.readonly option.");
                        $content = preg_replace('/^phar.readonly\\s*=\\s*.*/im', "phar.readonly = 0", $content);
                    }
                    file_put_contents($targetConfigPath, $content);
                }
            }
        }
        $this->logger->info("Initializing pear config...");
        $home = Config::getPhpbrewHome();
        @mkdir("{$home}/tmp/pear/temp", 0755, true);
        @mkdir("{$home}/tmp/pear/cache_dir", 0755, true);
        @mkdir("{$home}/tmp/pear/download_dir", 0755, true);
        system("pear config-set temp_dir {$home}/tmp/pear/temp");
        system("pear config-set cache_dir {$home}/tmp/pear/cache_dir");
        system("pear config-set download_dir {$home}/tmp/pear/download_dir");
        $this->logger->info("Enabling pear auto-discover...");
        system("pear config-set auto_discover 1");
        $this->logger->debug("Source directory: " . $targetDir);
        $this->logger->info("Congratulations! Now you have PHP with {$version}.");
        echo <<<EOT
To use the newly built PHP, try the line(s) below:

    \$ phpbrew use {$version}

Or you can use switch command to switch your default php version to {$version}:

    \$ phpbrew switch {$version}

Enjoy!

EOT;
    }
예제 #27
0
 public function run(Build $build, $variantOptions)
 {
     $extra = $build->getExtraOptions();
     if (!file_exists($build->getSourceDirectory() . DIRECTORY_SEPARATOR . 'configure')) {
         $this->debug("configure file not found, running buildconf script...");
         $lastline = system('./buildconf', $status);
         if ($status !== 0) {
             throw new SystemCommandException("buildconf error: {$lastline}");
         }
     }
     $prefix = $build->getInstallPrefix();
     // append cflags
     if ($this->optimizationLevel) {
         $o = $this->optimizationLevel;
         $cflags = getenv('CFLAGS');
         putenv("CFLAGS={$cflags} -O{$o}");
         $_ENV['CFLAGS'] = "{$cflags} -O{$o}";
     }
     $args = array();
     $args[] = "--prefix=" . $prefix;
     $args[] = "--with-config-file-path={$prefix}/etc";
     $args[] = "--with-config-file-scan-dir={$prefix}/var/db";
     $args[] = "--with-pear={$prefix}/lib/php";
     if ($variantOptions) {
         $args = array_merge($args, $variantOptions);
     }
     $this->debug('Enabled variants: ' . join(', ', array_keys($build->getVariants())));
     $this->debug('Disabled variants: ' . join(', ', array_keys($build->getDisabledVariants())));
     foreach ((array) $this->options->patch as $patchPath) {
         // copy patch file to here
         $this->info("===> Applying patch file from {$patchPath} ...");
         // Search for strip parameter
         for ($i = 0; $i <= 16; $i++) {
             ob_start();
             system("patch -p{$i} --dry-run < {$patchPath}", $return);
             ob_end_clean();
             if ($return === 0) {
                 system("patch -p{$i} < {$patchPath}");
                 break;
             }
         }
     }
     // let's apply patch for libphp{php version}.so (apxs)
     if ($build->isEnabledVariant('apxs2')) {
         $apxs2Checker = new \PhpBrew\Tasks\Apxs2CheckTask($this->logger);
         $apxs2Checker->check($build, $this->options);
         $apxs2Patch = new \PhpBrew\Tasks\Apxs2PatchTask($this->logger);
         $apxs2Patch->patch($build, $this->options);
     }
     foreach ($extra as $a) {
         $args[] = $a;
     }
     $cmd = new CommandBuilder('./configure');
     $cmd->args($args);
     $buildLogPath = $build->getBuildLogPath();
     if (file_exists($buildLogPath)) {
         $newPath = $buildLogPath . '.' . filemtime($buildLogPath);
         $this->info("Found existing build.log, renaming it to {$newPath}");
         rename($buildLogPath, $newPath);
     }
     $this->info("===> Configuring {$build->version}...");
     $cmd->setAppendLog(true);
     $cmd->setLogPath($buildLogPath);
     $cmd->setStdout($this->options->{'stdout'});
     $this->logger->info("\n");
     $this->logger->info("Use tail command to see what's going on:");
     $this->logger->info("   \$ tail -F {$buildLogPath}\n\n");
     $this->debug($cmd->getCommand());
     if ($this->options->nice) {
         $cmd->nice($this->options->nice);
     }
     if (!$this->options->dryrun) {
         $code = $cmd->execute();
         if ($code != 0) {
             throw new SystemCommandException("Configure failed: {$code}", $buildLogPath);
         }
     }
     if (!$this->options->{'no-patch'}) {
         $patch64bit = new \PhpBrew\Tasks\Patch64BitSupportTask($this->logger, $this->options);
         if ($patch64bit->match($build)) {
             $patch64bit->patch($build);
         }
     }
     $build->setState(Build::STATE_CONFIGURE);
 }
예제 #28
0
    public function execute($version)
    {
        $distUrl = NULL;
        $versionInfo = array();
        $releaseList = ReleaseList::getReadyInstance();
        $versionDslParser = new VersionDslParser();
        $clean = new MakeTask($this->logger, $this->options);
        $clean->setQuiet();
        if ($root = $this->options->root) {
            Config::setPhpbrewRoot($root);
        }
        if ($home = $this->options->home) {
            Config::setPhpbrewHome($home);
        }
        if ('latest' === strtolower($version)) {
            $version = $releaseList->getLatestVersion();
        }
        // this should point to master or the latest version branch yet to be released
        if ('next' === strtolower($version)) {
            $version = "github.com/php/php-src:master";
        }
        if ($info = $versionDslParser->parse($version)) {
            $version = $info['version'];
            $distUrl = $info['url'];
            // always redownload when installing from github master
            // beware to keep this behavior after clean up the TODO below
            $this->options['force']->setValue(true);
        } else {
            // TODO ↓ clean later ↓ d.d.d versions should be part of the DSL too
            $version = preg_replace('/^php-/', '', $version);
            $versionInfo = $releaseList->getVersion($version);
            if (!$versionInfo) {
                throw new Exception("Version {$version} not found.");
            }
            $version = $versionInfo['version'];
            $distUrlPolicy = new DistributionUrlPolicy();
            if ($this->options->mirror) {
                $distUrlPolicy->setMirrorSite($this->options->mirror);
            }
            $distUrl = $distUrlPolicy->buildUrl($version, $versionInfo['filename']);
        }
        // get options and variants for building php
        // and skip the first argument since it's the target version.
        $args = func_get_args();
        array_shift($args);
        // shift the version name
        $semanticOptions = $this->parseSemanticOptions($args);
        $buildAs = isset($semanticOptions['as']) ? $semanticOptions['as'] : $this->options->name;
        $buildLike = isset($semanticOptions['like']) ? $semanticOptions['like'] : $this->options->like;
        // convert patch to realpath
        if ($this->options->patch) {
            $patchPaths = array();
            foreach ($this->options->patch as $patch) {
                /** @var \SplFileInfo $patch */
                $patchPath = realpath($patch);
                if ($patchPath !== false) {
                    $patchPaths[(string) $patch] = $patchPath;
                }
            }
            // rewrite patch paths
            $this->options->keys['patch']->value = $patchPaths;
        }
        // Initialize the build object, contains the information to build php.
        $build = new Build($version, $buildAs);
        $installPrefix = Config::getInstallPrefix() . DIRECTORY_SEPARATOR . $build->getName();
        if (!file_exists($installPrefix)) {
            mkdir($installPrefix, 0755, true);
        }
        $build->setInstallPrefix($installPrefix);
        // find inherited variants
        if ($buildLike) {
            if ($parentBuild = Build::findByName($buildLike)) {
                $build->loadVariantInfo($parentBuild->settings->toArray());
            }
        }
        $msg = "===> phpbrew will now build {$build->getVersion()}";
        if ($buildLike) {
            $msg .= ' using variants from ' . $buildLike;
        }
        if (isset($semanticOptions['using'])) {
            $msg .= ' plus custom variants: ' . join(', ', $semanticOptions['using']);
            $args = array_merge($args, $semanticOptions['using']);
        }
        if ($buildAs) {
            $msg .= ' as ' . $buildAs;
        }
        $this->logger->info($msg);
        if (!empty($args)) {
            $this->logger->debug("---> Parsing variants from command arguments '" . join(' ', $args) . "'");
        }
        // ['extra_options'] => the extra options to be passed to ./configure command
        // ['enabled_variants'] => enabeld variants
        // ['disabled_variants'] => disabled variants
        $variantInfo = VariantParser::parseCommandArguments($args);
        $build->loadVariantInfo($variantInfo);
        // load again
        // assume +default variant if no build config is given and warn about that
        if (!$variantInfo['enabled_variants']) {
            $build->setBuildSettings(new DefaultBuildSettings());
            $this->logger->notice("You haven't set any variant. A default set of extensions will be installed for the minimum requirement:");
            $this->logger->notice('[' . implode(', ', array_keys($build->getVariants())) . ']');
            $this->logger->notice("Please run 'phpbrew variants' for more information.\n");
        }
        if (preg_match('/5\\.3\\./', $version)) {
            $this->logger->notice("PHP 5.3 requires +intl, enabled by default.");
            $build->enableVariant('intl');
        }
        // always add +xml by default unless --without-pear is present
        // TODO: This can be done by "-pear"
        if (!in_array('--without-pear', $variantInfo['extra_options'])) {
            $build->enableVariant('xml');
        }
        $this->logger->info('===> Loading and resolving variants...');
        $removedVariants = $build->loadVariantInfo($variantInfo);
        if (!empty($removedVariants)) {
            $this->logger->debug('Removed variants: ' . join(',', $removedVariants));
        }
        $prepareTask = new PrepareDirectoryTask($this->logger, $this->options);
        $prepareTask->run($build);
        // Move to to build directory, because we are going to download distribution.
        $buildDir = $this->options->{'build-dir'} ?: Config::getBuildDir();
        if (!file_exists($buildDir)) {
            mkdir($buildDir, 0755, true);
        }
        $variantBuilder = new VariantBuilder();
        $variants = $variantBuilder->build($build);
        $distFileDir = Config::getDistFileDir();
        $downloadTask = new DownloadTask($this->logger, $this->options);
        $targetFilePath = $downloadTask->download($distUrl, $distFileDir, isset($versionInfo['md5']) ? $versionInfo['md5'] : NULL);
        if (!file_exists($targetFilePath)) {
            throw new Exception("Download failed, {$targetFilePath} does not exist.");
        }
        unset($downloadTask);
        $extractTask = new ExtractTask($this->logger, $this->options);
        $targetDir = $extractTask->extract($build, $targetFilePath, $buildDir);
        if (!file_exists($targetDir)) {
            throw new Exception("Extract failed, {$targetDir} does not exist.");
        }
        unset($extractTask);
        // Update build source directory
        $this->logger->debug('Source Directory: ' . realpath($targetDir));
        $build->setSourceDirectory($targetDir);
        if (!$this->options->{'no-clean'} && file_exists($targetDir . DIRECTORY_SEPARATOR . 'Makefile')) {
            $this->logger->info("Found existing Makefile, running make clean to ensure everything will be rebuilt.");
            $this->logger->info("You can append --no-clean option after the install command if you don't want to rebuild.");
            $clean->clean($build);
        }
        // Change directory to the downloaded source directory.
        chdir($targetDir);
        // Write variants info.
        $variantInfoFile = $build->getInstallPrefix() . DIRECTORY_SEPARATOR . 'phpbrew.variants';
        $this->logger->debug("Writing variant info to {$variantInfoFile}");
        if (false === $build->writeVariantInfoFile($variantInfoFile)) {
            $this->logger->warn("Can't store variant info.");
        }
        $buildLogFile = $build->getBuildLogPath();
        if (!$this->options->{'no-configure'}) {
            $configureTask = new ConfigureTask($this->logger, $this->options);
            $configureTask->run($build, $variants);
            unset($configureTask);
            // trigger __destruct
        }
        $buildTask = new BuildTask($this->logger, $this->options);
        $buildTask->run($build);
        unset($buildTask);
        // trigger __destruct
        if ($this->options->{'test'}) {
            $testTask = new TestTask($this->logger, $this->options);
            $testTask->run($build);
            unset($testTask);
            // trigger __destruct
        }
        if (!$this->options->{'no-install'}) {
            $installTask = new InstallTask($this->logger, $this->options);
            $installTask->install($build);
            unset($installTask);
            // trigger __destruct
        }
        if ($this->options->{'post-clean'}) {
            $clean->clean($build);
        }
        $dsym = new DSymTask($this->logger, $this->options);
        $dsym->patch($build, $this->options);
        // copy php-fpm config
        $this->logger->info("---> Creating php-fpm.conf");
        $phpFpmConfigPath = "sapi/fpm/php-fpm.conf";
        $phpFpmTargetConfigPath = $build->getEtcDirectory() . DIRECTORY_SEPARATOR . 'php-fpm.conf';
        if (file_exists($phpFpmConfigPath)) {
            if (!file_exists($phpFpmTargetConfigPath)) {
                copy($phpFpmConfigPath, $phpFpmTargetConfigPath);
            } else {
                $this->logger->notice("Found existing {$phpFpmTargetConfigPath}.");
            }
        }
        $this->logger->info("---> Creating php.ini");
        $phpConfigPath = $build->getSourceDirectory() . DIRECTORY_SEPARATOR . ($this->options->production ? 'php.ini-production' : 'php.ini-development');
        $this->logger->info("---> Copying {$phpConfigPath} ");
        if (file_exists($phpConfigPath) && !$this->options->dryrun) {
            $targetConfigPath = $build->getEtcDirectory() . DIRECTORY_SEPARATOR . 'php.ini';
            if (file_exists($targetConfigPath)) {
                $this->logger->notice("Found existing {$targetConfigPath}.");
            } else {
                // TODO: Move this to PhpConfigPatchTask
                // move config file to target location
                copy($phpConfigPath, $targetConfigPath);
            }
            if (!$this->options->{'no-patch'}) {
                $config = parse_ini_file($targetConfigPath, true);
                $configContent = file_get_contents($targetConfigPath);
                $patched = false;
                if (!isset($config['date']['timezone'])) {
                    $this->logger->info('---> Found date.timezone is not set, patching...');
                    // Replace current timezone
                    if ($timezone = ini_get('date.timezone')) {
                        $this->logger->info("---> Found date.timezone, patching config timezone with {$timezone}");
                        $configContent = preg_replace('/^;?date.timezone\\s*=\\s*.*/im', "date.timezone = {$timezone}", $configContent);
                    }
                    $patched = true;
                }
                if (!isset($config['phar']['readonly'])) {
                    $pharReadonly = ini_get('phar.readonly');
                    // 0 or "" means readonly is disabled manually
                    if (!$pharReadonly) {
                        $this->logger->info("---> Disabling phar.readonly option.");
                        $configContent = preg_replace('/^;?phar.readonly\\s*=\\s*.*/im', "phar.readonly = 0", $configContent);
                    }
                }
                file_put_contents($targetConfigPath, $configContent);
            }
        }
        $this->logger->info("Initializing pear config...");
        $home = Config::getPhpbrewHome();
        @mkdir("{$home}/tmp/pear/temp", 0755, true);
        @mkdir("{$home}/tmp/pear/cache_dir", 0755, true);
        @mkdir("{$home}/tmp/pear/download_dir", 0755, true);
        system("pear config-set temp_dir {$home}/tmp/pear/temp");
        system("pear config-set cache_dir {$home}/tmp/pear/cache_dir");
        system("pear config-set download_dir {$home}/tmp/pear/download_dir");
        $this->logger->info("Enabling pear auto-discover...");
        system("pear config-set auto_discover 1");
        $this->logger->debug("Source directory: " . $targetDir);
        $buildName = $build->getName();
        $this->logger->info("Congratulations! Now you have PHP with {$version} as {$buildName}");
        echo <<<EOT
To use the newly built PHP, try the line(s) below:

    \$ phpbrew use {$buildName}

Or you can use switch command to switch your default php to {$buildName}:

    \$ phpbrew switch {$buildName}

Enjoy!

EOT;
    }
예제 #29
0
 public function configure(Build $build, $options)
 {
     $root = Config::getPhpbrewRoot();
     $buildDir = Config::getBuildDir();
     $variantBuilder = new VariantBuilder();
     $extra = $build->getExtraOptions();
     if (!file_exists('configure')) {
         $this->debug("configure file not found, running buildconf script...");
         system('./buildconf') !== false or die('buildconf error');
     }
     $prefix = $build->getInstallPrefix();
     // append cflags
     if ($this->optimizationLevel) {
         $o = $this->optimizationLevel;
         $cflags = getenv('CFLAGS');
         putenv("CFLAGS={$cflags} -O{$o}");
         $_ENV['CFLAGS'] = "{$cflags} -O{$o}";
     }
     $args = array();
     $args[] = "--prefix=" . $prefix;
     $args[] = "--with-config-file-path={$prefix}/etc";
     $args[] = "--with-config-file-scan-dir={$prefix}/var/db";
     $args[] = "--with-pear={$prefix}/lib/php";
     $variantOptions = $variantBuilder->build($build);
     if ($variantOptions) {
         $args = array_merge($args, $variantOptions);
     }
     $this->debug('Enabled variants: ' . join(', ', array_keys($build->getVariants())));
     $this->debug('Disabled variants: ' . join(', ', array_keys($build->getDisabledVariants())));
     foreach ((array) $options->patch as $patchPath) {
         // copy patch file to here
         $this->info("===> Applying patch file from {$patchPath} ...");
         // Search for strip parameter
         for ($i = 0; $i <= 16; $i++) {
             ob_start();
             system("patch -p{$i} --dry-run < {$patchPath}", $return);
             ob_clean();
             if ($return === 0) {
                 system("patch -p{$i} < {$patchPath}");
                 break;
             }
         }
     }
     // let's apply patch for libphp{php version}.so (apxs)
     if ($build->isEnabledVariant('apxs2')) {
         $apxs2Checker = new \PhpBrew\Tasks\Apxs2CheckTask($this->logger);
         $apxs2Checker->check($build, $options);
         $apxs2Patch = new \PhpBrew\Tasks\Apxs2PatchTask($this->logger);
         $apxs2Patch->patch($build, $options);
     }
     foreach ($extra as $a) {
         $args[] = $a;
     }
     $cmd = new CommandBuilder('./configure');
     $cmd->args($args);
     $this->info("===> Configuring {$build->version}...");
     $cmd->append = false;
     $cmd->stdout = Config::getVersionBuildLogPath($build->name);
     echo "\n\n";
     echo "Use tail command to see what's going on:\n";
     echo "   \$ tail -f {$cmd->stdout}\n\n\n";
     $this->debug($cmd->getCommand());
     if ($options->nice) {
         $cmd->nice($options->nice);
     }
     if (!$options->dryrun) {
         $cmd->execute() !== false or die('Configure failed.');
     }
     $patch64bit = new \PhpBrew\Tasks\Patch64BitSupportTask($this->logger, $options);
     $patch64bit->patch($build, $options);
 }
예제 #30
0
 public function __construct()
 {
     parent::__construct('5.3.29');
     $this->setSourceDirectory(Config::getTempFileDir() . '/' . uniqid());
 }