mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-06 08:15:39 +08:00
Merge branch 'main' into feat/libcurl-extra
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
@@ -79,6 +80,92 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$this->lib_list = $sorted_libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip unneeded symbols from binary file.
|
||||
*/
|
||||
public function stripBinary(string $binary_path): void
|
||||
{
|
||||
shell()->exec(match (PHP_OS_FAMILY) {
|
||||
'Darwin' => "strip -S {$binary_path}",
|
||||
'Linux' => "strip --strip-unneeded {$binary_path}",
|
||||
default => throw new SPCInternalException('stripBinary is only supported on Linux and macOS'),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract debug information from binary file.
|
||||
*
|
||||
* @param string $binary_path the path to the binary file, including executables, shared libraries, etc
|
||||
*/
|
||||
public function extractDebugInfo(string $binary_path): string
|
||||
{
|
||||
$target_dir = BUILD_ROOT_PATH . '/debug';
|
||||
FileSystem::createDir($target_dir);
|
||||
$basename = basename($binary_path);
|
||||
$debug_file = "{$target_dir}/{$basename}" . (PHP_OS_FAMILY === 'Darwin' ? '.dwarf' : '.debug');
|
||||
if (PHP_OS_FAMILY === 'Darwin') {
|
||||
shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}");
|
||||
} elseif (PHP_OS_FAMILY === 'Linux') {
|
||||
if ($eu_strip = SystemUtil::findCommand('eu-strip')) {
|
||||
shell()
|
||||
->exec("{$eu_strip} -f {$debug_file} {$binary_path}")
|
||||
->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}");
|
||||
} else {
|
||||
shell()
|
||||
->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}")
|
||||
->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}");
|
||||
}
|
||||
} else {
|
||||
throw new SPCInternalException('extractDebugInfo is only supported on Linux and macOS');
|
||||
}
|
||||
return $debug_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy the binary file from src to dst.
|
||||
*/
|
||||
public function deployBinary(string $src, string $dst, bool $executable = true): string
|
||||
{
|
||||
logger()->debug('Deploying binary from ' . $src . ' to ' . $dst);
|
||||
|
||||
// file must exists
|
||||
if (!file_exists($src)) {
|
||||
throw new SPCInternalException("Deploy failed. Cannot find file: {$src}");
|
||||
}
|
||||
// dst dir must exists
|
||||
FileSystem::createDir(dirname($dst));
|
||||
|
||||
// ignore copy to self
|
||||
if (realpath($src) !== realpath($dst)) {
|
||||
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg($dst));
|
||||
}
|
||||
|
||||
// file exist
|
||||
if (!file_exists($dst)) {
|
||||
throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}");
|
||||
}
|
||||
|
||||
// extract debug info
|
||||
$this->extractDebugInfo($dst);
|
||||
|
||||
// strip
|
||||
if (!$this->getOption('no-strip')) {
|
||||
$this->stripBinary($dst);
|
||||
}
|
||||
|
||||
// UPX for linux
|
||||
$upx_option = $this->getOption('with-upx-pack');
|
||||
if ($upx_option && PHP_OS_FAMILY === 'Linux' && $executable) {
|
||||
if ($this->getOption('no-strip')) {
|
||||
logger()->warning('UPX compression is not recommended when --no-strip is enabled.');
|
||||
}
|
||||
logger()->info("Compressing {$dst} with UPX");
|
||||
shell()->exec(getenv('UPX_EXEC') . " --best {$dst}");
|
||||
}
|
||||
|
||||
return $dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity check after build complete.
|
||||
*/
|
||||
@@ -209,23 +296,20 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy the binary file to the build bin path.
|
||||
*
|
||||
* @param int $type Type integer, one of BUILD_TARGET_CLI, BUILD_TARGET_MICRO, BUILD_TARGET_FPM
|
||||
* Deploy binaries that produces executable SAPI
|
||||
*/
|
||||
protected function deployBinary(int $type): bool
|
||||
protected function deploySAPIBinary(int $type): string
|
||||
{
|
||||
$src = match ($type) {
|
||||
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
|
||||
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
||||
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
|
||||
BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi',
|
||||
BUILD_TARGET_FRANKENPHP => BUILD_BIN_PATH . '/frankenphp',
|
||||
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
|
||||
};
|
||||
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||
FileSystem::createDir(BUILD_BIN_PATH);
|
||||
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_BIN_PATH));
|
||||
return true;
|
||||
$dst = BUILD_BIN_PATH . '/' . basename($src);
|
||||
return $this->deployBinary($src, $dst);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,8 +356,10 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
*/
|
||||
protected function processFrankenphpApp(): void
|
||||
{
|
||||
$frankenphpSourceDir = SOURCE_PATH . '/frankenphp';
|
||||
SourceManager::initSource(['frankenphp'], ['frankenphp']);
|
||||
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
|
||||
if (!is_dir($frankenphpSourceDir)) {
|
||||
SourceManager::initSource(['frankenphp'], ['frankenphp']);
|
||||
}
|
||||
$frankenphpAppPath = $this->getOption('with-frankenphp-app');
|
||||
|
||||
if ($frankenphpAppPath) {
|
||||
@@ -297,7 +383,11 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
|
||||
protected function getFrankenPHPVersion(): string
|
||||
{
|
||||
$goModPath = SOURCE_PATH . '/frankenphp/caddy/go.mod';
|
||||
if ($version = getenv('FRANKENPHP_VERSION')) {
|
||||
return $version;
|
||||
}
|
||||
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
|
||||
$goModPath = $frankenphpSourceDir . '/caddy/go.mod';
|
||||
|
||||
if (!file_exists($goModPath)) {
|
||||
throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?");
|
||||
@@ -318,7 +408,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
|
||||
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
|
||||
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
|
||||
$frankenphpSourceDir = SOURCE_PATH . '/frankenphp';
|
||||
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
|
||||
|
||||
$xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp\S*#', '', $xcaddyModules);
|
||||
$xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " .
|
||||
@@ -338,7 +428,6 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$dynamic_exports = ' ' . $dynamicSymbolsArgument;
|
||||
}
|
||||
}
|
||||
$debugFlags = $this->getOption('no-strip') ? '' : '-w -s ';
|
||||
$extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
|
||||
$muslTags = '';
|
||||
$staticFlags = '';
|
||||
@@ -363,7 +452,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
'CGO_CFLAGS' => clean_spaces($cflags),
|
||||
'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}",
|
||||
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
|
||||
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
|
||||
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' .
|
||||
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
|
||||
"v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
|
||||
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
|
||||
@@ -373,13 +462,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
->setEnv($env)
|
||||
->exec("xcaddy build --output frankenphp {$xcaddyModules}");
|
||||
|
||||
if (!$this->getOption('no-strip', false) && file_exists(BUILD_BIN_PATH . '/frankenphp')) {
|
||||
if (PHP_OS_FAMILY === 'Linux') {
|
||||
shell()->cd(BUILD_BIN_PATH)->exec('strip --strip-unneeded frankenphp');
|
||||
} else { // macOS doesn't understand strip-unneeded
|
||||
shell()->cd(BUILD_BIN_PATH)->exec('strip -S frankenphp');
|
||||
}
|
||||
}
|
||||
$this->deploySAPIBinary(BUILD_TARGET_FRANKENPHP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user