diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c157b5e9..1088c104 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -120,8 +120,8 @@ jobs: php: - "8.0" - "8.1" - - "8.2.22" - - "8.3.10" + - "8.2" + - "8.3" os: - ubuntu-latest - macos-13 diff --git a/docs/en/guide/env-vars.md b/docs/en/guide/env-vars.md index a6c66e43..f60b1d2d 100644 --- a/docs/en/guide/env-vars.md +++ b/docs/en/guide/env-vars.md @@ -48,7 +48,7 @@ These environment variables are system-specific and will only take effect on a s |---------------------|-----------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------| | `PHP_SDK_PATH` | `{pwd}\php-sdk-binary-tools` | PHP SDK tools path | | `UPX_EXEC` | `$PKG_ROOT_PATH\bin\upx.exe` | UPX compression tool path | -| `SPC_MICRO_PATCHES` | `static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | +| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | ### macOS @@ -66,7 +66,7 @@ These environment variables are system-specific and will only take effect on a s | `SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS` | `-L$BUILD_LIB_PATH` | `LDFLAGS` variable of PHP `configure` command | | `SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS` | `-g0 -Os` or `-g -O0` (the latter when using `--no-strip`) | `EXTRA_CFLAGS` variable of PHP `make` command | | `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | `-lresolv` | Extra `EXTRA_LIBS` variables for PHP `make` command | -| `SPC_MICRO_PATCHES` | `static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | +| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | ### Linux @@ -92,7 +92,7 @@ These environment variables are system-specific and will only take effect on a s | `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | empty | Extra `EXTRA_LIBS` variables for PHP `make` command | | `SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM` | `-all-static` (when using `clang`: `-Xcompiler -fuse-ld=lld -all-static`) | Additional `LDFLAGS` variable for `make` command | | `SPC_NO_MUSL_PATH` | empty | Whether to not insert the PATH of the musl toolchain (not inserted when the value is `yes`) | -| `SPC_MICRO_PATCHES` | `static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | +| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | > `{ld_lib_path}` value is `/usr/local/musl/$GNU_ARCH-linux-musl/lib`。 ### FreeBSD diff --git a/docs/zh/guide/env-vars.md b/docs/zh/guide/env-vars.md index 9fe95e2b..6c467542 100644 --- a/docs/zh/guide/env-vars.md +++ b/docs/zh/guide/env-vars.md @@ -46,7 +46,7 @@ SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli |---------------------|-----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| | `PHP_SDK_PATH` | `{pwd}\php-sdk-binary-tools` | PHP SDK 工具的安装目录 | | `UPX_EXEC` | `$PKG_ROOT_PATH\bin\upx.exe` | UPX 压缩工具的路径 | -| `SPC_MICRO_PATCHES` | `static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | +| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | ### macOS @@ -64,7 +64,7 @@ SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli | `SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS` | `-L$BUILD_LIB_PATH` | PHP `configure` 命令的 `LDFLAGS` 变量 | | `SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS` | `-g0 -Os` 或 `-g -O0`(当使用 `--no-strip` 时为后者) | PHP `make` 命令的 `EXTRA_CFLAGS` 变量 | | `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | `-lresolv` | PHP `make` 命令的额外 `EXTRA_LIBS` 变量 | -| `SPC_MICRO_PATCHES` | `static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | +| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | ### Linux @@ -90,7 +90,7 @@ SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli | `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | empty | PHP `make` 命令的额外 `EXTRA_LIBS` 变量 | | `SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM` | `-all-static`(当使用 `clang` 时:`-Xcompiler -fuse-ld=lld -all-static`) | `make` 命令的额外 `LDFLAGS` 变量(用于编译程序) | | `SPC_NO_MUSL_PATH` | empty | 是否不插入 musl 工具链的 PATH(值为 `yes` 时不插入) | -| `SPC_MICRO_PATCHES` | `static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | +| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) | > `{ld_lib_path}` 值为 `/usr/local/musl/$GNU_ARCH-linux-musl/lib`。 diff --git a/src/SPC/builder/extension/opcache.php b/src/SPC/builder/extension/opcache.php index a0af4a8f..5276261a 100644 --- a/src/SPC/builder/extension/opcache.php +++ b/src/SPC/builder/extension/opcache.php @@ -7,6 +7,7 @@ namespace SPC\builder\extension; use SPC\builder\Extension; use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; +use SPC\store\SourcePatcher; use SPC\util\CustomExt; #[CustomExt('opcache')] @@ -23,6 +24,24 @@ class opcache extends Extension } } + public function patchBeforeBuildconf(): bool + { + if (file_exists(SOURCE_PATH . '/php-src/.opcache_patched')) { + return false; + } + // if 8.2.0 <= PHP_VERSION < 8.2.23, we need to patch from legacy patch file + if (version_compare($this->builder->getPHPVersion(), '8.2.0', '>=') && version_compare($this->builder->getPHPVersion(), '8.2.23', '<')) { + SourcePatcher::patchFile('spc_fix_static_opcache_before_80222.patch', SOURCE_PATH . '/php-src'); + } + // if 8.3.0 <= PHP_VERSION < 8.3.11, we need to patch from legacy patch file + elseif (version_compare($this->builder->getPHPVersion(), '8.3.0', '>=') && version_compare($this->builder->getPHPVersion(), '8.3.11', '<')) { + SourcePatcher::patchFile('spc_fix_static_opcache_before_80310.patch', SOURCE_PATH . '/php-src'); + } else { + SourcePatcher::patchMicro(items: ['static_opcache']); + } + return file_put_contents(SOURCE_PATH . '/php-src/.opcache_patched', '1') !== false; + } + public function getUnixConfigureArg(): string { return '--enable-opcache'; diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index e21e42ea..86014e7c 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -88,7 +88,7 @@ class SourcePatcher * @throws RuntimeException * @throws FileSystemException */ - public static function patchMicro(): bool + public static function patchMicro(string $name = '', string $target = '', ?array $items = null): bool { if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) { return false; @@ -108,8 +108,12 @@ class SourcePatcher // $check = !defined('DEBUG_MODE') ? ' -q' : ''; // f_passthru('cd ' . SOURCE_PATH . '/php-src && git checkout' . $check . ' HEAD'); - $spc_micro_patches = getenv('SPC_MICRO_PATCHES'); - $spc_micro_patches = $spc_micro_patches === false ? [] : explode(',', $spc_micro_patches); + if ($items !== null) { + $spc_micro_patches = $items; + } else { + $spc_micro_patches = getenv('SPC_MICRO_PATCHES'); + $spc_micro_patches = $spc_micro_patches === false ? [] : explode(',', $spc_micro_patches); + } $patch_list = $spc_micro_patches; $patches = []; $serial = ['80', '81', '82', '83', '84']; diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index 598631ad..083262d4 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -64,7 +64,7 @@ class GlobalEnvManager // Windows need php-sdk binary tools self::initIfNotExists('PHP_SDK_PATH', WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools'); self::initIfNotExists('UPX_EXEC', PKG_ROOT_PATH . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'upx.exe'); - self::initIfNotExists('SPC_MICRO_PATCHES', 'static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static'); + self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static'); } private static function initLinuxEnv(BuilderBase $builder): void @@ -92,7 +92,7 @@ class GlobalEnvManager self::initIfNotExists('SPC_EXTRA_LIBS', ''); // SPC_MICRO_PATCHES for linux - self::initIfNotExists('SPC_MICRO_PATCHES', 'static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream'); + self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream'); // Init linux-only env self::initIfNotExists('UPX_EXEC', PKG_ROOT_PATH . '/bin/upx'); @@ -145,7 +145,7 @@ class GlobalEnvManager self::initIfNotExists('SPC_EXTRA_LIBS', ''); // SPC_MICRO_PATCHES for macOS - self::initIfNotExists('SPC_MICRO_PATCHES', 'static_opcache,static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv'); + self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv'); $init_spc_cmd_maps = [ // Init default build command prefix diff --git a/src/globals/patch/spc_fix_static_opcache_before_80222.patch b/src/globals/patch/spc_fix_static_opcache_before_80222.patch new file mode 100644 index 00000000..6cac993a --- /dev/null +++ b/src/globals/patch/spc_fix_static_opcache_before_80222.patch @@ -0,0 +1,129 @@ +diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk +index 1e71ea2069..3da32d8830 100644 +--- a/build/order_by_dep.awk ++++ b/build/order_by_dep.awk +@@ -37,6 +37,11 @@ function get_module_index(name, i) + function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) + { + module_name = mods[mod_idx]; ++ # TODO: real skip zend extension ++ if (module_name == "opcache") { ++ delete mods[mod_idx]; ++ return; ++ } + mod_name_len = length(module_name); + + for (ext in mod_deps) { +diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c +index 5f6b854d47..ea15c0d5bc 100644 +--- a/ext/opcache/ZendAccelerator.c ++++ b/ext/opcache/ZendAccelerator.c +@@ -91,7 +91,10 @@ typedef int gid_t; + #include + #endif + ++#ifdef COMPILE_DL_OPCACHE ++// avoid symbol conflict + ZEND_EXTENSION(); ++#endif + + #ifndef ZTS + zend_accel_globals accel_globals; +@@ -4808,7 +4811,11 @@ static int accel_finish_startup(void) + return SUCCESS; + } + ++#ifdef COMPILE_DL_OPCACHE + ZEND_EXT_API zend_extension zend_extension_entry = { ++#else ++zend_extension opcache_zend_extension_entry = { ++#endif + ACCELERATOR_PRODUCT_NAME, /* name */ + PHP_VERSION, /* version */ + "Zend Technologies", /* author */ +diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 +index 2a83fa2455..7b3b37182e 100644 +--- a/ext/opcache/config.m4 ++++ b/ext/opcache/config.m4 +@@ -21,7 +21,8 @@ PHP_ARG_ENABLE([opcache-jit], + if test "$PHP_OPCACHE" != "no"; then + + dnl Always build as shared extension +- ext_shared=yes ++ dnl why? ++ dnl ext_shared=yes + + if test "$PHP_HUGE_CODE_PAGES" = "yes"; then + AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) +@@ -327,7 +328,9 @@ int main() { + shared_alloc_mmap.c \ + shared_alloc_posix.c \ + $ZEND_JIT_SRC, +- shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) ++ $ext_shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) ++ ++ AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) + + PHP_ADD_EXTENSION_DEP(opcache, pcre) + +diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 +index 764a2edaab..95427090ce 100644 +--- a/ext/opcache/config.w32 ++++ b/ext/opcache/config.w32 +@@ -16,7 +16,9 @@ if (PHP_OPCACHE != "no") { + zend_persist_calc.c \ + zend_file_cache.c \ + zend_shared_alloc.c \ +- shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ++ shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ++ ++ AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); + + if (PHP_OPCACHE_JIT == "yes") { + if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { +diff --git a/main/main.c b/main/main.c +index 8c16f01b11..0560348a06 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -2011,6 +2011,18 @@ void dummy_invalid_parameter_handler( + } + #endif + ++// this can be moved to other place ++#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) ++extern zend_extension opcache_zend_extension_entry; ++extern void zend_register_extension(zend_extension *new_extension, void *handle); ++ ++int zend_load_static_extensions(void) ++{ ++ zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); ++ return 0; ++} ++#endif ++ + /* {{{ php_module_startup */ + int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules) + { +@@ -2253,6 +2265,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod + ahead of all other internals + */ + php_ini_register_extensions(); ++#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) ++ zend_load_static_extensions(); ++#endif + zend_startup_modules(); + + /* start Zend extensions */ +diff --git a/win32/build/confutils.js b/win32/build/confutils.js +index 1a2dfe43b4..ae405f035a 100644 +--- a/win32/build/confutils.js ++++ b/win32/build/confutils.js +@@ -1535,6 +1535,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) + } + } + ++ // TODO: real skip zend extensions ++ if (extname != 'opcache') + extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; + + DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')'); diff --git a/src/globals/patch/spc_fix_static_opcache_before_80310.patch b/src/globals/patch/spc_fix_static_opcache_before_80310.patch new file mode 100644 index 00000000..bf555ef2 --- /dev/null +++ b/src/globals/patch/spc_fix_static_opcache_before_80310.patch @@ -0,0 +1,129 @@ +diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk +index 1e71ea2069..3da32d8830 100644 +--- a/build/order_by_dep.awk ++++ b/build/order_by_dep.awk +@@ -37,6 +37,11 @@ function get_module_index(name, i) + function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) + { + module_name = mods[mod_idx]; ++ # TODO: real skip zend extension ++ if (module_name == "opcache") { ++ delete mods[mod_idx]; ++ return; ++ } + mod_name_len = length(module_name); + + for (ext in mod_deps) { +diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c +index ec33c69eb2..b8ce7e3eca 100644 +--- a/ext/opcache/ZendAccelerator.c ++++ b/ext/opcache/ZendAccelerator.c +@@ -93,7 +93,10 @@ typedef int gid_t; + #include + #endif + ++#ifdef COMPILE_DL_OPCACHE ++// avoid symbol conflict + ZEND_EXTENSION(); ++#endif + + #ifndef ZTS + zend_accel_globals accel_globals; +@@ -4814,7 +4817,11 @@ static int accel_finish_startup(void) + #endif /* ZEND_WIN32 */ + } + ++#ifdef COMPILE_DL_OPCACHE + ZEND_EXT_API zend_extension zend_extension_entry = { ++#else ++zend_extension opcache_zend_extension_entry = { ++#endif + ACCELERATOR_PRODUCT_NAME, /* name */ + PHP_VERSION, /* version */ + "Zend Technologies", /* author */ +diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 +index 2a83fa2455..7b3b37182e 100644 +--- a/ext/opcache/config.m4 ++++ b/ext/opcache/config.m4 +@@ -21,7 +21,8 @@ PHP_ARG_ENABLE([opcache-jit], + if test "$PHP_OPCACHE" != "no"; then + + dnl Always build as shared extension +- ext_shared=yes ++ dnl why? ++ dnl ext_shared=yes + + if test "$PHP_HUGE_CODE_PAGES" = "yes"; then + AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) +@@ -327,7 +328,9 @@ int main() { + shared_alloc_mmap.c \ + shared_alloc_posix.c \ + $ZEND_JIT_SRC, +- shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) ++ $ext_shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) ++ ++ AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) + + PHP_ADD_EXTENSION_DEP(opcache, pcre) + +diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 +index 764a2edaab..95427090ce 100644 +--- a/ext/opcache/config.w32 ++++ b/ext/opcache/config.w32 +@@ -16,7 +16,9 @@ if (PHP_OPCACHE != "no") { + zend_persist_calc.c \ + zend_file_cache.c \ + zend_shared_alloc.c \ +- shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ++ shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ++ ++ AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); + + if (PHP_OPCACHE_JIT == "yes") { + if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { +diff --git a/main/main.c b/main/main.c +index 6fdfbce13e..bcccfad6e3 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -2012,6 +2012,18 @@ void dummy_invalid_parameter_handler( + } + #endif + ++// this can be moved to other place ++#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) ++extern zend_extension opcache_zend_extension_entry; ++extern void zend_register_extension(zend_extension *new_extension, void *handle); ++ ++int zend_load_static_extensions(void) ++{ ++ zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); ++ return 0; ++} ++#endif ++ + /* {{{ php_module_startup */ + zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module) + { +@@ -2196,6 +2208,9 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi + ahead of all other internals + */ + php_ini_register_extensions(); ++#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) ++ zend_load_static_extensions(); ++#endif + zend_startup_modules(); + + /* start Zend extensions */ +diff --git a/win32/build/confutils.js b/win32/build/confutils.js +index 359c751b7b..01068efcf6 100644 +--- a/win32/build/confutils.js ++++ b/win32/build/confutils.js +@@ -1534,6 +1534,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) + } + } + ++ // TODO: real skip zend extensions ++ if (extname != 'opcache') + extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; + + DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')');