mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-04 15:25:41 +08:00
Add go-xcaddy,musl-toolchain,php,upx, and also glfw linux support
This commit is contained in:
75
src/Package/Artifact/php_src.php
Normal file
75
src/Package/Artifact/php_src.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Package\Artifact;
|
||||
|
||||
use StaticPHP\Attribute\Artifact\AfterSourceExtract;
|
||||
use StaticPHP\Attribute\PatchDescription;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
use StaticPHP\Util\FileSystem;
|
||||
use StaticPHP\Util\SourcePatcher;
|
||||
|
||||
class php_src
|
||||
{
|
||||
#[AfterSourceExtract('php-src')]
|
||||
#[PatchDescription('Patch PHP source for libxml2 2.12 compatibility on Alpine Linux')]
|
||||
public function patchPhpLibxml212(): void
|
||||
{
|
||||
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
||||
if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0) {
|
||||
$ver_id = intval($match[1]);
|
||||
if ($ver_id < 80000) {
|
||||
SourcePatcher::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src');
|
||||
return;
|
||||
}
|
||||
if ($ver_id < 80100) {
|
||||
SourcePatcher::patchFile('spc_fix_libxml2_12_php80.patch', SOURCE_PATH . '/php-src');
|
||||
SourcePatcher::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src');
|
||||
return;
|
||||
}
|
||||
if ($ver_id < 80200) {
|
||||
// self::patchFile('spc_fix_libxml2_12_php81.patch', SOURCE_PATH . '/php-src');
|
||||
SourcePatcher::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[AfterSourceExtract('php-src')]
|
||||
#[PatchDescription('Patch GD extension for Windows builds')]
|
||||
public function patchGDWin32(): void
|
||||
{
|
||||
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
||||
if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0) {
|
||||
$ver_id = intval($match[1]);
|
||||
if ($ver_id < 80200) {
|
||||
// see: https://github.com/php/php-src/commit/243966177e39eb71822935042c3f13fa6c5b9eed
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gd/libgd/gdft.c', '#ifndef MSWIN32', '#ifndef _WIN32');
|
||||
}
|
||||
// custom config.w32, because official config.w32 is hard-coded many things
|
||||
$origin = $ver_id >= 80100 ? file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_81.w32') : file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_80.w32');
|
||||
file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32.bak', file_get_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32'));
|
||||
file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32', $origin);
|
||||
}
|
||||
}
|
||||
|
||||
#[AfterSourceExtract('php-src')]
|
||||
#[PatchDescription('Patch FFI extension on CentOS 7 with -O3 optimization (strncmp issue)')]
|
||||
public function patchFfiCentos7FixO3strncmp(): void
|
||||
{
|
||||
spc_skip_if(!($ver = SystemTarget::getLibcVersion()) || version_compare($ver, '2.17', '>'));
|
||||
spc_skip_if(!file_exists(SOURCE_PATH . '/php-src/main/php_version.h'));
|
||||
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
||||
spc_skip_if(preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0 && intval($match[1]) < 80316);
|
||||
SourcePatcher::patchFile('ffi_centos7_fix_O3_strncmp.patch', SOURCE_PATH . '/php-src');
|
||||
}
|
||||
|
||||
#[AfterSourceExtract('php-src')]
|
||||
#[PatchDescription('Add LICENSE file to IMAP extension if missing')]
|
||||
public function patchImapLicense(): void
|
||||
{
|
||||
if (!file_exists(SOURCE_PATH . '/php-src/ext/imap/LICENSE') && is_dir(SOURCE_PATH . '/php-src/ext/imap')) {
|
||||
file_put_contents(SOURCE_PATH . '/php-src/ext/imap/LICENSE', file_get_contents(ROOT_DIR . '/src/globals/extra/Apache_LICENSE'));
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/Package/Extension/glfw.php
Normal file
59
src/Package/Extension/glfw.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Package\Extension;
|
||||
|
||||
use Package\Target\php;
|
||||
use StaticPHP\Attribute\Package\BeforeStage;
|
||||
use StaticPHP\Attribute\Package\CustomPhpConfigureArg;
|
||||
use StaticPHP\Attribute\Package\Extension;
|
||||
use StaticPHP\Attribute\PatchDescription;
|
||||
use StaticPHP\Package\PhpExtensionPackage;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
use StaticPHP\Util\FileSystem;
|
||||
|
||||
#[Extension('glfw')]
|
||||
class glfw extends PhpExtensionPackage
|
||||
{
|
||||
#[BeforeStage('php', [php::class, 'buildconfForUnix'], 'ext-glfw')]
|
||||
#[PatchDescription('Patch glfw extension before buildconf')]
|
||||
public function patchBeforeBuildconf(): void
|
||||
{
|
||||
if (!file_exists(SOURCE_PATH . '/php-src/ext/glfw')) {
|
||||
FileSystem::copyDir($this->getSourceDir(), SOURCE_PATH . '/php-src/ext/glfw');
|
||||
}
|
||||
}
|
||||
|
||||
#[BeforeStage('php', [php::class, 'configureForUnix'], 'ext-glfw')]
|
||||
#[PatchDescription('Patch glfw extension before configure')]
|
||||
public function patchBeforeConfigure(): void
|
||||
{
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/configure',
|
||||
'-lglfw ',
|
||||
'-lglfw3 '
|
||||
);
|
||||
|
||||
// add X11 shared libs for linux
|
||||
if (SystemTarget::getTargetOS() === 'Linux') {
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
$extra_libs .= ' -lX11 -lXrandr -lXinerama -lXcursor -lXi';
|
||||
putenv('SPC_EXTRA_LIBS=' . trim($extra_libs));
|
||||
$extra_cflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') ?: '';
|
||||
|
||||
$extra_cflags .= ' -idirafter /usr/include';
|
||||
putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . trim($extra_cflags));
|
||||
$extra_ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: '';
|
||||
$extra_ldflags .= ' -L/usr/lib/' . SystemTarget::getTargetArch() . '-linux-gnu ';
|
||||
putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=' . $extra_ldflags);
|
||||
}
|
||||
}
|
||||
|
||||
#[CustomPhpConfigureArg('Darwin')]
|
||||
#[CustomPhpConfigureArg('Linux')]
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return '--enable-glfw --with-glfw-dir=' . BUILD_ROOT_PATH;
|
||||
}
|
||||
}
|
||||
100
src/Package/Library/glfw.php
Normal file
100
src/Package/Library/glfw.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Package\Library;
|
||||
|
||||
use StaticPHP\Attribute\Package\BuildFor;
|
||||
use StaticPHP\Attribute\Package\Library;
|
||||
use StaticPHP\Attribute\Package\Validate;
|
||||
use StaticPHP\Exception\BuildFailureException;
|
||||
use StaticPHP\Exception\ValidationException;
|
||||
use StaticPHP\Package\LibraryPackage;
|
||||
use StaticPHP\Runtime\Executor\UnixCMakeExecutor;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
use StaticPHP\Toolchain\Interface\ToolchainInterface;
|
||||
|
||||
#[Library('glfw')]
|
||||
class glfw
|
||||
{
|
||||
#[Validate]
|
||||
public function validate(ToolchainInterface $toolchain): void
|
||||
{
|
||||
if (SystemTarget::getTargetOS() === 'Linux') {
|
||||
if ($toolchain->isStatic()) {
|
||||
throw new ValidationException('glfw library does not support full-static linking on Linux, please build with dynamic target specified.');
|
||||
}
|
||||
// detect X11 dev packages
|
||||
$required_headers = [
|
||||
'/usr/include/X11',
|
||||
'/usr/include/X11/extensions/Xrandr.h',
|
||||
'/usr/include/X11/extensions/Xinerama.h',
|
||||
'/usr/include/X11/Xcursor/Xcursor.h',
|
||||
];
|
||||
foreach ($required_headers as $header) {
|
||||
if (!file_exists($header)) {
|
||||
throw new ValidationException("glfw requires X11 development headers. Missing: {$header}. Please confirm that your system has the necessary X11 packages installed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[BuildFor('Linux')]
|
||||
public function buildForLinux(LibraryPackage $lib): void
|
||||
{
|
||||
$x11_lib_find = [
|
||||
'/usr/lib/' . SystemTarget::getTargetArch() . '-linux-gnu/libX11.so',
|
||||
'/usr/lib64/libX11.so',
|
||||
'/usr/lib/libX11.so',
|
||||
];
|
||||
$found = false;
|
||||
foreach ($x11_lib_find as $path) {
|
||||
if (file_exists($path)) {
|
||||
$found = $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
throw new BuildFailureException('Cannot find X11 library files in standard locations. Please ensure that the X11 development libraries are installed.');
|
||||
}
|
||||
$base_path = pathinfo($found, PATHINFO_DIRNAME);
|
||||
UnixCMakeExecutor::create($lib)
|
||||
->setBuildDir("{$lib->getSourceDir()}/vendor/glfw")
|
||||
->setReset(false)
|
||||
->addConfigureArgs(
|
||||
'-DGLFW_BUILD_EXAMPLES=OFF',
|
||||
'-DGLFW_BUILD_TESTS=OFF',
|
||||
'-DGLFW_BUILD_DOCS=OFF',
|
||||
'-DX11_X11_INCLUDE_PATH=/usr/include',
|
||||
'-DX11_Xrandr_INCLUDE_PATH=/usr/include/X11/extensions',
|
||||
'-DX11_Xinerama_INCLUDE_PATH=/usr/include/X11/extensions',
|
||||
'-DX11_Xkb_INCLUDE_PATH=/usr/include/X11',
|
||||
'-DX11_Xcursor_INCLUDE_PATH=/usr/include/X11/Xcursor',
|
||||
'-DX11_Xi_INCLUDE_PATH=/usr/include/X11/extensions',
|
||||
"-DX11_X11_LIB={$base_path}/libX11.so",
|
||||
"-DX11_Xrandr_LIB={$base_path}/libXrandr.so",
|
||||
"-DX11_Xinerama_LIB={$base_path}/libXinerama.so",
|
||||
"-DX11_Xcursor_LIB={$base_path}/libXcursor.so",
|
||||
"-DX11_Xi_LIB={$base_path}/libXi.so"
|
||||
)
|
||||
->build('.');
|
||||
// patch pkgconf
|
||||
$lib->patchPkgconfPrefix(['glfw3.pc']);
|
||||
}
|
||||
|
||||
#[BuildFor('Darwin')]
|
||||
public function buildForMac(LibraryPackage $lib): void
|
||||
{
|
||||
UnixCMakeExecutor::create($lib)
|
||||
->setBuildDir("{$lib->getSourceDir()}/vendor/glfw")
|
||||
->setReset(false)
|
||||
->addConfigureArgs(
|
||||
'-DGLFW_BUILD_EXAMPLES=OFF',
|
||||
'-DGLFW_BUILD_TESTS=OFF',
|
||||
'-DGLFW_BUILD_DOCS=OFF',
|
||||
)
|
||||
->build('.');
|
||||
// patch pkgconf
|
||||
$lib->patchPkgconfPrefix(['glfw3.pc']);
|
||||
}
|
||||
}
|
||||
@@ -134,9 +134,11 @@ trait unix
|
||||
{
|
||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('make cli'));
|
||||
$concurrency = $builder->concurrency;
|
||||
$vars = $this->makeVars($installer);
|
||||
$makeArgs = $this->makeVarsToArgs($vars);
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($this->makeVars($installer))
|
||||
->exec("make -j{$concurrency} cli");
|
||||
->setEnv($vars)
|
||||
->exec("make -j{$concurrency} {$makeArgs} cli");
|
||||
|
||||
$builder->deployBinary("{$package->getSourceDir()}/sapi/cli/php", BUILD_BIN_PATH . '/php');
|
||||
$package->setOutput('Binary path for cli SAPI', BUILD_BIN_PATH . '/php');
|
||||
@@ -147,9 +149,11 @@ trait unix
|
||||
{
|
||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('make cgi'));
|
||||
$concurrency = $builder->concurrency;
|
||||
$vars = $this->makeVars($installer);
|
||||
$makeArgs = $this->makeVarsToArgs($vars);
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($this->makeVars($installer))
|
||||
->exec("make -j{$concurrency} cgi");
|
||||
->setEnv($vars)
|
||||
->exec("make -j{$concurrency} {$makeArgs} cgi");
|
||||
|
||||
$builder->deployBinary("{$package->getSourceDir()}/sapi/cgi/php-cgi", BUILD_BIN_PATH . '/php-cgi');
|
||||
$package->setOutput('Binary path for cgi SAPI', BUILD_BIN_PATH . '/php-cgi');
|
||||
@@ -160,9 +164,11 @@ trait unix
|
||||
{
|
||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('make fpm'));
|
||||
$concurrency = $builder->concurrency;
|
||||
$vars = $this->makeVars($installer);
|
||||
$makeArgs = $this->makeVarsToArgs($vars);
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($this->makeVars($installer))
|
||||
->exec("make -j{$concurrency} fpm");
|
||||
->setEnv($vars)
|
||||
->exec("make -j{$concurrency} {$makeArgs} fpm");
|
||||
|
||||
$builder->deployBinary("{$package->getSourceDir()}/sapi/fpm/php-fpm", BUILD_BIN_PATH . '/php-fpm');
|
||||
$package->setOutput('Binary path for fpm SAPI', BUILD_BIN_PATH . '/php-fpm');
|
||||
@@ -182,10 +188,11 @@ trait unix
|
||||
// apply --with-micro-fake-cli option
|
||||
$vars = $this->makeVars($installer);
|
||||
$vars['EXTRA_CFLAGS'] .= $package->getBuildOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$makeArgs = $this->makeVarsToArgs($vars);
|
||||
// build
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($vars)
|
||||
->exec("make -j{$builder->concurrency} micro");
|
||||
->exec("make -j{$builder->concurrency} {$makeArgs} micro");
|
||||
|
||||
$builder->deployBinary($package->getSourceDir() . '/sapi/micro/micro.sfx', BUILD_BIN_PATH . '/micro.sfx');
|
||||
$package->setOutput('Binary path for micro SAPI', BUILD_BIN_PATH . '/micro.sfx');
|
||||
@@ -440,11 +447,30 @@ trait unix
|
||||
$static = ApplicationContext::get(ToolchainInterface::class)->isStatic() ? '-all-static' : '';
|
||||
$pie = SystemTarget::getTargetOS() === 'Linux' ? '-pie' : '';
|
||||
|
||||
// Append SPC_EXTRA_LIBS to libs for dynamic linking support (e.g., X11)
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
$libs = trim($config['libs'] . ' ' . $extra_libs);
|
||||
|
||||
return array_filter([
|
||||
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
|
||||
'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') . "{$config['ldflags']} {$static} {$pie}",
|
||||
'EXTRA_LDFLAGS' => $config['ldflags'],
|
||||
'EXTRA_LIBS' => $config['libs'],
|
||||
'EXTRA_LIBS' => $libs,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert make variables array to command line argument string.
|
||||
* This is needed because make command line arguments have higher priority than environment variables.
|
||||
*/
|
||||
private function makeVarsToArgs(array $vars): string
|
||||
{
|
||||
$args = [];
|
||||
foreach ($vars as $key => $value) {
|
||||
if (trim($value) !== '') {
|
||||
$args[] = $key . '=' . escapeshellarg($value);
|
||||
}
|
||||
}
|
||||
return implode(' ', $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,7 @@ class ZigCheck
|
||||
#[CheckItem('if zig is installed', level: 800)]
|
||||
public function checkZig(): CheckResult
|
||||
{
|
||||
$installer = new PackageInstaller();
|
||||
$package = 'zig';
|
||||
$installer->addInstallPackage($package);
|
||||
$installed = $installer->isPackageInstalled($package);
|
||||
if ($installed) {
|
||||
if (new PackageInstaller()->addInstallPackage('zig')->isPackageInstalled('zig')) {
|
||||
return CheckResult::ok();
|
||||
}
|
||||
return CheckResult::fail('zig is not installed', 'install-zig');
|
||||
|
||||
Reference in New Issue
Block a user