mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 14:25:41 +08:00
ttt
This commit is contained in:
57
TODO.md
Normal file
57
TODO.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# v3 TODO List
|
||||
|
||||
Tracking items identified during the v2 → v3 migration audit.
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
- [ ] Implement `craft` command (drives full build from `craft.yml`; should be easier with v3 vendor/registry mode)
|
||||
- [ ] Migrate `micro:combine` command (combine `micro.sfx` with PHP code + INI injection)
|
||||
- [ ] Implement `dump-extensions` command (extract required extensions from `composer.json` / `composer.lock`)
|
||||
- [ ] Design and implement v3 dev toolchain commands (WIP — needs design decision):
|
||||
- [ ] `dev:extensions` / equivalent listing command
|
||||
- [ ] `dev:php-version`, `dev:ext-version`, `dev:lib-version`
|
||||
- [ ] Doc generation commands (`dev:gen-ext-docs`, `dev:gen-ext-dep-docs`, `dev:gen-lib-dep-docs`) — pending v3 doc design
|
||||
|
||||
---
|
||||
|
||||
## Source Patches (SourcePatcher → Artifact migration)
|
||||
|
||||
The following v2 `SourcePatcher` hooks are not yet migrated to v3 `src/Package/Artifact/` classes:
|
||||
|
||||
- [ ] Migrate `patchSQLSRVWin32` — removes `/sdl` compile flag to prevent Zend build failure on Windows
|
||||
- [ ] Migrate `patchSQLSRVPhp85` — fixes `pdo_sqlsrv` directory layout for PHP 8.5
|
||||
- [ ] Migrate `patchYamlWin32` — patches `config.w32` `_a.lib` detection logic for the `yaml` extension
|
||||
- [ ] Migrate `patchImagickWith84` — applies PHP 8.4 compatibility patch for `imagick` based on version detection
|
||||
|
||||
---
|
||||
|
||||
## Extension Package Classes (Unix)
|
||||
|
||||
Extensions that had non-trivial v2 build logic and are missing a v3 `src/Package/Extension/` class:
|
||||
|
||||
- [x] `gettext` — macOS: fix `config.m4` bracket syntax for cross-version compatibility + append frameworks to linker flags (critical for macOS linking; this is a Unix-side gap, not Windows-only)
|
||||
|
||||
---
|
||||
|
||||
## Windows Extensions (Early Stage)
|
||||
|
||||
Windows extension support is still in early stage. The following extensions had Windows-specific configure args or patches in v2 and are pending v3 Windows implementation:
|
||||
|
||||
- [ ] `amqp` — Windows configure args
|
||||
- [ ] `com_dotnet` — Windows-only extension
|
||||
- [ ] `dom` — remove `dllmain.c` from `config.w32`
|
||||
- [ ] `ev` — fix `PHP_EV_SHARED` in `config.w32`
|
||||
- [ ] `gmssl` — add `CHECK_LIB("gmssl.lib")` to `config.w32`
|
||||
- [ ] `intl` — fix `PHP_INTL_SHARED` in `config.w32`
|
||||
- [ ] `lz4` — Windows configure args
|
||||
- [ ] `mbregex` — Windows configure args
|
||||
- [ ] `sqlsrv` / `pdo_sqlsrv` — complex conditional build logic (independent `sqlsrv` without `pdo_sqlsrv`)
|
||||
- [ ] `xml` — remove `dllmain.c` from `config.w32`; handles `soap`, `xmlreader`, `xmlwriter`, `simplexml`
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ ] Write v3 user documentation (currently zero v3 docs)
|
||||
30
src/Package/Extension/gettext.php
Normal file
30
src/Package/Extension/gettext.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Package\Extension;
|
||||
|
||||
use Package\Target\php;
|
||||
use StaticPHP\Attribute\Package\BeforeStage;
|
||||
use StaticPHP\Attribute\Package\Extension;
|
||||
use StaticPHP\Attribute\PatchDescription;
|
||||
use StaticPHP\Package\PackageInstaller;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
use StaticPHP\Util\FileSystem;
|
||||
|
||||
#[Extension('gettext')]
|
||||
class gettext
|
||||
{
|
||||
#[BeforeStage('php', [php::class, 'buildconfForUnix'], 'ext-gettext')]
|
||||
#[PatchDescription('Patch gettext extension config.m4 to fix library detection on macOS')]
|
||||
public function patchBeforeBuildconf(PackageInstaller $installer): void
|
||||
{
|
||||
spc_skip_unless(SystemTarget::getTargetOS() === 'Darwin', 'gettext extension patch is only needed on macOS');
|
||||
$php_src = $installer->getTargetPackage('php')->getSourceDir();
|
||||
FileSystem::replaceFileStr(
|
||||
"{$php_src}/ext/gettext/config.m4",
|
||||
['AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB([$GETTEXT_CHECK_IN_LIB'],
|
||||
['AC_CHECK_LIB(intl', 'AC_CHECK_LIB([intl'] // new php versions use a bracket
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use StaticPHP\Attribute\Package\BuildFor;
|
||||
use StaticPHP\Attribute\Package\Library;
|
||||
use StaticPHP\Package\LibraryPackage;
|
||||
use StaticPHP\Runtime\Executor\UnixAutoconfExecutor;
|
||||
use StaticPHP\Util\FileSystem;
|
||||
|
||||
#[Library('idn2')]
|
||||
class idn2
|
||||
@@ -29,5 +30,10 @@ class idn2
|
||||
->make();
|
||||
$lib->patchPkgconfPrefix(['libidn2.pc']);
|
||||
$lib->patchLaDependencyPrefix();
|
||||
// libunistring is in Libs.private of libidn2.pc, but CMake's pkg_check_modules
|
||||
// does not follow Libs.private for static linking. Promote it to Libs so that
|
||||
// consumers linking static binaries (e.g. the curl exe) can resolve _uc_* / _u32_* symbols.
|
||||
$libidn2_pc = BUILD_ROOT_PATH . '/lib/pkgconfig/libidn2.pc';
|
||||
FileSystem::replaceFileStr($libidn2_pc, 'Libs: -L${libdir} -lidn2', 'Libs: -L${libdir} -lidn2 -lunistring');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use StaticPHP\Package\LibraryPackage;
|
||||
use StaticPHP\Package\PackageInstaller;
|
||||
use StaticPHP\Runtime\Executor\UnixAutoconfExecutor;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
use StaticPHP\Util\FileSystem;
|
||||
use StaticPHP\Util\SPCConfigUtil;
|
||||
|
||||
#[Library('krb5')]
|
||||
@@ -59,5 +60,11 @@ class krb5
|
||||
'mit-krb5.pc',
|
||||
'gssrpc.pc',
|
||||
]);
|
||||
// libkrb5support is in Libs.private of mit-krb5.pc, but CMake's pkg_check_modules
|
||||
// does not follow Libs.private for static linking. Promote it to Libs so that
|
||||
// consumers linking static binaries (e.g. the curl exe) can resolve _k5_* symbols.
|
||||
$mit_krb5_pc = BUILD_ROOT_PATH . '/lib/pkgconfig/mit-krb5.pc';
|
||||
FileSystem::replaceFileStr($mit_krb5_pc, 'Libs.private: -lkrb5support', 'Libs.private:');
|
||||
FileSystem::replaceFileStr($mit_krb5_pc, '-lcom_err', '-lcom_err -lkrb5support');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,16 +81,19 @@ class curl
|
||||
->addConfigureArgs(
|
||||
'-DBUILD_CURL_EXE=ON',
|
||||
'-DBUILD_LIBCURL_DOCS=OFF',
|
||||
'-DCURL_USE_PKGCONFIG=ON',
|
||||
)
|
||||
->build();
|
||||
|
||||
// patch pkgconf
|
||||
$lib->patchPkgconfPrefix(['libcurl.pc']);
|
||||
// curl's CMake embeds krb5 link flags directly without following Requires.private chain,
|
||||
// so -lkrb5support (from mit-krb5.pc Libs.private) is missing from libcurl.pc.
|
||||
// Ensure -lkrb5support is present in libcurl.pc for downstream consumers.
|
||||
// krb5.php already promotes it to Libs in mit-krb5.pc before the build, so
|
||||
// CMake should have embedded it; this is a safety fallback if it was missed.
|
||||
$pc_path = "{$lib->getLibDir()}/pkgconfig/libcurl.pc";
|
||||
if (str_contains(FileSystem::readFile($pc_path), '-lgssapi_krb5')) {
|
||||
FileSystem::replaceFileRegex($pc_path, '/-lcom_err$/m', '-lcom_err -lkrb5support');
|
||||
$pc_content = FileSystem::readFile($pc_path);
|
||||
if (str_contains($pc_content, '-lgssapi_krb5') && !str_contains($pc_content, '-lkrb5support')) {
|
||||
FileSystem::replaceFileRegex($pc_path, '/-lcom_err\b/', '-lcom_err -lkrb5support');
|
||||
}
|
||||
shell()->cd("{$lib->getLibDir()}/cmake/CURL/")
|
||||
->exec("sed -ie 's|\"/lib/libcurl.a\"|\"{$lib->getLibDir()}/libcurl.a\"|g' CURLTargets-release.cmake");
|
||||
|
||||
@@ -10,10 +10,13 @@ use StaticPHP\Exception\SPCInternalException;
|
||||
use StaticPHP\Package\LibraryPackage;
|
||||
use StaticPHP\Package\PackageBuilder;
|
||||
use StaticPHP\Package\PackageInstaller;
|
||||
use StaticPHP\Package\TargetPackage;
|
||||
use StaticPHP\Runtime\Shell\UnixShell;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
use StaticPHP\Util\FileSystem;
|
||||
use StaticPHP\Util\InteractiveTerm;
|
||||
use StaticPHP\Util\PkgConfigUtil;
|
||||
use StaticPHP\Util\SPCConfigUtil;
|
||||
use ZM\Logger\ConsoleColor;
|
||||
|
||||
/**
|
||||
@@ -214,7 +217,7 @@ class UnixCMakeExecutor extends Executor
|
||||
*/
|
||||
private function getDefaultCMakeArgs(): array
|
||||
{
|
||||
return $this->custom_default_args ?? [
|
||||
$args = $this->custom_default_args ?? [
|
||||
'-DCMAKE_BUILD_TYPE=Release',
|
||||
"-DCMAKE_INSTALL_PREFIX={$this->package->getBuildRootPath()}",
|
||||
'-DCMAKE_INSTALL_BINDIR=bin',
|
||||
@@ -224,6 +227,20 @@ class UnixCMakeExecutor extends Executor
|
||||
'-DBUILD_SHARED_LIBS=OFF',
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}",
|
||||
];
|
||||
|
||||
// EXE linker flags: base system libs + framework flags for target packages
|
||||
$exeLinkerFlags = SystemTarget::getRuntimeLibs();
|
||||
if ($this->package instanceof TargetPackage) {
|
||||
$resolvedNames = array_keys($this->installer->getResolvedPackages());
|
||||
$resolvedNames[] = $this->package->getName();
|
||||
$fwFlags = SPCConfigUtil::getFrameworksString($resolvedNames);
|
||||
if ($fwFlags !== '') {
|
||||
$exeLinkerFlags .= " {$fwFlags}";
|
||||
}
|
||||
}
|
||||
$args[] = "-DCMAKE_EXE_LINKER_FLAGS=\"{$exeLinkerFlags}\"";
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,13 +291,13 @@ SET(CMAKE_PREFIX_PATH "{$root}")
|
||||
SET(CMAKE_INSTALL_PREFIX "{$root}")
|
||||
SET(CMAKE_INSTALL_LIBDIR "lib")
|
||||
|
||||
set(PKG_CONFIG_EXECUTABLE "{$pkgConfigExecutable}")
|
||||
set(PKG_CONFIG_EXECUTABLE "{$pkgConfigExecutable}" CACHE FILEPATH "pkg-config executable" FORCE)
|
||||
set(PKG_CONFIG_ARGN "--static" CACHE STRING "Extra arguments for pkg-config" FORCE)
|
||||
set(ENV{PKG_CONFIG_PATH} "{$root}/lib/pkgconfig")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-ldl -lpthread -lm -lutil")
|
||||
CMAKE;
|
||||
// Whoops, linux may need CMAKE_AR sometimes
|
||||
if (PHP_OS_FAMILY === 'Linux') {
|
||||
|
||||
@@ -57,8 +57,9 @@ class SPCConfigUtil
|
||||
$libs .= " {$extra_env}";
|
||||
}
|
||||
// package frameworks
|
||||
if (SystemTarget::getTargetOS() === 'Darwin') {
|
||||
$libs .= " {$this->getFrameworksString($resolved)}";
|
||||
$fwStr = self::getFrameworksString($resolved);
|
||||
if ($fwStr !== '') {
|
||||
$libs .= " {$fwStr}";
|
||||
}
|
||||
// C++
|
||||
if ($this->hasCpp($resolved)) {
|
||||
@@ -236,8 +237,9 @@ class SPCConfigUtil
|
||||
}
|
||||
|
||||
// package frameworks
|
||||
if (SystemTarget::getTargetOS() === 'Darwin') {
|
||||
$libs .= " {$this->getFrameworksString($resolved_packages)}";
|
||||
$fwStr = self::getFrameworksString($resolved_packages);
|
||||
if ($fwStr !== '') {
|
||||
$libs .= " {$fwStr}";
|
||||
}
|
||||
|
||||
// C++
|
||||
@@ -285,6 +287,31 @@ class SPCConfigUtil
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the frameworks string for a list of packages.
|
||||
*
|
||||
* Returns empty string on non-Darwin platforms.
|
||||
*
|
||||
* @param string[] $packages Package names to collect frameworks from
|
||||
* @return string e.g. "-framework Kerberos -framework CoreFoundation"
|
||||
*/
|
||||
public static function getFrameworksString(array $packages): string
|
||||
{
|
||||
if (SystemTarget::getTargetOS() !== 'Darwin') {
|
||||
return '';
|
||||
}
|
||||
$list = [];
|
||||
foreach ($packages as $package) {
|
||||
foreach (PackageConfig::get($package, 'frameworks', []) as $fw) {
|
||||
$ks = '-framework ' . $fw;
|
||||
if (!in_array($ks, $list)) {
|
||||
$list[] = $ks;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(' ', $list);
|
||||
}
|
||||
|
||||
private function hasCpp(array $packages): bool
|
||||
{
|
||||
foreach ($packages as $package) {
|
||||
@@ -492,18 +519,4 @@ class SPCConfigUtil
|
||||
}
|
||||
return $lib;
|
||||
}
|
||||
|
||||
private function getFrameworksString(array $extensions): string
|
||||
{
|
||||
$list = [];
|
||||
foreach ($extensions as $extension) {
|
||||
foreach (PackageConfig::get($extension, 'frameworks', []) as $fw) {
|
||||
$ks = '-framework ' . $fw;
|
||||
if (!in_array($ks, $list)) {
|
||||
$list[] = $ks;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(' ', $list);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user