2023-03-21 00:25:46 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace SPC\builder\linux;
|
|
|
|
|
|
2024-01-10 21:08:25 +08:00
|
|
|
use SPC\builder\unix\UnixBuilderBase;
|
2023-03-21 00:25:46 +08:00
|
|
|
use SPC\exception\FileSystemException;
|
|
|
|
|
use SPC\exception\RuntimeException;
|
2023-03-29 21:39:36 +08:00
|
|
|
use SPC\exception\WrongUsageException;
|
2023-10-01 01:32:43 +08:00
|
|
|
use SPC\store\FileSystem;
|
2023-04-30 12:42:19 +08:00
|
|
|
use SPC\store\SourcePatcher;
|
2024-04-07 15:52:24 +08:00
|
|
|
use SPC\util\GlobalEnvManager;
|
2025-07-22 19:59:44 +08:00
|
|
|
use SPC\util\SPCConfigUtil;
|
2025-07-01 16:57:56 +07:00
|
|
|
use SPC\util\SPCTarget;
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2024-01-10 21:08:25 +08:00
|
|
|
class LinuxBuilder extends UnixBuilderBase
|
2023-03-21 00:25:46 +08:00
|
|
|
{
|
2023-08-20 19:51:45 +08:00
|
|
|
/** @var bool Micro patch phar flag */
|
2023-03-21 00:25:46 +08:00
|
|
|
private bool $phar_patched = false;
|
|
|
|
|
|
|
|
|
|
/**
|
2023-08-20 19:51:45 +08:00
|
|
|
* @throws FileSystemException
|
2023-04-15 18:45:34 +08:00
|
|
|
* @throws WrongUsageException
|
2023-03-21 00:25:46 +08:00
|
|
|
*/
|
2023-08-20 19:51:45 +08:00
|
|
|
public function __construct(array $options = [])
|
2023-03-21 00:25:46 +08:00
|
|
|
{
|
2023-08-20 19:51:45 +08:00
|
|
|
$this->options = $options;
|
|
|
|
|
|
2025-06-22 20:44:11 +08:00
|
|
|
GlobalEnvManager::init();
|
2025-06-28 16:36:05 +08:00
|
|
|
GlobalEnvManager::afterInit();
|
2024-04-07 16:26:21 +08:00
|
|
|
|
2023-08-20 19:51:45 +08:00
|
|
|
// concurrency
|
2025-07-04 14:39:42 +07:00
|
|
|
$this->concurrency = (int) getenv('SPC_CONCURRENCY');
|
2023-08-20 19:51:45 +08:00
|
|
|
// cflags
|
2024-04-07 15:52:24 +08:00
|
|
|
$this->arch_c_flags = getenv('SPC_DEFAULT_C_FLAGS');
|
|
|
|
|
$this->arch_cxx_flags = getenv('SPC_DEFAULT_CXX_FLAGS');
|
2023-10-23 00:37:28 +08:00
|
|
|
|
2023-08-20 19:51:45 +08:00
|
|
|
// create pkgconfig and include dir (some libs cannot create them automatically)
|
2023-03-21 00:25:46 +08:00
|
|
|
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
|
|
|
|
|
f_mkdir(BUILD_INCLUDE_PATH, recursive: true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2024-05-16 10:51:31 +08:00
|
|
|
* Build PHP from source.
|
|
|
|
|
*
|
|
|
|
|
* @param int $build_target Build target, use `BUILD_TARGET_*` constants
|
2023-03-21 00:25:46 +08:00
|
|
|
* @throws RuntimeException
|
|
|
|
|
* @throws FileSystemException
|
2023-08-20 19:51:45 +08:00
|
|
|
* @throws WrongUsageException
|
2023-03-21 00:25:46 +08:00
|
|
|
*/
|
2023-08-20 19:51:45 +08:00
|
|
|
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
|
2023-03-21 00:25:46 +08:00
|
|
|
{
|
|
|
|
|
$cflags = $this->arch_c_flags;
|
2025-03-10 00:39:20 +08:00
|
|
|
f_putenv('CFLAGS=' . $cflags);
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2024-01-03 15:57:05 +08:00
|
|
|
$this->emitPatchPoint('before-php-buildconf');
|
2023-07-28 23:45:39 +08:00
|
|
|
SourcePatcher::patchBeforeBuildconf($this);
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2024-04-07 15:52:24 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src')->exec(getenv('SPC_CMD_PREFIX_PHP_BUILDCONF'));
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2024-01-03 15:57:05 +08:00
|
|
|
$this->emitPatchPoint('before-php-configure');
|
2023-07-28 23:45:39 +08:00
|
|
|
SourcePatcher::patchBeforeConfigure($this);
|
2023-05-10 02:04:08 +08:00
|
|
|
|
2023-08-21 12:54:36 +02:00
|
|
|
$phpVersionID = $this->getPHPVersionID();
|
|
|
|
|
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
|
2023-08-21 18:37:00 +02:00
|
|
|
|
|
|
|
|
if ($this->getOption('enable-zts', false)) {
|
|
|
|
|
$maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : '';
|
|
|
|
|
$zts = '--enable-zts --disable-zend-signals ';
|
|
|
|
|
} else {
|
|
|
|
|
$maxExecutionTimers = '';
|
|
|
|
|
$zts = '';
|
|
|
|
|
}
|
2023-10-16 14:05:07 +02:00
|
|
|
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
|
2025-07-01 16:57:56 +07:00
|
|
|
if (!$disable_jit && $this->getExt('opcache')) {
|
2025-07-04 14:39:42 +07:00
|
|
|
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
|
2025-07-01 16:57:56 +07:00
|
|
|
}
|
2024-10-12 10:41:45 +02:00
|
|
|
$config_file_path = $this->getOption('with-config-file-path', false) ?
|
|
|
|
|
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
|
2024-10-18 14:46:00 +02:00
|
|
|
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
|
|
|
|
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
|
2024-10-12 10:41:45 +02:00
|
|
|
|
2025-06-18 11:20:05 +07:00
|
|
|
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
|
|
|
|
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
|
|
|
|
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
|
|
|
|
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
|
|
|
|
$enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP;
|
2023-08-21 09:30:46 +02:00
|
|
|
|
2024-04-07 15:52:24 +08:00
|
|
|
// prepare build php envs
|
2025-07-24 10:53:49 +07:00
|
|
|
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
|
2025-07-24 21:32:14 +07:00
|
|
|
if (str_contains($config['libs'], ' -lpgport') && !$this->getExt('pgsql')?->isBuildStatic()) {
|
|
|
|
|
// -lpgport defines many glibc functions if they are missing, which leads to feature tests succeeding that aren't meant to succeed
|
|
|
|
|
$config['libs'] = str_replace(' -lpgport', '', $config['libs']);
|
|
|
|
|
}
|
2024-04-07 15:52:24 +08:00
|
|
|
$envs_build_php = SystemUtil::makeEnvVarString([
|
|
|
|
|
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
|
|
|
|
|
'CPPFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS'),
|
2025-07-25 12:44:22 +08:00
|
|
|
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
|
2025-07-24 10:53:49 +07:00
|
|
|
'LIBS' => $config['libs'],
|
2024-04-07 15:52:24 +08:00
|
|
|
]);
|
|
|
|
|
|
2025-03-10 16:15:47 +08:00
|
|
|
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
|
2025-07-01 16:57:56 +07:00
|
|
|
if ($embed_type !== 'static' && SPCTarget::isStatic()) {
|
|
|
|
|
throw new WrongUsageException(
|
|
|
|
|
'Linux does not support loading shared libraries when linking libc statically. ' .
|
|
|
|
|
'Change SPC_CMD_VAR_PHP_EMBED_TYPE to static.'
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-03-26 22:27:51 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src')
|
|
|
|
|
->exec(
|
2024-04-07 15:52:24 +08:00
|
|
|
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
|
2025-06-18 11:20:05 +07:00
|
|
|
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
|
|
|
|
($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') .
|
|
|
|
|
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
|
|
|
|
|
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
|
2024-10-12 10:41:45 +02:00
|
|
|
$config_file_path .
|
2024-10-18 14:46:00 +02:00
|
|
|
$config_file_scan_dir .
|
2023-10-16 14:05:07 +02:00
|
|
|
$disable_jit .
|
2023-05-04 11:29:14 +08:00
|
|
|
$json_74 .
|
2023-08-20 19:51:45 +08:00
|
|
|
$zts .
|
2023-08-21 12:54:36 +02:00
|
|
|
$maxExecutionTimers .
|
2025-03-24 23:50:12 +08:00
|
|
|
$this->makeStaticExtensionArgs() .
|
2024-01-03 10:31:21 +08:00
|
|
|
' ' . $envs_build_php . ' '
|
2023-03-26 22:27:51 +08:00
|
|
|
);
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2024-01-03 15:57:05 +08:00
|
|
|
$this->emitPatchPoint('before-php-make');
|
2023-07-28 23:45:39 +08:00
|
|
|
SourcePatcher::patchBeforeMake($this);
|
2023-04-30 12:42:19 +08:00
|
|
|
|
2023-03-26 22:27:51 +08:00
|
|
|
$this->cleanMake();
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2025-06-18 11:20:05 +07:00
|
|
|
if ($enableCli) {
|
2023-04-23 20:31:58 +08:00
|
|
|
logger()->info('building cli');
|
2023-10-30 22:14:47 +01:00
|
|
|
$this->buildCli();
|
2023-04-23 20:31:58 +08:00
|
|
|
}
|
2025-06-18 11:20:05 +07:00
|
|
|
if ($enableFpm) {
|
2023-04-23 20:31:58 +08:00
|
|
|
logger()->info('building fpm');
|
2023-10-30 22:14:47 +01:00
|
|
|
$this->buildFpm();
|
2023-04-23 20:31:58 +08:00
|
|
|
}
|
2025-06-18 11:20:05 +07:00
|
|
|
if ($enableMicro) {
|
2023-04-23 20:31:58 +08:00
|
|
|
logger()->info('building micro');
|
2023-10-30 22:14:47 +01:00
|
|
|
$this->buildMicro();
|
2023-03-21 00:25:46 +08:00
|
|
|
}
|
2025-06-18 11:20:05 +07:00
|
|
|
if ($enableEmbed) {
|
2023-08-21 09:30:46 +02:00
|
|
|
logger()->info('building embed');
|
2025-06-18 11:20:05 +07:00
|
|
|
if ($enableMicro) {
|
2023-10-01 01:32:43 +08:00
|
|
|
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la');
|
|
|
|
|
}
|
2023-10-30 22:14:47 +01:00
|
|
|
$this->buildEmbed();
|
2023-08-21 09:30:46 +02:00
|
|
|
}
|
2025-06-18 11:20:05 +07:00
|
|
|
if ($enableFrankenphp) {
|
2025-06-18 10:48:09 +07:00
|
|
|
logger()->info('building frankenphp');
|
|
|
|
|
$this->buildFrankenphp();
|
|
|
|
|
}
|
2025-05-21 18:35:48 +07:00
|
|
|
}
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2025-05-21 18:35:48 +07:00
|
|
|
public function testPHP(int $build_target = BUILD_TARGET_NONE)
|
|
|
|
|
{
|
2025-03-14 18:22:50 +08:00
|
|
|
$this->emitPatchPoint('before-sanity-check');
|
|
|
|
|
$this->sanityCheck($build_target);
|
2023-03-21 00:25:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-08-20 19:51:45 +08:00
|
|
|
* Build cli sapi
|
|
|
|
|
*
|
2023-03-21 00:25:46 +08:00
|
|
|
* @throws RuntimeException
|
2023-08-20 19:51:45 +08:00
|
|
|
* @throws FileSystemException
|
2023-03-21 00:25:46 +08:00
|
|
|
*/
|
2024-01-10 11:10:40 +08:00
|
|
|
protected function buildCli(): void
|
2023-03-21 00:25:46 +08:00
|
|
|
{
|
2024-04-07 15:52:24 +08:00
|
|
|
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
2025-05-25 09:37:15 +07:00
|
|
|
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
2023-03-26 22:27:51 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src')
|
|
|
|
|
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
2025-05-25 10:47:32 +07:00
|
|
|
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
|
2023-08-20 19:51:45 +08:00
|
|
|
|
2025-07-05 12:01:52 +07:00
|
|
|
if (!$this->getOption('no-strip', false)) {
|
2025-07-05 13:52:47 +07:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-unneeded php');
|
2025-07-05 12:01:52 +07:00
|
|
|
}
|
2024-02-19 15:29:43 +08:00
|
|
|
if ($this->getOption('with-upx-pack')) {
|
2024-02-19 12:17:03 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
|
2024-04-07 15:52:24 +08:00
|
|
|
->exec(getenv('UPX_EXEC') . ' --best php');
|
2023-08-20 19:51:45 +08:00
|
|
|
}
|
2023-03-26 22:27:51 +08:00
|
|
|
|
2023-04-23 20:31:58 +08:00
|
|
|
$this->deployBinary(BUILD_TARGET_CLI);
|
2023-03-21 00:25:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-08-20 19:51:45 +08:00
|
|
|
* Build phpmicro sapi
|
|
|
|
|
*
|
|
|
|
|
* @throws FileSystemException
|
2023-10-23 00:37:28 +08:00
|
|
|
* @throws RuntimeException
|
|
|
|
|
* @throws WrongUsageException
|
2023-03-21 00:25:46 +08:00
|
|
|
*/
|
2024-01-10 11:10:40 +08:00
|
|
|
protected function buildMicro(): void
|
2023-03-21 00:25:46 +08:00
|
|
|
{
|
2023-04-03 20:47:24 +08:00
|
|
|
if ($this->getPHPVersionID() < 80000) {
|
2023-10-23 00:37:28 +08:00
|
|
|
throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
|
2023-04-03 20:47:24 +08:00
|
|
|
}
|
2023-03-21 00:25:46 +08:00
|
|
|
if ($this->getExt('phar')) {
|
|
|
|
|
$this->phar_patched = true;
|
2024-06-03 23:16:15 +08:00
|
|
|
SourcePatcher::patchMicroPhar($this->getPHPVersionID());
|
2023-03-21 00:25:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-04-07 15:52:24 +08:00
|
|
|
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
|
|
|
|
$vars = $this->getMakeExtraVars();
|
|
|
|
|
|
|
|
|
|
// patch fake cli for micro
|
|
|
|
|
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
|
|
|
|
|
$vars = SystemUtil::makeEnvVarString($vars);
|
2025-05-25 09:37:15 +07:00
|
|
|
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
2024-04-07 15:52:24 +08:00
|
|
|
|
2023-03-26 22:27:51 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src')
|
|
|
|
|
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
2025-05-25 10:47:32 +07:00
|
|
|
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} micro");
|
2023-03-21 00:25:46 +08:00
|
|
|
|
2024-06-03 23:16:15 +08:00
|
|
|
$this->processMicroUPX();
|
|
|
|
|
|
2023-04-23 20:31:58 +08:00
|
|
|
$this->deployBinary(BUILD_TARGET_MICRO);
|
2023-09-23 17:00:42 +08:00
|
|
|
|
|
|
|
|
if ($this->phar_patched) {
|
2024-06-03 23:16:15 +08:00
|
|
|
SourcePatcher::unpatchMicroPhar();
|
2023-09-23 17:00:42 +08:00
|
|
|
}
|
2023-04-23 20:31:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-08-20 19:51:45 +08:00
|
|
|
* Build fpm sapi
|
2023-04-29 18:59:47 +08:00
|
|
|
*
|
2023-08-20 19:51:45 +08:00
|
|
|
* @throws FileSystemException
|
|
|
|
|
* @throws RuntimeException
|
2023-04-23 20:31:58 +08:00
|
|
|
*/
|
2024-01-10 11:10:40 +08:00
|
|
|
protected function buildFpm(): void
|
2023-04-23 20:31:58 +08:00
|
|
|
{
|
2025-03-07 10:00:10 +01:00
|
|
|
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
2025-05-25 09:37:15 +07:00
|
|
|
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
2023-04-23 20:31:58 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src')
|
|
|
|
|
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
2025-05-25 10:47:32 +07:00
|
|
|
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} fpm");
|
2023-08-20 19:51:45 +08:00
|
|
|
|
2025-07-05 12:01:52 +07:00
|
|
|
if (!$this->getOption('no-strip', false)) {
|
2025-07-05 13:52:47 +07:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')->exec('strip --strip-unneeded php-fpm');
|
2025-07-05 12:01:52 +07:00
|
|
|
}
|
2024-02-19 15:29:43 +08:00
|
|
|
if ($this->getOption('with-upx-pack')) {
|
2024-02-19 12:17:03 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
|
2024-04-07 15:52:24 +08:00
|
|
|
->exec(getenv('UPX_EXEC') . ' --best php-fpm');
|
2023-08-20 19:51:45 +08:00
|
|
|
}
|
2023-04-23 20:31:58 +08:00
|
|
|
$this->deployBinary(BUILD_TARGET_FPM);
|
2023-03-21 00:25:46 +08:00
|
|
|
}
|
2023-08-21 09:30:46 +02:00
|
|
|
|
2023-10-23 00:37:28 +08:00
|
|
|
/**
|
|
|
|
|
* Build embed sapi
|
|
|
|
|
*
|
|
|
|
|
* @throws RuntimeException
|
|
|
|
|
*/
|
2024-01-10 11:10:40 +08:00
|
|
|
protected function buildEmbed(): void
|
2023-08-21 09:30:46 +02:00
|
|
|
{
|
2024-04-07 15:52:24 +08:00
|
|
|
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
2023-08-21 09:30:46 +02:00
|
|
|
|
2024-04-07 15:52:24 +08:00
|
|
|
shell()->cd(SOURCE_PATH . '/php-src')
|
2023-08-21 09:30:46 +02:00
|
|
|
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
2025-05-21 13:19:51 +07:00
|
|
|
->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
|
2024-04-07 15:52:24 +08:00
|
|
|
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
|
2025-06-05 13:54:17 +07:00
|
|
|
|
|
|
|
|
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS');
|
2025-07-05 13:52:47 +07:00
|
|
|
$libDir = BUILD_LIB_PATH;
|
|
|
|
|
$modulesDir = BUILD_MODULES_PATH;
|
|
|
|
|
$libphpSo = "{$libDir}/libphp.so";
|
2025-06-27 22:48:15 +07:00
|
|
|
$realLibName = 'libphp.so';
|
2025-07-22 12:25:43 +08:00
|
|
|
$cwd = getcwd();
|
2025-07-05 13:52:47 +07:00
|
|
|
|
2025-06-05 13:54:17 +07:00
|
|
|
if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) {
|
|
|
|
|
$release = $matches[1];
|
2025-07-05 13:52:47 +07:00
|
|
|
$realLibName = "libphp-{$release}.so";
|
|
|
|
|
$libphpRelease = "{$libDir}/{$realLibName}";
|
|
|
|
|
if (!file_exists($libphpRelease) && file_exists($libphpSo)) {
|
|
|
|
|
rename($libphpSo, $libphpRelease);
|
2025-06-24 12:10:01 +07:00
|
|
|
}
|
|
|
|
|
if (file_exists($libphpRelease)) {
|
2025-07-05 13:52:47 +07:00
|
|
|
chdir($libDir);
|
|
|
|
|
if (file_exists($libphpSo)) {
|
|
|
|
|
unlink($libphpSo);
|
2025-06-25 14:32:00 +07:00
|
|
|
}
|
2025-06-23 15:26:39 +07:00
|
|
|
symlink($realLibName, 'libphp.so');
|
2025-07-05 13:52:47 +07:00
|
|
|
shell()->exec(sprintf(
|
|
|
|
|
'patchelf --set-soname %s %s',
|
|
|
|
|
escapeshellarg($realLibName),
|
|
|
|
|
escapeshellarg($libphpRelease)
|
|
|
|
|
));
|
2025-06-23 15:26:39 +07:00
|
|
|
}
|
2025-07-05 13:52:47 +07:00
|
|
|
if (is_dir($modulesDir)) {
|
|
|
|
|
chdir($modulesDir);
|
2025-06-23 15:26:39 +07:00
|
|
|
foreach ($this->getExts() as $ext) {
|
|
|
|
|
if (!$ext->isBuildShared()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$name = $ext->getName();
|
|
|
|
|
$versioned = "{$name}-{$release}.so";
|
|
|
|
|
$unversioned = "{$name}.so";
|
2025-07-05 13:52:47 +07:00
|
|
|
$src = "{$modulesDir}/{$versioned}";
|
|
|
|
|
$dst = "{$modulesDir}/{$unversioned}";
|
|
|
|
|
if (is_file($src)) {
|
|
|
|
|
rename($src, $dst);
|
|
|
|
|
shell()->exec(sprintf(
|
|
|
|
|
'patchelf --set-soname %s %s',
|
|
|
|
|
escapeshellarg($unversioned),
|
|
|
|
|
escapeshellarg($dst)
|
|
|
|
|
));
|
2025-06-23 15:26:39 +07:00
|
|
|
}
|
2025-06-12 20:19:21 +07:00
|
|
|
}
|
|
|
|
|
}
|
2025-07-22 12:25:43 +08:00
|
|
|
chdir($cwd);
|
2025-07-05 13:52:47 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$target = "{$libDir}/{$realLibName}";
|
|
|
|
|
if (file_exists($target)) {
|
2025-07-05 13:53:12 +07:00
|
|
|
[, $output] = shell()->execWithResult('readelf -d ' . escapeshellarg($target));
|
2025-07-05 13:52:47 +07:00
|
|
|
$output = join("\n", $output);
|
2025-07-22 12:29:41 +08:00
|
|
|
if (preg_match('/SONAME.*\[(.+)]/', $output, $sonameMatch)) {
|
2025-07-05 13:52:47 +07:00
|
|
|
$currentSoname = $sonameMatch[1];
|
|
|
|
|
if ($currentSoname !== basename($target)) {
|
|
|
|
|
shell()->exec(sprintf(
|
|
|
|
|
'patchelf --set-soname %s %s',
|
|
|
|
|
escapeshellarg(basename($target)),
|
|
|
|
|
escapeshellarg($target)
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-05 13:54:17 +07:00
|
|
|
}
|
2025-07-05 13:52:47 +07:00
|
|
|
|
2025-06-27 22:48:15 +07:00
|
|
|
if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) {
|
2025-07-05 13:52:47 +07:00
|
|
|
shell()->cd(BUILD_LIB_PATH)->exec("strip --strip-unneeded {$realLibName}");
|
2025-06-27 22:01:37 +07:00
|
|
|
}
|
2025-03-24 23:50:12 +08:00
|
|
|
$this->patchPhpScripts();
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-07 15:52:24 +08:00
|
|
|
private function getMakeExtraVars(): array
|
2023-10-30 22:14:47 +01:00
|
|
|
{
|
2025-07-22 19:59:44 +08:00
|
|
|
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
|
2025-07-25 12:44:22 +08:00
|
|
|
$static = SPCTarget::isStatic() ? '-all-static' : '';
|
|
|
|
|
$lib = BUILD_LIB_PATH;
|
2025-06-24 23:07:17 +07:00
|
|
|
return [
|
2024-04-07 15:52:24 +08:00
|
|
|
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
|
2025-07-25 09:59:24 +07:00
|
|
|
'EXTRA_LIBS' => $config['libs'],
|
2025-06-05 13:54:17 +07:00
|
|
|
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
|
2025-07-25 12:44:22 +08:00
|
|
|
'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie",
|
2023-10-30 22:14:47 +01:00
|
|
|
];
|
|
|
|
|
}
|
2024-05-16 10:51:31 +08:00
|
|
|
|
|
|
|
|
/**
|
2025-07-22 12:29:41 +08:00
|
|
|
* Strip micro.sfx for Linux.
|
|
|
|
|
* The micro.sfx does not support UPX directly, but we can remove UPX-info segment to adapt.
|
|
|
|
|
* This will also make micro.sfx with upx-packed more like a malware fore antivirus :(
|
2024-05-16 10:51:31 +08:00
|
|
|
*
|
2025-07-22 12:29:41 +08:00
|
|
|
* @throws RuntimeException
|
2024-05-16 10:51:31 +08:00
|
|
|
*/
|
2024-06-03 23:16:15 +08:00
|
|
|
private function processMicroUPX(): void
|
|
|
|
|
{
|
|
|
|
|
if (version_compare($this->getMicroVersion(), '0.2.0') >= 0 && !$this->getOption('no-strip', false)) {
|
2025-07-05 13:52:47 +07:00
|
|
|
shell()->exec('strip --strip-unneeded ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx');
|
2024-06-03 23:16:15 +08:00
|
|
|
|
|
|
|
|
if ($this->getOption('with-upx-pack')) {
|
|
|
|
|
// strip first
|
|
|
|
|
shell()->exec(getenv('UPX_EXEC') . ' --best ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx');
|
|
|
|
|
// cut binary with readelf
|
|
|
|
|
[$ret, $out] = shell()->execWithResult('readelf -l ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx | awk \'/LOAD|GNU_STACK/ {getline; print $1, $2, $3, $4, $6, $7}\'');
|
|
|
|
|
$out[1] = explode(' ', $out[1]);
|
|
|
|
|
$offset = $out[1][0];
|
|
|
|
|
if ($ret !== 0 || !str_starts_with($offset, '0x')) {
|
|
|
|
|
throw new RuntimeException('Cannot find offset in readelf output');
|
|
|
|
|
}
|
|
|
|
|
$offset = hexdec($offset);
|
|
|
|
|
// remove upx extra wastes
|
|
|
|
|
file_put_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', substr(file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx'), 0, $offset));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-21 00:25:46 +08:00
|
|
|
}
|