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 ;
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 ;
2024-04-07 15:52:24 +08:00
// check musl-cross make installed if we use musl-cross-make
$arch = arch2gnu ( php_uname ( 'm' ));
2023-10-23 00:37:28 +08:00
2024-04-07 15:52:24 +08:00
GlobalEnvManager :: init ( $this );
2023-08-20 19:51:45 +08:00
2025-03-14 18:22:50 +08:00
if ( getenv ( 'SPC_LIBC' ) === 'musl' && ! SystemUtil :: isMuslDist ()) {
2025-03-07 11:15:11 +01:00
$this -> setOptionIfNotExist ( 'library_path' , " LIBRARY_PATH= \" /usr/local/musl/ { $arch } -linux-musl/lib \" " );
$this -> setOptionIfNotExist ( 'ld_library_path' , " LD_LIBRARY_PATH= \" /usr/local/musl/ { $arch } -linux-musl/lib \" " );
2025-03-12 08:59:47 +01:00
$configure = getenv ( 'SPC_CMD_PREFIX_PHP_CONFIGURE' );
$configure = " LD_LIBRARY_PATH= \" /usr/local/musl/ { $arch } -linux-musl/lib \" " . $configure ;
GlobalEnvManager :: putenv ( " SPC_CMD_PREFIX_PHP_CONFIGURE= { $configure } " );
2025-03-07 11:15:11 +01:00
2025-03-14 18:22:50 +08:00
if ( ! file_exists ( " /usr/local/musl/ { $arch } -linux-musl/lib/libc.a " )) {
throw new WrongUsageException ( 'You are building with musl-libc target in glibc distro, but musl-toolchain is not installed, please install musl-toolchain first. (You can use `doctor` command to install it)' );
}
2024-04-07 16:26:21 +08:00
}
2023-08-20 19:51:45 +08:00
// concurrency
2024-04-07 15:52:24 +08:00
$this -> concurrency = intval ( 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-10-16 14:09:49 +02:00
// cross-compiling is not supported yet
2023-08-20 19:51:45 +08:00
/* if ( php_uname ( 'm' ) !== $this -> arch ) {
2023-03-21 00:25:46 +08:00
$this -> cross_compile_prefix = SystemUtil :: getCrossCompilePrefix ( $this -> cc , $this -> arch );
logger () -> info ( 'using cross compile prefix: ' . $this -> cross_compile_prefix );
$this -> configure_env .= " CROSS_COMPILE=' { $this -> cross_compile_prefix } ' " ;
2023-08-20 19:51:45 +08:00
} */
2023-03-21 00:25:46 +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
{
2023-08-20 19:51:45 +08:00
// ---------- Update extra-libs ----------
2024-04-07 15:52:24 +08:00
$extra_libs = getenv ( 'SPC_EXTRA_LIBS' ) ? : '' ;
// bloat means force-load all static libraries, even if they are not used
2023-08-20 19:51:45 +08:00
if ( ! $this -> getOption ( 'bloat' , false )) {
$extra_libs .= ( empty ( $extra_libs ) ? '' : ' ' ) . implode ( ' ' , $this -> getAllStaticLibFiles ());
2023-03-21 00:25:46 +08:00
} else {
2023-08-20 19:51:45 +08:00
$extra_libs .= ( empty ( $extra_libs ) ? '' : ' ' ) . implode ( ' ' , array_map ( fn ( $x ) => " -Xcompiler { $x } " , array_filter ( $this -> getAllStaticLibFiles ())));
2023-03-21 00:25:46 +08:00
}
2023-10-16 14:09:49 +02:00
// add libstdc++, some extensions or libraries need it
2023-10-23 00:37:28 +08:00
$extra_libs .= ( empty ( $extra_libs ) ? '' : ' ' ) . ( $this -> hasCpp () ? '-lstdc++ ' : '' );
2024-04-07 15:52:24 +08:00
f_putenv ( 'SPC_EXTRA_LIBS=' . $extra_libs );
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-06-24 09:05:44 +07:00
$cc = trim ( getenv ( 'CC' ));
if ( ! $disable_jit && $this -> getExt ( 'opcache' ) && str_contains ( $cc , 'zig' )) {
2025-06-24 12:10:01 +07:00
f_putenv ( " CC= { $cc } -fno-sanitize=undefined " );
2025-06-24 09:05:44 +07:00
}
2023-03-21 00:25:46 +08: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
2025-03-20 07:27:38 +01:00
$mimallocLibs = $this -> getLib ( 'mimalloc' ) !== null ? BUILD_LIB_PATH . '/mimalloc.o ' : '' ;
2024-04-07 15:52:24 +08:00
// prepare build php envs
$envs_build_php = SystemUtil :: makeEnvVarString ([
'CFLAGS' => getenv ( 'SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS' ),
'CPPFLAGS' => getenv ( 'SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS' ),
'LDFLAGS' => getenv ( 'SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS' ),
2025-03-20 07:27:38 +01:00
'LIBS' => $mimallocLibs . getenv ( 'SPC_CMD_VAR_PHP_CONFIGURE_LIBS' ),
2024-04-07 15:52:24 +08:00
]);
2024-05-16 10:51:31 +08:00
// process micro upx patch if micro sapi enabled
2025-06-18 11:20:05 +07:00
if ( $enableMicro ) {
2024-06-03 23:16:15 +08:00
if ( version_compare ( $this -> getMicroVersion (), '0.2.0' ) < 0 ) {
// for phpmicro 0.1.x
$this -> processMicroUPXLegacy ();
}
// micro latest needs do strip and upx pack later (strip, upx, cut binary manually supported)
2024-02-19 12:17:03 +08:00
}
2025-03-10 16:15:47 +08:00
$embed_type = getenv ( 'SPC_CMD_VAR_PHP_EMBED_TYPE' ) ? : '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-24 09:05:44 +07:00
if ( ! $disable_jit && $this -> getExt ( 'opcache' ) && str_contains ( $cc , 'zig' )) {
2025-06-24 12:10:01 +07:00
f_putenv ( " CC= { $cc } " );
2025-06-24 09:05:44 +07: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
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' )
-> exec ( 'strip --strip-all php' )
2024-04-07 15:52:24 +08:00
-> exec ( getenv ( 'UPX_EXEC' ) . ' --best php' );
2024-02-19 15:29:43 +08:00
} elseif ( ! $this -> getOption ( 'no-strip' , false )) {
shell () -> cd ( SOURCE_PATH . '/php-src/sapi/cli' ) -> exec ( 'strip --strip-all 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
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' )
-> exec ( 'strip --strip-all php-fpm' )
2024-04-07 15:52:24 +08:00
-> exec ( getenv ( 'UPX_EXEC' ) . ' --best php-fpm' );
2024-02-19 15:29:43 +08:00
} elseif ( ! $this -> getOption ( 'no-strip' , false )) {
shell () -> cd ( SOURCE_PATH . '/php-src/sapi/fpm' ) -> exec ( 'strip --strip-all 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' );
if ( preg_match ( '/-release\s+(\S+)/' , $ldflags , $matches )) {
$release = $matches [ 1 ];
$realLibName = 'libphp-' . $release . '.so' ;
$cwd = getcwd ();
2025-06-24 12:10:01 +07:00
$libphpPath = BUILD_LIB_PATH . '/libphp.so' ;
$libphpRelease = BUILD_LIB_PATH . '/' . $realLibName ;
if ( ! file_exists ( $libphpRelease ) && file_exists ( $libphpPath )) {
rename ( $libphpPath , $libphpRelease );
}
if ( file_exists ( $libphpRelease )) {
rename ( BUILD_LIB_PATH . '/libphp.so' , $libphpRelease );
2025-06-23 15:26:39 +07:00
chdir ( BUILD_LIB_PATH );
symlink ( $realLibName , 'libphp.so' );
}
if ( is_dir ( BUILD_MODULES_PATH )) {
chdir ( BUILD_MODULES_PATH );
foreach ( $this -> getExts () as $ext ) {
if ( ! $ext -> isBuildShared ()) {
continue ;
}
$name = $ext -> getName ();
$versioned = " { $name } - { $release } .so " ;
$unversioned = " { $name } .so " ;
if ( is_file ( BUILD_MODULES_PATH . " / { $versioned } " )) {
rename ( BUILD_MODULES_PATH . " / { $versioned } " , BUILD_MODULES_PATH . " / { $unversioned } " );
shell () -> cd ( BUILD_MODULES_PATH )
-> exec ( sprintf (
'patchelf --set-soname %s %s' ,
escapeshellarg ( $unversioned ),
escapeshellarg ( $unversioned )
));
}
2025-06-12 20:19:21 +07:00
}
}
2025-06-05 13:54:17 +07:00
chdir ( $cwd );
}
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
{
return [
2024-04-07 15:52:24 +08:00
'EXTRA_CFLAGS' => getenv ( 'SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS' ),
2024-04-07 16:26:21 +08:00
'EXTRA_LIBS' => getenv ( 'SPC_EXTRA_LIBS' ) . ' ' . getenv ( 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS' ),
2025-06-05 13:54:17 +07:00
'EXTRA_LDFLAGS' => getenv ( 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS' ),
2024-04-07 15:52:24 +08:00
'EXTRA_LDFLAGS_PROGRAM' => getenv ( 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM' ),
2023-10-30 22:14:47 +01:00
];
}
2024-05-16 10:51:31 +08:00
/**
2024-06-03 23:16:15 +08:00
* Apply option -- no - strip and -- with - upx - pack for micro sapi ( only for phpmicro 0.1 . x )
2024-05-16 10:51:31 +08:00
*
* @ throws FileSystemException
*/
2024-06-03 23:16:15 +08:00
private function processMicroUPXLegacy () : void
2024-05-16 10:51:31 +08:00
{
// upx pack and strip for micro
// but always restore Makefile.frag.bak first
if ( file_exists ( SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak' )) {
copy ( SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak' , SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' );
}
if ( $this -> getOption ( 'with-upx-pack' , false )) {
// judge $(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)` count
// if 2, replace src/globals/extra/micro-triple-Makefile.frag file content
if ( substr_count ( FileSystem :: readFile ( SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' ), '$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`' ) === 2 ) {
// bak first
copy ( SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' , SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak' );
// replace Makefile.frag content
FileSystem :: writeFile ( SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' , FileSystem :: readFile ( ROOT_DIR . '/src/globals/extra/micro-triple-Makefile.frag' ));
}
// with upx pack always need strip
FileSystem :: replaceFileRegex (
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' ,
'/POST_MICRO_BUILD_COMMANDS=.*/' ,
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH) && ' . getenv ( 'UPX_EXEC' ) . ' --best \$(SAPI_MICRO_PATH)' ,
);
} elseif ( ! $this -> getOption ( 'no-strip' , false )) {
// not-no-strip means strip (default behavior)
FileSystem :: replaceFileRegex (
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' ,
'/POST_MICRO_BUILD_COMMANDS=.*/' ,
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH)' ,
);
} else {
// just no strip
FileSystem :: replaceFileRegex (
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag' ,
'/POST_MICRO_BUILD_COMMANDS=.*/' ,
'POST_MICRO_BUILD_COMMANDS=true' ,
);
}
}
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 )) {
shell () -> exec ( 'strip --strip-all ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx' );
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
}