2023-03-21 00:25:46 +08:00
< ? php
declare ( strict_types = 1 );
namespace SPC\builder\linux ;
use SPC\builder\linux\library\LinuxLibraryBase ;
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
GlobalEnvManager :: putenv ( " PATH=/usr/local/musl/bin:/usr/local/musl/ { $arch } -linux-musl/bin: " . getenv ( 'PATH' ));
$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-08-20 19:51:45 +08:00
// cmake toolchain
2023-03-21 00:25:46 +08:00
$this -> cmake_toolchain_file = SystemUtil :: makeCmakeToolchainFile (
2023-08-20 19:51:45 +08:00
'Linux' ,
2024-04-07 15:52:24 +08:00
$arch ,
2023-08-20 19:51:45 +08:00
$this -> arch_c_flags ,
2023-10-23 00:37:28 +08:00
getenv ( 'CC' ),
getenv ( 'CXX' ),
2023-03-21 00:25:46 +08:00
);
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 );
}
2023-08-20 19:51:45 +08:00
/**
* @ throws FileSystemException
* @ throws RuntimeException
* @ throws WrongUsageException
*/
2023-03-21 00:25:46 +08:00
public function makeAutoconfArgs ( string $name , array $libSpecs ) : string
{
$ret = '' ;
foreach ( $libSpecs as $libName => $arr ) {
$lib = $this -> getLib ( $libName );
$arr = $arr ? ? [];
$disableArgs = $arr [ 0 ] ? ? null ;
$prefix = $arr [ 1 ] ? ? null ;
if ( $lib instanceof LinuxLibraryBase ) {
logger () -> info ( " { $name } \033 [32;1mwith \033 [0;1m { $libName } support " );
$ret .= $lib -> makeAutoconfEnv ( $prefix ) . ' ' ;
} else {
logger () -> info ( " { $name } \033 [31;1mwithout \033 [0;1m { $libName } support " );
$ret .= ( $disableArgs ? ? " --with- { $libName } =no " ) . ' ' ;
}
}
return rtrim ( $ret );
}
/**
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 ' : '' ;
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
2024-05-16 10:51:31 +08:00
$enable_cli = ( $build_target & BUILD_TARGET_CLI ) === BUILD_TARGET_CLI ;
$enable_fpm = ( $build_target & BUILD_TARGET_FPM ) === BUILD_TARGET_FPM ;
$enable_micro = ( $build_target & BUILD_TARGET_MICRO ) === BUILD_TARGET_MICRO ;
$enable_embed = ( $build_target & BUILD_TARGET_EMBED ) === BUILD_TARGET_EMBED ;
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
if ( $enable_micro ) {
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' ) . ' ' .
2024-05-16 10:51:31 +08:00
( $enable_cli ? '--enable-cli ' : '--disable-cli ' ) .
2025-03-05 11:35:03 +01:00
( $enable_fpm ? '--enable-fpm ' . ( $this -> getLib ( 'libacl' ) !== null ? '--with-fpm-acl ' : '' ) : '--disable-fpm ' ) .
2025-03-10 16:15:47 +08:00
( $enable_embed ? " --enable-embed= { $embed_type } " : '--disable-embed ' ) .
2024-05-16 10:51:31 +08:00
( $enable_micro ? '--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
2024-05-16 10:51:31 +08:00
if ( $enable_cli ) {
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
}
2024-05-16 10:51:31 +08:00
if ( $enable_fpm ) {
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
}
2024-05-16 10:51:31 +08:00
if ( $enable_micro ) {
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
}
2024-05-16 10:51:31 +08:00
if ( $enable_embed ) {
2023-08-21 09:30:46 +02:00
logger () -> info ( 'building embed' );
2024-05-16 10:51:31 +08:00
if ( $enable_micro ) {
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
}
2023-03-21 00:25:46 +08:00
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 ());
2023-03-26 22:27:51 +08:00
shell () -> cd ( SOURCE_PATH . '/php-src' )
-> exec ( 'sed -i "s|//lib|/lib|g" Makefile' )
2024-04-07 15:52:24 +08: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 );
2023-03-26 22:27:51 +08:00
shell () -> cd ( SOURCE_PATH . '/php-src' )
-> exec ( 'sed -i "s|//lib|/lib|g" Makefile' )
2024-04-07 15:52:24 +08: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 ());
2023-04-23 20:31:58 +08:00
shell () -> cd ( SOURCE_PATH . '/php-src' )
-> exec ( 'sed -i "s|//lib|/lib|g" Makefile' )
2024-04-07 15:52:24 +08: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' )
2024-04-07 15:52:24 +08:00
-> exec ( getenv ( 'SPC_CMD_PREFIX_PHP_MAKE' ) . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " { $vars } install " );
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' ),
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
}