Example #1
0
 public function execute()
 {
     $args = func_get_args();
     // $currentVersion;
     $root = Config::getPhpbrewRoot();
     $home = Config::getPhpbrewHome();
     $buildDir = Config::getBuildDir();
     $version = getenv('PHPBREW_PHP');
     // XXX: get source dir from current build information
     $sourceDir = $buildDir . DIRECTORY_SEPARATOR . $version;
     $this->logger->info($sourceDir);
     $cmd = new CommandBuilder('ctags');
     $cmd->arg('--recurse');
     $cmd->arg('-a');
     $cmd->arg('-h');
     $cmd->arg('.c.h.cpp');
     $cmd->arg($sourceDir . DIRECTORY_SEPARATOR . 'main');
     $cmd->arg($sourceDir . DIRECTORY_SEPARATOR . 'ext');
     $cmd->arg($sourceDir . DIRECTORY_SEPARATOR . 'Zend');
     foreach ($args as $a) {
         $cmd->arg($a);
     }
     $this->logger->info($cmd->__toString());
     $cmd->execute();
     $this->logger->info("Done");
 }
Example #2
0
 public function execute($version = null)
 {
     // get current version
     if (!$version) {
         $version = getenv('PHPBREW_PHP');
     }
     // $currentVersion;
     $root = Config::getPhpbrewRoot();
     $home = Config::getPhpbrewHome();
     $lookup = getenv('PHPBREW_LOOKUP_PREFIX');
     // $versionBuildPrefix = Config::getVersionBuildPrefix($version);
     // $versionBinPath     = Config::getVersionBinPath($version);
     echo "export PHPBREW_ROOT={$root}\n";
     echo "export PHPBREW_HOME={$home}\n";
     echo "export PHPBREW_LOOKUP_PREFIX={$lookup}\n";
     if ($version !== false) {
         // checking php version exists
         $version = Utils::findLatestPhpVersion($version);
         $targetPhpBinPath = Config::getVersionBinPath($version);
         if (!is_dir($targetPhpBinPath)) {
             throw new Exception("# php version: " . $version . " not exists.");
         }
         echo 'export PHPBREW_PHP=' . $version . "\n";
         echo 'export PHPBREW_PATH=' . ($version ? Config::getVersionBinPath($version) : '') . "\n";
     }
 }
Example #3
0
 public static function runUse($version)
 {
     putenv("PHPBREW_BIN=" . Config::getPhpbrewHome() . '/bin');
     putenv("PHPBREW_HOME=" . Config::getPhpbrewHome());
     putenv("PHPBREW_LOOKUP_PREFIX=/usr/local/Cellar:/usr/local");
     putenv("PHPBREW_PATH=" . Config::getPhpbrewHome() . "/php/php-{$version}/bin");
     putenv("PHPBREW_PHP=php-{$version}");
     putenv("PHPBREW_ROOT=" . Config::getPhpbrewRoot());
     putenv('PATH=' . getenv('PHPBREW_PATH') . ':' . self::getCleanPath());
 }
Example #4
0
 public function execute($buildName)
 {
     // this block is important for tests only
     $root = Config::getPhpbrewRoot();
     $home = Config::getPhpbrewHome();
     putenv("PHPBREW_ROOT={$root}");
     putenv("PHPBREW_HOME={$home}");
     putenv("PHPBREW_PHP={$buildName}");
     putenv("PHPBREW_PATH={$root}/{$buildName}/bin");
     putenv("PHPBREW_BIN={$home}/bin");
     $this->logger->warning("You should not see this, if you see this, it means you didn't load the ~/.phpbrew/bashrc script, please check if bashrc is sourced in your shell.");
 }
Example #5
0
    public function execute()
    {
        // $currentVersion;
        $root = Config::getPhpbrewRoot();
        $home = Config::getPhpbrewHome();
        $buildDir = Config::getBuildDir();
        $buildPrefix = Config::getBuildPrefix();
        // $versionBuildPrefix = Config::getVersionBuildPrefix($version);
        // $versionBinPath     = Config::getVersionBinPath($version);
        if (!file_exists($root)) {
            mkdir($root, 0755, true);
        }
        touch($root . DIRECTORY_SEPARATOR . '.metadata_never_index');
        // prevent spotlight index here
        if ($root != $home) {
            touch($home . DIRECTORY_SEPARATOR . '.metadata_never_index');
        }
        if ($this->options->{'config'} !== null) {
            copy($this->options->{'config'}, $root . DIRECTORY_SEPARATOR . 'config.yaml');
        }
        if (!file_exists($home)) {
            mkdir($home, 0755, true);
        }
        if (!file_exists($buildPrefix)) {
            mkdir($buildPrefix, 0755, true);
        }
        if (!file_exists($buildDir)) {
            mkdir($buildDir, 0755, true);
        }
        // write bashrc script to phpbrew home
        file_put_contents($home . '/bashrc', $this->getBashScript());
        echo <<<EOS
Phpbrew environment is initialized, required directories are created under

    {$home}

Paste the following line(s) to the end of your ~/.bashrc and start a
new shell, phpbrew should be up and fully functional from there:

    source {$home}/bashrc

To enable PHP version info in your shell prompt, please set PHPBREW_SET_PROMPT=1
in your `~/.bashrc` before you source `~/.phpbrew/bashrc`

    export PHPBREW_SET_PROMPT=1

For further instructions, simply run `phpbrew` to see the help message.

Enjoy phpbrew at \$HOME!!

EOS;
    }
 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);
         }
     }
 }
Example #7
0
 public function execute($buildName = NULL)
 {
     // get current version
     if (!$buildName) {
         $buildName = getenv('PHPBREW_PHP');
     }
     // $currentVersion;
     $root = Config::getPhpbrewRoot();
     $home = Config::getPhpbrewHome();
     $lookup = getenv('PHPBREW_LOOKUP_PREFIX');
     $this->logger->writeln("export PHPBREW_ROOT={$root}");
     $this->logger->writeln("export PHPBREW_HOME={$home}");
     $this->logger->writeln("export PHPBREW_LOOKUP_PREFIX={$lookup}");
     if ($buildName !== false) {
         // checking php version existence
         $targetPhpBinPath = Config::getVersionBinPath($buildName);
         if (is_dir($targetPhpBinPath)) {
             echo 'export PHPBREW_PHP=' . $buildName . "\n";
             echo 'export PHPBREW_PATH=' . ($buildName ? Config::getVersionBinPath($buildName) : '') . "\n";
         }
     }
 }
Example #8
0
 public function execute($versionName = NULL)
 {
     $args = func_get_args();
     array_shift($args);
     // $currentVersion;
     $root = Config::getPhpbrewRoot();
     $home = Config::getPhpbrewHome();
     if ($versionName) {
         $sourceDir = Config::getBuildDir() . DIRECTORY_SEPARATOR . $versionName;
     } else {
         if (!getenv('PHPBREW_PHP')) {
             $this->logger->error("Error: PHPBREW_PHP environment variable is not defined.");
             $this->logger->error("  This command requires you specify a PHP version from your build list.");
             $this->logger->error("  And it looks like you haven't switched to a version from the builds that were built with PHPBrew.");
             $this->logger->error("Suggestion: Please install at least one PHP with your prefered version and switch to it.");
             return false;
         }
         $sourceDir = Config::getCurrentBuildDir();
     }
     if (!file_exists($sourceDir)) {
         return $this->logger->error("{$sourceDir} does not exist.");
     }
     $this->logger->info("Scanning " . $sourceDir);
     $cmd = new CommandBuilder('ctags');
     $cmd->arg('--recurse');
     $cmd->arg('-a');
     $cmd->arg('-h');
     $cmd->arg('.c.h.cpp');
     $cmd->arg($sourceDir . DIRECTORY_SEPARATOR . 'main');
     $cmd->arg($sourceDir . DIRECTORY_SEPARATOR . 'ext');
     $cmd->arg($sourceDir . DIRECTORY_SEPARATOR . 'Zend');
     foreach ($args as $a) {
         $cmd->arg($a);
     }
     $this->logger->debug($cmd->__toString());
     $cmd->execute();
     $this->logger->info("Done");
 }
Example #9
0
 public function execute($name)
 {
     switch ($name) {
         case 'root':
             echo Config::getPhpbrewRoot();
             break;
         case 'home':
             echo Config::getPhpbrewHome();
             break;
         case 'config-scan':
             echo Config::getCurrentPhpConfigScanPath();
             break;
         case 'dist':
             echo Config::getDistFileDir();
             break;
         case 'build':
             echo Config::getCurrentBuildDir();
             break;
         case 'bin':
             echo Config::getCurrentPhpBin();
             break;
         case 'include':
             echo Config::getVersionInstallPrefix(Config::getCurrentPhpName()) . DIRECTORY_SEPARATOR . 'include';
             break;
         case 'extension-src':
         case 'ext-src':
             echo Config::getCurrentBuildDir() . DIRECTORY_SEPARATOR . 'ext';
             break;
         case 'extension-dir':
         case 'ext-dir':
         case 'ext':
             echo ini_get('extension_dir');
             break;
         case 'etc':
             echo Config::getVersionInstallPrefix(Config::getCurrentPhpName()) . DIRECTORY_SEPARATOR . 'etc';
             break;
     }
 }
Example #10
0
    public function execute()
    {
        // $currentVersion;
        $root = Config::getPhpbrewRoot();
        $home = Config::getPhpbrewHome();
        $buildDir = Config::getBuildDir();
        $buildPrefix = Config::getInstallPrefix();
        // $versionBuildPrefix = Config::getVersionInstallPrefix($version);
        // $versionBinPath     = Config::getVersionBinPath($version);
        if (!file_exists($root)) {
            mkdir($root, 0755, true);
        }
        $paths = array();
        $paths[] = $home;
        $paths[] = $root;
        $paths[] = $buildDir;
        $paths[] = $buildPrefix;
        foreach ($paths as $p) {
            $this->logger->info("Checking directory {$p}");
            if (!file_exists($p)) {
                $this->logger->info("Creating directory {$p}");
                mkdir($p, 0755, true);
            }
        }
        $this->logger->info('Creating .metadata_never_index to prevent SpotLight indexing');
        touch($root . DIRECTORY_SEPARATOR . '.metadata_never_index');
        // prevent spotlight index here
        touch($home . DIRECTORY_SEPARATOR . '.metadata_never_index');
        if ($configFile = $this->options->{'config'}) {
            if (!file_exists($configFile)) {
                return $this->logger->error("{$configFile} does not exist.");
            }
            $this->logger->debug("Using yaml config from {$configFile}");
            copy($configFile, $root . DIRECTORY_SEPARATOR . 'config.yaml');
        }
        $this->logger->writeln($this->formatter->format("Initialization successfully finished!", 'strong_green'));
        $this->logger->writeln($this->formatter->format("<=====================================================>", 'strong_white'));
        // write bashrc script to phpbrew home
        file_put_contents($home . '/bashrc', $this->getBashScript());
        // write phpbrew.fish script to phpbrew home
        file_put_contents($home . '/phpbrew.fish', $this->getFishScript());
        if (strpos(getenv("SHELL"), "fish") !== false) {
            $initConfig = <<<EOS
Paste the following line(s) to the end of your ~/.config/fish/config.fish and start a
new shell, phpbrew should be up and fully functional from there:

    source {$home}/phpbrew.fish
EOS;
        } else {
            $initConfig = <<<EOS
Paste the following line(s) to the end of your ~/.bashrc and start a
new shell, phpbrew should be up and fully functional from there:

    source {$home}/bashrc

To enable PHP version info in your shell prompt, please set PHPBREW_SET_PROMPT=1
in your `~/.bashrc` before you source `~/.phpbrew/bashrc`

    export PHPBREW_SET_PROMPT=1
EOS;
        }
        echo <<<EOS
Phpbrew environment is initialized, required directories are created under

    {$home}

{$initConfig}

For further instructions, simply run `phpbrew` to see the help message.

Enjoy phpbrew at \$HOME!!


EOS;
        $this->logger->writeln($this->formatter->format("<=====================================================>", 'strong_white'));
    }
Example #11
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;
    }
Example #12
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;
    }