Add several extensions and libs for windows

exts: bz2, sqlsrv, pdo_sqlsrv, yaml, zip, rar
libs: bzip2, libyaml, libzip, xz
This commit is contained in:
crazywhalecc 2024-06-30 00:12:39 +08:00 committed by Jerry Ma
parent a6236eb98c
commit 3100911802
11 changed files with 286 additions and 32 deletions

View File

@ -21,11 +21,9 @@
"type": "builtin" "type": "builtin"
}, },
"bz2": { "bz2": {
"support": {
"Windows": "wip"
},
"type": "builtin", "type": "builtin",
"arg-type": "with-prefix", "arg-type-unix": "with-prefix",
"arg-type-windows": "with",
"lib-depends": [ "lib-depends": [
"bzip2" "bzip2"
] ]
@ -473,7 +471,6 @@
}, },
"pdo_sqlsrv": { "pdo_sqlsrv": {
"support": { "support": {
"Windows": "wip",
"BSD": "wip" "BSD": "wip"
}, },
"type": "external", "type": "external",
@ -519,7 +516,6 @@
}, },
"rar": { "rar": {
"support": { "support": {
"Windows": "wip",
"BSD": "wip", "BSD": "wip",
"Darwin": "partial" "Darwin": "partial"
}, },
@ -636,12 +632,11 @@
}, },
"sqlsrv": { "sqlsrv": {
"support": { "support": {
"Windows": "wip",
"BSD": "wip" "BSD": "wip"
}, },
"type": "external", "type": "external",
"source": "sqlsrv", "source": "sqlsrv",
"lib-depends": [ "lib-depends-unix": [
"unixodbc" "unixodbc"
], ],
"ext-depends-linux": [ "ext-depends-linux": [
@ -925,12 +920,12 @@
}, },
"yaml": { "yaml": {
"support": { "support": {
"Windows": "wip",
"BSD": "wip" "BSD": "wip"
}, },
"type": "external", "type": "external",
"source": "yaml", "source": "yaml",
"arg-type": "with-prefix", "arg-type-unix": "with-prefix",
"arg-type-windows": "with",
"lib-depends": [ "lib-depends": [
"libyaml" "libyaml"
] ]
@ -943,8 +938,18 @@
"type": "builtin", "type": "builtin",
"arg-type": "with-prefix", "arg-type": "with-prefix",
"arg-type-windows": "enable", "arg-type-windows": "enable",
"lib-depends": [ "lib-depends-unix": [
"libzip" "libzip"
],
"ext-depends-windows": [
"zlib",
"bz2"
],
"lib-depends-windows": [
"libzip",
"zlib",
"bzip2",
"xz"
] ]
}, },
"zlib": { "zlib": {

View File

@ -21,10 +21,8 @@
"libbz2.a" "libbz2.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
[ "libbz2.lib",
"libbz2.lib", "libbz2_a.lib"
"libbz2_a.lib"
]
], ],
"headers": [ "headers": [
"bzlib.h" "bzlib.h"
@ -448,23 +446,30 @@
"libzip.a" "libzip.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
[ "zip.lib",
"zip.lib", "libzip_a.lib"
"libzip_a.lib"
]
], ],
"headers": [ "headers": [
"zip.h", "zip.h",
"zipconf.h" "zipconf.h"
], ],
"lib-depends": [ "lib-depends-unix": [
"zlib" "zlib"
], ],
"lib-suggests": [ "lib-suggests-unix": [
"bzip2", "bzip2",
"xz", "xz",
"zstd", "zstd",
"openssl" "openssl"
],
"lib-depends-windows": [
"zlib",
"bzip2",
"xz"
],
"lib-suggests-windows": [
"zstd",
"openssl"
] ]
}, },
"ncurses": { "ncurses": {
@ -625,10 +630,8 @@
"liblzma.a" "liblzma.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
[ "liblzma.lib",
"liblzma.lib", "liblzma_a.lib"
"liblzma_a.lib"
]
], ],
"headers-unix": [ "headers-unix": [
"lzma" "lzma"
@ -637,7 +640,7 @@
"lzma", "lzma",
"lzma.h" "lzma.h"
], ],
"lib-depends": [ "lib-depends-unix": [
"libiconv" "libiconv"
] ]
}, },

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('sqlsrv')]
class sqlsrv extends Extension
{
private bool $pdo_sqlsrv_patched = false;
public function patchBeforeBuildconf(): bool
{
if (PHP_OS_FAMILY === 'Windows' && $this->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;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
class bzip2 extends WindowsLibraryBase
{
public const NAME = 'bzip2';
protected function build(): void
{
$nmake = $this->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');
}
}

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class libyaml extends WindowsLibraryBase
{
public const NAME = 'libyaml';
protected function build(): void
{
// reset cmake
FileSystem::resetDir($this->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}"
);
}
}

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class libzip extends WindowsLibraryBase
{
public const NAME = 'libzip';
protected function build(): void
{
// reset cmake
FileSystem::resetDir($this->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');
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class xz extends WindowsLibraryBase
{
public const NAME = 'xz';
protected function build(): void
{
// 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} " .
'-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)');
}
}

View File

@ -521,7 +521,7 @@ class FileSystem
private static function emitSourceExtractHook(string $name): void private static function emitSourceExtractHook(string $name): void
{ {
foreach ((self::$_extract_hook[$name] ?? []) as $hook) { foreach ((self::$_extract_hook[$name] ?? []) as $hook) {
if ($hook() === true) { if ($hook($name) === true) {
logger()->info('Patched source [' . $name . '] after extracted'); logger()->info('Patched source [' . $name . '] after extracted');
} }
} }

View File

@ -9,6 +9,7 @@ use SPC\builder\linux\LinuxBuilder;
use SPC\builder\unix\UnixBuilderBase; use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
class SourcePatcher class SourcePatcher
{ {
@ -20,12 +21,18 @@ class SourcePatcher
FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']); FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']);
FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchPhpLibxml212']); FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchPhpLibxml212']);
FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchGDWin32']); 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 * 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 public static function patchBeforeBuildconf(BuilderBase $builder): void
{ {
@ -77,7 +84,7 @@ class SourcePatcher
* @throws RuntimeException * @throws RuntimeException
* @throws FileSystemException * @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')) { if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) {
return false; return false;
@ -112,7 +119,7 @@ class SourcePatcher
if (PHP_OS_FAMILY === 'Darwin') { if (PHP_OS_FAMILY === 'Darwin') {
$default[] = 'macos_iconv'; $default[] = 'macos_iconv';
} }
$patch_list = $list ?? $default; $patch_list = $default;
$patches = []; $patches = [];
$serial = ['80', '81', '82', '83', '84']; $serial = ['80', '81', '82', '83', '84'];
foreach ($patch_list as $patchName) { foreach ($patch_list as $patchName) {
@ -135,7 +142,7 @@ class SourcePatcher
f_passthru( f_passthru(
'cd ' . SOURCE_PATH . '/php-src && ' . '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; return true;
@ -183,6 +190,9 @@ class SourcePatcher
return false; return false;
} }
/**
* @throws FileSystemException
*/
public static function patchSwoole(): bool public static function patchSwoole(): bool
{ {
// swoole hook needs pdo/pdo.h // swoole hook needs pdo/pdo.h
@ -281,6 +291,9 @@ class SourcePatcher
return $result; return $result;
} }
/**
* @throws FileSystemException
*/
public static function patchMicroPhar(int $version_id): void public static function patchMicroPhar(int $version_id): void
{ {
FileSystem::backupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c'); FileSystem::backupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c');
@ -306,11 +319,35 @@ class SourcePatcher
} }
} }
/**
* @throws RuntimeException
*/
public static function unpatchMicroPhar(): void public static function unpatchMicroPhar(): void
{ {
FileSystem::restoreBackupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c'); 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. * Patch cli SAPI Makefile for Windows.
* *
@ -325,7 +362,7 @@ class SourcePatcher
$line_num = 0; $line_num = 0;
$found = false; $found = false;
foreach ($lines as $v) { foreach ($lines as $v) {
if (strpos($v, '$(BUILD_DIR)\php.exe:') !== false) { if (str_contains($v, '$(BUILD_DIR)\php.exe:')) {
$found = $line_num; $found = $line_num;
break; break;
} }
@ -339,6 +376,9 @@ class SourcePatcher
FileSystem::writeFile(SOURCE_PATH . '/php-src/Makefile', implode("\r\n", $lines)); FileSystem::writeFile(SOURCE_PATH . '/php-src/Makefile', implode("\r\n", $lines));
} }
/**
* @throws RuntimeException
*/
public static function patchPhpLibxml212(): bool public static function patchPhpLibxml212(): bool
{ {
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
@ -360,6 +400,9 @@ class SourcePatcher
return false; return false;
} }
/**
* @throws FileSystemException
*/
public static function patchGDWin32(): bool public static function patchGDWin32(): bool
{ {
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); $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 public static function patchMicroWin32(): void
{ {
// patch micro win32 // patch micro win32

View File

@ -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)

View File

@ -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@"