From 310091180270218af54e684be3bfb0ba9bedd920 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Sun, 30 Jun 2024 00:12:39 +0800 Subject: [PATCH] Add several extensions and libs for windows exts: bz2, sqlsrv, pdo_sqlsrv, yaml, zip, rar libs: bzip2, libyaml, libzip, xz --- config/ext.json | 27 +++++---- config/lib.json | 33 ++++++----- src/SPC/builder/extension/sqlsrv.php | 36 ++++++++++++ src/SPC/builder/windows/library/bzip2.php | 21 +++++++ src/SPC/builder/windows/library/libyaml.php | 44 +++++++++++++++ src/SPC/builder/windows/library/libzip.php | 46 +++++++++++++++ src/SPC/builder/windows/library/xz.php | 39 +++++++++++++ src/SPC/store/FileSystem.php | 2 +- src/SPC/store/SourcePatcher.php | 56 +++++++++++++++++-- src/globals/extra/libyaml_YamlConfig.cmake.in | 10 ++++ src/globals/extra/libyaml_config.h.in | 4 ++ 11 files changed, 286 insertions(+), 32 deletions(-) create mode 100644 src/SPC/builder/extension/sqlsrv.php create mode 100644 src/SPC/builder/windows/library/bzip2.php create mode 100644 src/SPC/builder/windows/library/libyaml.php create mode 100644 src/SPC/builder/windows/library/libzip.php create mode 100644 src/SPC/builder/windows/library/xz.php create mode 100644 src/globals/extra/libyaml_YamlConfig.cmake.in create mode 100644 src/globals/extra/libyaml_config.h.in diff --git a/config/ext.json b/config/ext.json index a3ec8041..9e0c3f3e 100644 --- a/config/ext.json +++ b/config/ext.json @@ -21,11 +21,9 @@ "type": "builtin" }, "bz2": { - "support": { - "Windows": "wip" - }, "type": "builtin", - "arg-type": "with-prefix", + "arg-type-unix": "with-prefix", + "arg-type-windows": "with", "lib-depends": [ "bzip2" ] @@ -473,7 +471,6 @@ }, "pdo_sqlsrv": { "support": { - "Windows": "wip", "BSD": "wip" }, "type": "external", @@ -519,7 +516,6 @@ }, "rar": { "support": { - "Windows": "wip", "BSD": "wip", "Darwin": "partial" }, @@ -636,12 +632,11 @@ }, "sqlsrv": { "support": { - "Windows": "wip", "BSD": "wip" }, "type": "external", "source": "sqlsrv", - "lib-depends": [ + "lib-depends-unix": [ "unixodbc" ], "ext-depends-linux": [ @@ -925,12 +920,12 @@ }, "yaml": { "support": { - "Windows": "wip", "BSD": "wip" }, "type": "external", "source": "yaml", - "arg-type": "with-prefix", + "arg-type-unix": "with-prefix", + "arg-type-windows": "with", "lib-depends": [ "libyaml" ] @@ -943,8 +938,18 @@ "type": "builtin", "arg-type": "with-prefix", "arg-type-windows": "enable", - "lib-depends": [ + "lib-depends-unix": [ "libzip" + ], + "ext-depends-windows": [ + "zlib", + "bz2" + ], + "lib-depends-windows": [ + "libzip", + "zlib", + "bzip2", + "xz" ] }, "zlib": { diff --git a/config/lib.json b/config/lib.json index d57ba0df..faaef865 100644 --- a/config/lib.json +++ b/config/lib.json @@ -21,10 +21,8 @@ "libbz2.a" ], "static-libs-windows": [ - [ - "libbz2.lib", - "libbz2_a.lib" - ] + "libbz2.lib", + "libbz2_a.lib" ], "headers": [ "bzlib.h" @@ -448,23 +446,30 @@ "libzip.a" ], "static-libs-windows": [ - [ - "zip.lib", - "libzip_a.lib" - ] + "zip.lib", + "libzip_a.lib" ], "headers": [ "zip.h", "zipconf.h" ], - "lib-depends": [ + "lib-depends-unix": [ "zlib" ], - "lib-suggests": [ + "lib-suggests-unix": [ "bzip2", "xz", "zstd", "openssl" + ], + "lib-depends-windows": [ + "zlib", + "bzip2", + "xz" + ], + "lib-suggests-windows": [ + "zstd", + "openssl" ] }, "ncurses": { @@ -625,10 +630,8 @@ "liblzma.a" ], "static-libs-windows": [ - [ - "liblzma.lib", - "liblzma_a.lib" - ] + "liblzma.lib", + "liblzma_a.lib" ], "headers-unix": [ "lzma" @@ -637,7 +640,7 @@ "lzma", "lzma.h" ], - "lib-depends": [ + "lib-depends-unix": [ "libiconv" ] }, diff --git a/src/SPC/builder/extension/sqlsrv.php b/src/SPC/builder/extension/sqlsrv.php new file mode 100644 index 00000000..edf5d919 --- /dev/null +++ b/src/SPC/builder/extension/sqlsrv.php @@ -0,0 +1,36 @@ +builder->getExt('pdo_sqlsrv') === null) { + // support sqlsrv without pdo_sqlsrv + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/sqlsrv/config.w32', 'PHP_PDO_SQLSRV', '"no"'); + $this->pdo_sqlsrv_patched = true; + return true; + } + return false; + } + + public function patchBeforeConfigure(): bool + { + if ($this->pdo_sqlsrv_patched) { + // revert pdo_sqlsrv patch + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/sqlsrv/config.w32', '"no" == "no"', 'PHP_PDO_SQLSRV == "no"'); + return true; + } + return false; + } +} diff --git a/src/SPC/builder/windows/library/bzip2.php b/src/SPC/builder/windows/library/bzip2.php new file mode 100644 index 00000000..81a74b0a --- /dev/null +++ b/src/SPC/builder/windows/library/bzip2.php @@ -0,0 +1,21 @@ +builder->makeSimpleWrapper('nmake /nologo /f Makefile.msc CFLAGS="-DWIN32 -MT -Ox -D_FILE_OFFSET_BITS=64 -nologo"'); + cmd()->cd($this->source_dir) + ->execWithWrapper($nmake, 'clean') + ->execWithWrapper($nmake, 'lib'); + copy($this->source_dir . '\libbz2.lib', BUILD_LIB_PATH . '\libbz2.lib'); + copy($this->source_dir . '\libbz2.lib', BUILD_LIB_PATH . '\libbz2_a.lib'); + copy($this->source_dir . '\bzlib.h', BUILD_INCLUDE_PATH . '\bzlib.h'); + } +} diff --git a/src/SPC/builder/windows/library/libyaml.php b/src/SPC/builder/windows/library/libyaml.php new file mode 100644 index 00000000..5d4026c5 --- /dev/null +++ b/src/SPC/builder/windows/library/libyaml.php @@ -0,0 +1,44 @@ +source_dir . '\build'); + + // check missing files: cmake\config.h.in and .\YamlConfig.cmake.in + if (!file_exists($this->source_dir . '\cmake\config.h.in')) { + FileSystem::createDir($this->source_dir . '\cmake'); + copy(ROOT_DIR . '\src\globals\extra\libyaml_config.h.in', $this->source_dir . '\cmake\config.h.in'); + } + if (!file_exists($this->source_dir . '\YamlConfig.cmake.in')) { + copy(ROOT_DIR . '\src\globals\extra\libyaml_YamlConfig.cmake.in', $this->source_dir . '\YamlConfig.cmake.in'); + } + + // start build + cmd()->cd($this->source_dir) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('cmake'), + '-B build ' . + '-A x64 ' . + "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . + '-DCMAKE_BUILD_TYPE=Release ' . + '-DBUILD_SHARED_LIBS=OFF ' . + '-DBUILD_TESTING=OFF ' . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' + ) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('cmake'), + "--build build --config Release --target install -j{$this->builder->concurrency}" + ); + } +} diff --git a/src/SPC/builder/windows/library/libzip.php b/src/SPC/builder/windows/library/libzip.php new file mode 100644 index 00000000..9a8206af --- /dev/null +++ b/src/SPC/builder/windows/library/libzip.php @@ -0,0 +1,46 @@ +source_dir . '\build'); + + $openssl = $this->builder->getLib('openssl') ? 'ON' : 'OFF'; + $zstd = $this->builder->getLib('zstd') ? 'ON' : 'OFF'; + + // start build + cmd()->cd($this->source_dir) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('cmake'), + '-B build ' . + '-A x64 ' . + "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . + '-DCMAKE_BUILD_TYPE=Release ' . + '-DBUILD_SHARED_LIBS=OFF ' . + '-DENABLE_BZIP2=ON ' . + '-DENABLE_LZMA=ON ' . + "-DENABLE_ZSTD={$zstd} " . + "-DENABLE_OPENSSL={$openssl} " . + '-DBUILD_TOOLS=OFF ' . + '-DBUILD_DOC=OFF ' . + '-DBUILD_EXAMPLES=OFF ' . + '-DBUILD_REGRESS=OFF ' . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' + ) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('cmake'), + "--build build --config Release --target install -j{$this->builder->concurrency}" + ); + copy(BUILD_LIB_PATH . '\zip.lib', BUILD_LIB_PATH . '\libzip_a.lib'); + } +} diff --git a/src/SPC/builder/windows/library/xz.php b/src/SPC/builder/windows/library/xz.php new file mode 100644 index 00000000..cf5b7234 --- /dev/null +++ b/src/SPC/builder/windows/library/xz.php @@ -0,0 +1,39 @@ +source_dir . '\build'); + + // start build + cmd()->cd($this->source_dir) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('cmake'), + '-B build ' . + '-A x64 ' . + "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . + '-DCMAKE_BUILD_TYPE=Release ' . + '-DBUILD_SHARED_LIBS=OFF ' . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' + ) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('cmake'), + "--build build --config Release --target install -j{$this->builder->concurrency}" + ); + + // copy liblzma.lib to liblzma_a.lib + copy(BUILD_LIB_PATH . '/liblzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib'); + // patch lzma.h + FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '/lzma.h', 'defined(LZMA_API_STATIC)', 'defined(_WIN32)'); + } +} diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 6295a889..6d192bce 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -521,7 +521,7 @@ class FileSystem private static function emitSourceExtractHook(string $name): void { foreach ((self::$_extract_hook[$name] ?? []) as $hook) { - if ($hook() === true) { + if ($hook($name) === true) { logger()->info('Patched source [' . $name . '] after extracted'); } } diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 96238619..dc114fe2 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -9,6 +9,7 @@ use SPC\builder\linux\LinuxBuilder; use SPC\builder\unix\UnixBuilderBase; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; +use SPC\exception\WrongUsageException; class SourcePatcher { @@ -20,12 +21,18 @@ class SourcePatcher FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']); FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchPhpLibxml212']); FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchGDWin32']); + FileSystem::addSourceExtractHook('sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']); + FileSystem::addSourceExtractHook('pdo_sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']); + FileSystem::addSourceExtractHook('yaml', [SourcePatcher::class, 'patchYamlWin32']); } /** * Source patcher runner before buildconf * - * @param BuilderBase $builder Builder + * @param BuilderBase $builder Builder + * @throws FileSystemException + * @throws RuntimeException + * @throws WrongUsageException */ public static function patchBeforeBuildconf(BuilderBase $builder): void { @@ -77,7 +84,7 @@ class SourcePatcher * @throws RuntimeException * @throws FileSystemException */ - public static function patchMicro(?array $list = null, bool $reverse = false): bool + public static function patchMicro(): bool { if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) { return false; @@ -112,7 +119,7 @@ class SourcePatcher if (PHP_OS_FAMILY === 'Darwin') { $default[] = 'macos_iconv'; } - $patch_list = $list ?? $default; + $patch_list = $default; $patches = []; $serial = ['80', '81', '82', '83', '84']; foreach ($patch_list as $patchName) { @@ -135,7 +142,7 @@ class SourcePatcher f_passthru( 'cd ' . SOURCE_PATH . '/php-src && ' . - (PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . $patchesStr . ' | patch -p1 ' . ($reverse ? '-R' : '') + (PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . $patchesStr . ' | patch -p1 ' ); return true; @@ -183,6 +190,9 @@ class SourcePatcher return false; } + /** + * @throws FileSystemException + */ public static function patchSwoole(): bool { // swoole hook needs pdo/pdo.h @@ -281,6 +291,9 @@ class SourcePatcher return $result; } + /** + * @throws FileSystemException + */ public static function patchMicroPhar(int $version_id): void { FileSystem::backupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c'); @@ -306,11 +319,35 @@ class SourcePatcher } } + /** + * @throws RuntimeException + */ public static function unpatchMicroPhar(): void { FileSystem::restoreBackupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c'); } + /** + * Fix the compilation issue of sqlsrv and pdo_sqlsrv on Windows (/sdl check is too strict and will cause Zend compilation to fail) + * + * @throws FileSystemException + */ + public static function patchSQLSRVWin32(string $source_name): bool + { + $source_name = preg_replace('/[^a-z_]/', '', $source_name); + if (file_exists(SOURCE_PATH . '/php-src/ext/' . $source_name . '/config.w32')) { + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/' . $source_name . '/config.w32', '/sdl', ''); + return true; + } + return false; + } + + public static function patchYamlWin32(): bool + { + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/yaml/config.w32', "lib.substr(lib.length - 6, 6) == '_a.lib'", "lib.substr(lib.length - 6, 6) == '_a.lib' || 'yes' == 'yes'"); + return true; + } + /** * Patch cli SAPI Makefile for Windows. * @@ -325,7 +362,7 @@ class SourcePatcher $line_num = 0; $found = false; foreach ($lines as $v) { - if (strpos($v, '$(BUILD_DIR)\php.exe:') !== false) { + if (str_contains($v, '$(BUILD_DIR)\php.exe:')) { $found = $line_num; break; } @@ -339,6 +376,9 @@ class SourcePatcher FileSystem::writeFile(SOURCE_PATH . '/php-src/Makefile', implode("\r\n", $lines)); } + /** + * @throws RuntimeException + */ public static function patchPhpLibxml212(): bool { $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); @@ -360,6 +400,9 @@ class SourcePatcher return false; } + /** + * @throws FileSystemException + */ public static function patchGDWin32(): bool { $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); @@ -393,6 +436,9 @@ class SourcePatcher } } + /** + * @throws FileSystemException + */ public static function patchMicroWin32(): void { // patch micro win32 diff --git a/src/globals/extra/libyaml_YamlConfig.cmake.in b/src/globals/extra/libyaml_YamlConfig.cmake.in new file mode 100644 index 00000000..839f3aba --- /dev/null +++ b/src/globals/extra/libyaml_YamlConfig.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set_and_check(yaml_TARGETS "@PACKAGE_CONFIG_DIR_CONFIG@/yamlTargets.cmake") + +if(NOT yaml_TARGETS_IMPORTED) + set(yaml_TARGETS_IMPORTED 1) + include(${yaml_TARGETS}) +endif() + +set(yaml_LIBRARIES yaml) \ No newline at end of file diff --git a/src/globals/extra/libyaml_config.h.in b/src/globals/extra/libyaml_config.h.in new file mode 100644 index 00000000..c92894bb --- /dev/null +++ b/src/globals/extra/libyaml_config.h.in @@ -0,0 +1,4 @@ +#define YAML_VERSION_MAJOR @YAML_VERSION_MAJOR@ +#define YAML_VERSION_MINOR @YAML_VERSION_MINOR@ +#define YAML_VERSION_PATCH @YAML_VERSION_PATCH@ +#define YAML_VERSION_STRING "@YAML_VERSION_STRING@" \ No newline at end of file