diff --git a/config/ext.json b/config/ext.json index af349727..8e26de94 100644 --- a/config/ext.json +++ b/config/ext.json @@ -123,8 +123,12 @@ "iconv": { "type": "builtin", "arg-type": "with-prefix", - "lib-depends": [ + "arg-type-windows": "with", + "lib-depends-unix": [ "libiconv" + ], + "lib-depends-windows": [ + "libiconv-win" ] }, "igbinary": { @@ -351,9 +355,11 @@ "simplexml": { "type": "builtin", "arg-type": "custom", - "arg-type-windows": "with", "lib-depends": [ "libxml2" + ], + "ext-depends-windows": [ + "xml" ] }, "snappy": { @@ -373,6 +379,9 @@ "arg-type": "custom", "lib-depends": [ "libxml2" + ], + "ext-depends-windows": [ + "xml" ] }, "sockets": { @@ -488,8 +497,7 @@ "unix-only": true }, "sysvshm": { - "type": "builtin", - "unix-only": true + "type": "builtin" }, "tidy": { "type": "builtin", @@ -534,6 +542,9 @@ "arg-type-windows": "with", "lib-depends": [ "libxml2" + ], + "ext-depends-windows": [ + "iconv" ] }, "xmlreader": { @@ -541,6 +552,10 @@ "arg-type": "custom", "lib-depends": [ "libxml2" + ], + "ext-depends-windows": [ + "xml", + "dom" ] }, "xmlwriter": { @@ -548,6 +563,9 @@ "arg-type": "custom", "lib-depends": [ "libxml2" + ], + "ext-depends-windows": [ + "xml" ] }, "xsl": { diff --git a/config/lib.json b/config/lib.json index 25b027a5..7dfef67c 100644 --- a/config/lib.json +++ b/config/lib.json @@ -245,6 +245,13 @@ "localcharset.h" ] }, + "libiconv-win": { + "source": "libiconv-win", + "static-libs-windows": [ + "libiconv.lib", + "libiconv_a.lib" + ] + }, "libjpeg": { "source": "libjpeg", "static-libs-unix": [ @@ -334,21 +341,25 @@ "libxml2.a" ], "static-libs-windows": [ - [ - "libxml2s.lib", - "libxml2_a.lib" - ] + "libxml2s.lib", + "libxml2_a.lib" ], "headers": [ "libxml2" ], - "lib-depends": [ + "lib-depends-unix": [ "libiconv" ], - "lib-suggests": [ + "lib-suggests-unix": [ "xz", "icu", "zlib" + ], + "lib-depends-windows": [ + "libiconv-win" + ], + "lib-suggests-windows": [ + "zlib" ] }, "libxslt": { diff --git a/config/source.json b/config/source.json index 73212640..11b65f53 100644 --- a/config/source.json +++ b/config/source.json @@ -254,6 +254,15 @@ "path": "COPYING" } }, + "libiconv-win": { + "type": "git", + "rev": "master", + "url": "https://github.com/static-php/libiconv-win.git", + "license": { + "type": "file", + "path": "source/COPYING" + } + }, "libjpeg": { "type": "ghtar", "repo": "libjpeg-turbo/libjpeg-turbo", @@ -331,7 +340,7 @@ }, "libxml2": { "type": "url", - "url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.9.14.tar.gz", + "url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.12.5.tar.gz", "license": { "type": "file", "path": "Copyright" diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 1776a268..ea875a78 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -212,7 +212,7 @@ class Extension // Trim additional content & escape special characters to allow inline usage $test = str_replace( ['getName() . '.php')) ); diff --git a/src/SPC/builder/extension/xml.php b/src/SPC/builder/extension/xml.php index adac92c8..6242be6b 100644 --- a/src/SPC/builder/extension/xml.php +++ b/src/SPC/builder/extension/xml.php @@ -6,6 +6,7 @@ namespace SPC\builder\extension; use SPC\builder\Extension; use SPC\exception\RuntimeException; +use SPC\store\FileSystem; use SPC\util\CustomExt; #[CustomExt('xml')] @@ -33,4 +34,25 @@ class xml extends Extension $arg .= ' --with-libxml="' . BUILD_ROOT_PATH . '"'; return $arg; } + + public function patchBeforeBuildconf(): bool + { + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/win32/build/config.w32', 'dllmain.c ', ''); + return true; + } + + public function getWindowsConfigureArg(): string + { + $arg = match ($this->name) { + 'xml' => '--with-xml', + 'soap' => '--enable-soap', + 'xmlreader' => '--enable-xmlreader', + 'xmlwriter' => '--enable-xmlwriter', + 'dom' => '--with-dom', + 'simplexml' => '--with-simplexml', + default => throw new RuntimeException('Not accept non-xml extension'), + }; + $arg .= ' --with-libxml'; + return $arg; + } } diff --git a/src/SPC/builder/windows/library/libiconv_win.php b/src/SPC/builder/windows/library/libiconv_win.php new file mode 100644 index 00000000..4f638530 --- /dev/null +++ b/src/SPC/builder/windows/library/libiconv_win.php @@ -0,0 +1,35 @@ + '/MSVC17', + 'vs16' => '/MSVC16', + default => throw new RuntimeException('Current VS version is not supported yet!'), + }; + + // start build + cmd()->cd($this->source_dir . $vs_ver_dir) + ->execWithWrapper( + $this->builder->makeSimpleWrapper('msbuild'), + 'libiconv.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64' + ); + FileSystem::createDir(BUILD_LIB_PATH); + FileSystem::createDir(BUILD_INCLUDE_PATH); + copy($this->source_dir . $vs_ver_dir . '\x64\lib\libiconv.lib', BUILD_LIB_PATH . '\libiconv.lib'); + copy($this->source_dir . $vs_ver_dir . '\x64\lib\libiconv_a.lib', BUILD_LIB_PATH . '\libiconv_a.lib'); + copy($this->source_dir . '\source\include\iconv.h', BUILD_INCLUDE_PATH . '\iconv.h'); + } +} diff --git a/src/SPC/builder/windows/library/libxml2.php b/src/SPC/builder/windows/library/libxml2.php new file mode 100644 index 00000000..d4a4b9b4 --- /dev/null +++ b/src/SPC/builder/windows/library/libxml2.php @@ -0,0 +1,44 @@ +builder->getLib('zlib') ? 'ON' : 'OFF'; + // reset cmake + FileSystem::resetDir($this->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} " . + '-DBUILD_SHARED_LIBS=OFF ' . + '-DBUILD_STATIC_LIBS=ON ' . + "-DLIBXML2_WITH_ZLIB={$zlib} " . + '-DLIBXML2_WITH_PYTHON=OFF ' . + '-DLIBXML2_WITH_ICONV=ON ' . + '-DIconv_LIBRARY=' . BUILD_LIB_PATH . ' ' . + '-DIconv_INCLUDE_DIR=' . BUILD_INCLUDE_PATH . ' ' . + '-DLIBXML2_WITH_LZMA=OFF ' . // xz not supported yet + '-DLIBXML2_WITH_PROGRAMS=OFF ' . + '-DLIBXML2_WITH_TESTS=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 . '\libxml2s.lib', BUILD_LIB_PATH . '\libxml2_a.lib'); + } +} diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 2cb45e00..732c5b3c 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -219,6 +219,14 @@ class FileSystem return str_replace('/', DIRECTORY_SEPARATOR, $path); } + public static function convertWinPathToMinGW(string $path): string + { + if (preg_match('/^[A-Za-z]:/', $path)) { + $path = '/' . strtolower(substr($path, 0, 1)) . '/' . str_replace('\\', '/', substr($path, 2)); + } + return $path; + } + /** * 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表 * @@ -443,6 +451,9 @@ class FileSystem if (f_mkdir(directory: $target, recursive: true) !== true) { throw new FileSystemException('create ' . $target . ' dir failed'); } + if (!file_exists($filename)) { + throw new FileSystemException('File not exists'); + } if (in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD'])) { match (self::extname($filename)) { @@ -455,9 +466,15 @@ class FileSystem } elseif (PHP_OS_FAMILY === 'Windows') { // use php-sdk-binary-tools/bin/7za.exe $_7z = self::convertPath(PHP_SDK_PATH . '/bin/7za.exe'); + + // Windows notes: I hate windows tar....... + // When extracting .tar.gz like libxml2, it shows a symlink error and returns code[1]. + // Related posts: https://answers.microsoft.com/en-us/windows/forum/all/tar-on-windows-fails-to-extract-archive-containing/0ee9a7ea-9b1f-4fef-86a9-5d9dc35cea2f + // And MinGW tar.exe cannot work on temporarily storage ??? (GitHub Actions hosted runner) + // Yeah, I will be an MS HATER ! match (self::extname($filename)) { 'tar' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"), - 'xz', 'txz', 'gz', 'tgz', 'bz2' => f_passthru("\"{$_7z}\" x -so {$filename} | tar -f - -x -C {$target} --strip-components 1"), + 'xz', 'txz', 'gz', 'tgz', 'bz2' => cmd()->execWithResult("\"{$_7z}\" x -so {$filename} | tar -f - -x -C \"{$target}\" --strip-components 1"), 'zip' => f_passthru("\"{$_7z}\" x {$filename} -o{$target} -y"), default => throw new FileSystemException("unknown archive format: {$filename}"), }; diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index fd0f1083..0cb26e07 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -14,7 +14,7 @@ declare(strict_types=1); // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { 'Linux', 'Darwin' => 'event,gettext', - 'Windows' => 'mbstring,curl,ssh2', + 'Windows' => 'mbstring,iconv,dom,xml,xmlwriter,xmlreader,soap,simplexml', }; // If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).