Skip to content

Commit a4bd2a7

Browse files
committed
Add shared extension build support
1 parent 7b16f68 commit a4bd2a7

File tree

2 files changed

+219
-37
lines changed

2 files changed

+219
-37
lines changed

src/Package/Target/php.php

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use StaticPHP\Attribute\Package\Target;
1515
use StaticPHP\Attribute\Package\Validate;
1616
use StaticPHP\Attribute\PatchDescription;
17+
use StaticPHP\Config\PackageConfig;
1718
use StaticPHP\DI\ApplicationContext;
1819
use StaticPHP\Exception\SPCException;
1920
use StaticPHP\Exception\WrongUsageException;
@@ -111,7 +112,7 @@ public function init(TargetPackage $package): void
111112
}
112113

113114
#[ResolveBuild]
114-
public function resolveBuild(TargetPackage $package): array
115+
public function resolveBuild(TargetPackage $package, PackageInstaller $installer): array
115116
{
116117
// Parse extensions and additional packages for all php-* targets
117118
$static_extensions = parse_extension_list($package->getBuildArgument('extensions'));
@@ -128,6 +129,7 @@ public function resolveBuild(TargetPackage $package): array
128129
// get instances
129130
foreach ($extensions_pkg as $extension) {
130131
$extname = substr($extension, 4);
132+
$config = PackageConfig::get($extension, 'php-extension', []);
131133
if (!PackageLoader::hasPackage($extension)) {
132134
throw new WrongUsageException("Extension [{$extname}] does not exist. Please check your extension name.");
133135
}
@@ -137,13 +139,25 @@ public function resolveBuild(TargetPackage $package): array
137139
}
138140
// set build static/shared
139141
if (in_array($extname, $static_extensions)) {
142+
if (($config['build-static'] ?? true) === false) {
143+
throw new WrongUsageException("Extension [{$extname}] cannot be built as static extension.");
144+
}
140145
$instance->setBuildStatic();
141146
}
142147
if (in_array($extname, $shared_extensions)) {
148+
if (($config['build-shared'] ?? true) === false) {
149+
throw new WrongUsageException("Extension [{$extname}] cannot be built as shared extension, please remove it from --build-shared option.");
150+
}
143151
$instance->setBuildShared();
152+
$instance->setBuildWithPhp($config['build-with-php'] ?? false);
144153
}
145154
}
146155

156+
// building shared extensions need embed SAPI
157+
if (!empty($shared_extensions) && !$package->getBuildOption('build-embed', false) && $package->getName() === 'php') {
158+
$installer->addBuildPackage('php-embed');
159+
}
160+
147161
return [...$extensions_pkg, ...$additional_packages];
148162
}
149163

@@ -178,14 +192,14 @@ public function info(Package $package, PackageInstaller $installer): array
178192
return [];
179193
}
180194
$sapis = array_filter([
181-
$installer->getBuildPackage('php-cli') ? 'cli' : null,
182-
$installer->getBuildPackage('php-fpm') ? 'fpm' : null,
183-
$installer->getBuildPackage('php-micro') ? 'micro' : null,
184-
$installer->getBuildPackage('php-cgi') ? 'cgi' : null,
185-
$installer->getBuildPackage('php-embed') ? 'embed' : null,
186-
$installer->getBuildPackage('frankenphp') ? 'frankenphp' : null,
195+
$installer->isPackageResolved('php-cli') ? 'cli' : null,
196+
$installer->isPackageResolved('php-fpm') ? 'fpm' : null,
197+
$installer->isPackageResolved('php-micro') ? 'micro' : null,
198+
$installer->isPackageResolved('php-cgi') ? 'cgi' : null,
199+
$installer->isPackageResolved('php-embed') ? 'embed' : null,
200+
$installer->isPackageResolved('frankenphp') ? 'frankenphp' : null,
187201
]);
188-
$static_extensions = array_filter($installer->getResolvedPackages(), fn ($x) => $x->getType() === 'php-extension');
202+
$static_extensions = array_filter($installer->getResolvedPackages(), fn ($x) => $x instanceof PhpExtensionPackage && $x->isBuildStatic());
189203
$shared_extensions = parse_extension_list($package->getBuildOption('build-shared') ?? []);
190204
$install_packages = array_filter($installer->getResolvedPackages(), fn ($x) => $x->getType() !== 'php-extension' && $x->getName() !== 'php' && !str_starts_with($x->getName(), 'php-'));
191205
return [
@@ -281,15 +295,15 @@ public function configureForUnix(TargetPackage $package, PackageInstaller $insta
281295
$args[] = "--with-config-file-scan-dir={$option}";
282296
}
283297
// perform enable cli options
284-
$args[] = $installer->isBuildPackage('php-cli') ? '--enable-cli' : '--disable-cli';
285-
$args[] = $installer->isBuildPackage('php-fpm') ? '--enable-fpm' : '--disable-fpm';
286-
$args[] = $installer->isBuildPackage('php-micro') ? match (SystemTarget::getTargetOS()) {
298+
$args[] = $installer->isPackageResolved('php-cli') ? '--enable-cli' : '--disable-cli';
299+
$args[] = $installer->isPackageResolved('php-fpm') ? '--enable-fpm' : '--disable-fpm';
300+
$args[] = $installer->isPackageResolved('php-micro') ? match (SystemTarget::getTargetOS()) {
287301
'Linux' => '--enable-micro=all-static',
288302
default => '--enable-micro',
289303
} : null;
290-
$args[] = $installer->isBuildPackage('php-cgi') ? '--enable-cgi' : '--disable-cgi';
304+
$args[] = $installer->isPackageResolved('php-cgi') ? '--enable-cgi' : '--disable-cgi';
291305
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
292-
$args[] = $installer->isBuildPackage('php-embed') ? "--enable-embed={$embed_type}" : '--disable-embed';
306+
$args[] = $installer->isPackageResolved('php-embed') ? "--enable-embed={$embed_type}" : '--disable-embed';
293307
$args[] = getenv('SPC_EXTRA_PHP_VARS') ?: null;
294308
$args = implode(' ', array_filter($args));
295309

@@ -311,19 +325,19 @@ public function makeForUnix(TargetPackage $package, PackageInstaller $installer)
311325
logger()->info('cleaning up php-src build files');
312326
shell()->cd($package->getSourceDir())->exec('make clean');
313327

314-
if ($installer->isBuildPackage('php-cli')) {
328+
if ($installer->isPackageResolved('php-cli')) {
315329
$package->runStage('unix-make-cli');
316330
}
317-
if ($installer->isBuildPackage('php-cgi')) {
331+
if ($installer->isPackageResolved('php-cgi')) {
318332
$package->runStage('unix-make-cgi');
319333
}
320-
if ($installer->isBuildPackage('php-fpm')) {
334+
if ($installer->isPackageResolved('php-fpm')) {
321335
$package->runStage('unix-make-fpm');
322336
}
323-
if ($installer->isBuildPackage('php-micro')) {
337+
if ($installer->isPackageResolved('php-micro')) {
324338
$package->runStage('unix-make-micro');
325339
}
326-
if ($installer->isBuildPackage('php-embed')) {
340+
if ($installer->isPackageResolved('php-embed')) {
327341
$package->runStage('unix-make-embed');
328342
}
329343
}
@@ -359,6 +373,7 @@ public function makeFpmForUnix(TargetPackage $package, PackageInstaller $install
359373
}
360374

361375
#[Stage('unix-make-micro')]
376+
#[PatchDescription('Patch phar extension for micro SAPI to support compressed phar')]
362377
public function makeMicroForUnix(TargetPackage $package, PackageInstaller $installer, PackageBuilder $builder): void
363378
{
364379
$phar_patched = false;
@@ -375,6 +390,8 @@ public function makeMicroForUnix(TargetPackage $package, PackageInstaller $insta
375390
shell()->cd($package->getSourceDir())
376391
->setEnv($vars)
377392
->exec("make -j{$builder->concurrency} micro");
393+
394+
$builder->deployBinary($package->getSourceDir() . '/sapi/micro/micro.sfx', BUILD_BIN_PATH . '/micro.sfx');
378395
} finally {
379396
if ($phar_patched) {
380397
SourcePatcher::unpatchMicroPhar();
@@ -385,6 +402,7 @@ public function makeMicroForUnix(TargetPackage $package, PackageInstaller $insta
385402
#[Stage('unix-make-embed')]
386403
public function makeEmbedForUnix(TargetPackage $package, PackageInstaller $installer, PackageBuilder $builder): void
387404
{
405+
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('make embed'));
388406
$shared_exts = array_filter(
389407
$installer->getResolvedPackages(),
390408
static fn ($x) => $x instanceof PhpExtensionPackage && $x->isBuildShared() && $x->isBuildWithPhp()
@@ -395,9 +413,11 @@ public function makeEmbedForUnix(TargetPackage $package, PackageInstaller $insta
395413
$diff = new DirDiff(BUILD_MODULES_PATH, true);
396414

397415
$root = BUILD_ROOT_PATH;
416+
$sed_prefix = SystemTarget::getTargetOS() === 'Darwin' ? 'sed -i ""' : 'sed -i';
417+
398418
shell()->cd($package->getSourceDir())
399419
->setEnv($this->makeVars($installer))
400-
->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
420+
->exec("{$sed_prefix} \"s|^EXTENSION_DIR = .*|EXTENSION_DIR = /" . basename(BUILD_MODULES_PATH) . '|" Makefile')
401421
->exec("make -j{$builder->concurrency} INSTALL_ROOT={$root} install-sapi {$install_modules} install-build install-headers install-programs");
402422

403423
// ------------- SPC_CMD_VAR_PHP_EMBED_TYPE=shared -------------
@@ -417,12 +437,15 @@ public function makeEmbedForUnix(TargetPackage $package, PackageInstaller $insta
417437
// process shared extensions that built-with-php
418438
$increment_files = $diff->getChangedFiles();
419439
foreach ($increment_files as $increment_file) {
420-
$builder->deployBinary($increment_file, $libphp_so, false);
440+
$builder->deployBinary($increment_file, $increment_file, false);
421441
}
422442

423443
// ------------- SPC_CMD_VAR_PHP_EMBED_TYPE=static -------------
424444

425445
// process libphp.a for static embed
446+
if (!file_exists("{$package->getLibDir()}/libphp.a")) {
447+
return;
448+
}
426449
$ar = getenv('AR') ?: 'ar';
427450
$libphp_a = "{$package->getLibDir()}/libphp.a";
428451
shell()->exec("{$ar} -t {$libphp_a} | grep '\\.a$' | xargs -n1 {$ar} d {$libphp_a}");
@@ -432,19 +455,9 @@ public function makeEmbedForUnix(TargetPackage $package, PackageInstaller $insta
432455
$package->runStage('patch-embed-scripts');
433456
}
434457

435-
#[BuildFor('Darwin')]
436-
#[BuildFor('Linux')]
437-
public function build(TargetPackage $package, PackageInstaller $installer, ToolchainInterface $toolchain): void
458+
#[Stage('unix-build-shared-ext')]
459+
public function unixBuildSharedExt(PackageInstaller $installer, ToolchainInterface $toolchain): void
438460
{
439-
// virtual target, do nothing
440-
if ($package->getName() !== 'php') {
441-
return;
442-
}
443-
444-
$package->runStage('unix-buildconf');
445-
$package->runStage('unix-configure');
446-
$package->runStage('unix-make');
447-
448461
// collect shared extensions
449462
/** @var PhpExtensionPackage[] $shared_extensions */
450463
$shared_extensions = array_filter(
@@ -470,9 +483,10 @@ public function build(TargetPackage $package, PackageInstaller $installer, Toolc
470483
}
471484

472485
try {
486+
logger()->debug('Building shared extensions...');
473487
foreach ($shared_extensions as $extension) {
474-
logger()->info('Building shared extensions...');
475-
$extension->buildSharedExtension();
488+
InteractiveTerm::setMessage('Building shared PHP extension: ' . ConsoleColor::yellow($extension->getName()));
489+
$extension->buildShared();
476490
}
477491
} finally {
478492
// restore php-config
@@ -483,6 +497,22 @@ public function build(TargetPackage $package, PackageInstaller $installer, Toolc
483497
}
484498
}
485499

500+
#[BuildFor('Darwin')]
501+
#[BuildFor('Linux')]
502+
public function build(TargetPackage $package): void
503+
{
504+
// virtual target, do nothing
505+
if ($package->getName() !== 'php') {
506+
return;
507+
}
508+
509+
$package->runStage('unix-buildconf');
510+
$package->runStage('unix-configure');
511+
$package->runStage('unix-make');
512+
513+
$package->runStage('unix-build-shared-ext');
514+
}
515+
486516
/**
487517
* Patch phpize and php-config if needed
488518
*/

0 commit comments

Comments
 (0)