mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 14:25:41 +08:00
move pgo from new to static creation method
This commit is contained in:
@@ -23,6 +23,8 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
/** @var bool Micro patch phar flag */
|
||||
private bool $phar_patched = false;
|
||||
|
||||
private ?PgoManager $pgo = null;
|
||||
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->options = $options;
|
||||
@@ -49,6 +51,8 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
*/
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
|
||||
{
|
||||
$this->pgo = PgoManager::fromBuilder($this, $build_target);
|
||||
|
||||
$cflags = $this->arch_c_flags;
|
||||
f_putenv('CFLAGS=' . $cflags);
|
||||
|
||||
@@ -134,7 +138,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
|
||||
$this->cleanMake();
|
||||
|
||||
$pgo = PgoManager::active();
|
||||
$pgo = $this->pgo;
|
||||
$needsClean = false;
|
||||
$sapiBuilds = [
|
||||
['cli', $enableCli, true, fn () => $this->buildCli()],
|
||||
|
||||
@@ -12,7 +12,6 @@ use SPC\store\SourcePatcher;
|
||||
use SPC\util\DependencyUtil;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
use SPC\util\LicenseDumper;
|
||||
use SPC\util\PgoManager;
|
||||
use SPC\util\SPCTarget;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
@@ -215,20 +214,6 @@ class BuildPHPCommand extends BuildCommand
|
||||
// clean old modules that may conflict with the new php build
|
||||
FileSystem::removeDir(BUILD_MODULES_PATH);
|
||||
|
||||
$pgi = (bool) $this->getOption('pgi');
|
||||
$csPgi = (bool) $this->getOption('cs-pgi');
|
||||
$pgo = (bool) $this->getOption('pgo');
|
||||
if (((int) $pgi + (int) $csPgi + (int) $pgo) > 1) {
|
||||
$this->output->writeln('<error>--pgi, --cs-pgi, and --pgo are mutually exclusive</error>');
|
||||
return static::FAILURE;
|
||||
}
|
||||
if ($pgi) {
|
||||
(new PgoManager())->setupInstrument($rule);
|
||||
} elseif ($csPgi) {
|
||||
(new PgoManager())->setupCsInstrument($rule);
|
||||
} elseif ($pgo) {
|
||||
(new PgoManager())->setupUse($rule);
|
||||
}
|
||||
$builder->buildPHP($rule);
|
||||
$builder->testPHP($rule);
|
||||
|
||||
|
||||
@@ -43,64 +43,29 @@ class PgoManager
|
||||
|
||||
private string $mode;
|
||||
|
||||
private static ?self $active = null;
|
||||
|
||||
public function __construct()
|
||||
private function __construct()
|
||||
{
|
||||
$this->profileRoot = BUILD_ROOT_PATH . '/pgo-data';
|
||||
}
|
||||
|
||||
public static function active(): ?self
|
||||
/** Build a PgoManager for the active --pgi/--cs-pgi/--pgo option, or null if none set. */
|
||||
public static function fromBuilder(BuilderBase $builder, int $rule): ?self
|
||||
{
|
||||
return self::$active;
|
||||
}
|
||||
|
||||
/** Setup --pgi: build with -fprofile-generate=<sapi-dir>. */
|
||||
public function setupInstrument(int $rule): void
|
||||
{
|
||||
$this->validateRule($rule);
|
||||
FileSystem::removeDir($this->profileRoot);
|
||||
f_mkdir($this->profileRoot, recursive: true);
|
||||
foreach ($this->trainableIn($rule) as $sapi) {
|
||||
f_mkdir($this->rawDir($sapi), recursive: true);
|
||||
$modes = array_filter(['pgi', 'cs-pgi', 'pgo'], fn ($m) => (bool) $builder->getOption($m));
|
||||
if (count($modes) > 1) {
|
||||
throw new WrongUsageException('--pgi, --cs-pgi, and --pgo are mutually exclusive');
|
||||
}
|
||||
$this->mode = self::MODE_INSTRUMENT;
|
||||
self::$active = $this;
|
||||
$this->applyShutdownPatches();
|
||||
$this->applyForSapi($this->trainableIn($rule)[0]);
|
||||
logger()->info('pgo --pgi: instrumented build, profraw will land under ' . $this->profileRoot . '/<sapi>/');
|
||||
}
|
||||
|
||||
/** Setup --cs-pgi: build with -fprofile-use=<sapi.profdata> -fcs-profile-generate=<cs-dir>. Requires existing .profdata. */
|
||||
public function setupCsInstrument(int $rule): void
|
||||
{
|
||||
$this->validateRule($rule);
|
||||
foreach ($this->trainableIn($rule) as $sapi) {
|
||||
if (!is_file($this->profDataFile($sapi))) {
|
||||
throw new WrongUsageException("--cs-pgi: missing {$sapi}.profdata; run --pgi + --pgo first");
|
||||
}
|
||||
f_mkdir($this->csRawDir($sapi), recursive: true);
|
||||
$mode = array_values($modes)[0] ?? null;
|
||||
if ($mode === null) {
|
||||
return null;
|
||||
}
|
||||
$this->mode = self::MODE_CS_INSTRUMENT;
|
||||
self::$active = $this;
|
||||
$this->applyShutdownPatches();
|
||||
$this->applyForSapi($this->trainableIn($rule)[0]);
|
||||
logger()->info('pgo --cs-pgi: cs-instrumented build, cs-profraw under ' . $this->profileRoot . '/cs-<sapi>/');
|
||||
}
|
||||
|
||||
/** Setup --pgo: merge collected .profraw, then build with -fprofile-use=<sapi.profdata>. */
|
||||
public function setupUse(int $rule): void
|
||||
{
|
||||
$this->validateRule($rule);
|
||||
if (trim((string) shell_exec('command -v llvm-profdata 2>/dev/null')) === '') {
|
||||
throw new WrongUsageException('--pgo: llvm-profdata not on PATH');
|
||||
}
|
||||
foreach ($this->trainableIn($rule) as $sapi) {
|
||||
$this->mergeSapi($sapi);
|
||||
}
|
||||
$this->mode = self::MODE_USE;
|
||||
self::$active = $this;
|
||||
$this->applyForSapi($this->trainableIn($rule)[0]);
|
||||
$instance = new self();
|
||||
match ($mode) {
|
||||
'pgi' => $instance->setupInstrument($rule),
|
||||
'cs-pgi' => $instance->setupCsInstrument($rule),
|
||||
'pgo' => $instance->setupUse($rule),
|
||||
};
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/** Patches php-src/libtool to passthrough -fcs-profile-* flags (otherwise dropped during shared lib link). */
|
||||
@@ -155,6 +120,51 @@ class PgoManager
|
||||
logger()->info("pgo {$this->mode} ({$sapi})");
|
||||
}
|
||||
|
||||
/** Setup --pgi: build with -fprofile-generate=<sapi-dir>. */
|
||||
private function setupInstrument(int $rule): void
|
||||
{
|
||||
$this->validateRule($rule);
|
||||
FileSystem::removeDir($this->profileRoot);
|
||||
f_mkdir($this->profileRoot, recursive: true);
|
||||
foreach ($this->trainableIn($rule) as $sapi) {
|
||||
f_mkdir($this->rawDir($sapi), recursive: true);
|
||||
}
|
||||
$this->mode = self::MODE_INSTRUMENT;
|
||||
$this->applyShutdownPatches();
|
||||
$this->applyForSapi($this->trainableIn($rule)[0]);
|
||||
logger()->info('pgo --pgi: instrumented build, profraw will land under ' . $this->profileRoot . '/<sapi>/');
|
||||
}
|
||||
|
||||
/** Setup --cs-pgi: build with -fprofile-use=<sapi.profdata> -fcs-profile-generate=<cs-dir>. Requires existing .profdata. */
|
||||
private function setupCsInstrument(int $rule): void
|
||||
{
|
||||
$this->validateRule($rule);
|
||||
foreach ($this->trainableIn($rule) as $sapi) {
|
||||
if (!is_file($this->profDataFile($sapi))) {
|
||||
throw new WrongUsageException("--cs-pgi: missing {$sapi}.profdata; run --pgi + --pgo first");
|
||||
}
|
||||
f_mkdir($this->csRawDir($sapi), recursive: true);
|
||||
}
|
||||
$this->mode = self::MODE_CS_INSTRUMENT;
|
||||
$this->applyShutdownPatches();
|
||||
$this->applyForSapi($this->trainableIn($rule)[0]);
|
||||
logger()->info('pgo --cs-pgi: cs-instrumented build, cs-profraw under ' . $this->profileRoot . '/cs-<sapi>/');
|
||||
}
|
||||
|
||||
/** Setup --pgo: merge collected .profraw, then build with -fprofile-use=<sapi.profdata>. */
|
||||
private function setupUse(int $rule): void
|
||||
{
|
||||
$this->validateRule($rule);
|
||||
if (trim((string) shell_exec('command -v llvm-profdata 2>/dev/null')) === '') {
|
||||
throw new WrongUsageException('--pgo: llvm-profdata not on PATH');
|
||||
}
|
||||
foreach ($this->trainableIn($rule) as $sapi) {
|
||||
$this->mergeSapi($sapi);
|
||||
}
|
||||
$this->mode = self::MODE_USE;
|
||||
$this->applyForSapi($this->trainableIn($rule)[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static-embed mode links libphp.a into frankenphp; both end up in one
|
||||
* binary so must share one profdata. Shared-embed mode keeps libphp.so
|
||||
|
||||
Reference in New Issue
Block a user