diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b42eef7d..5ed6d59d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -190,7 +190,7 @@ jobs: echo "UPX_CMD=$(php src/globals/test-extensions.php upx)" >> $GITHUB_ENV - name: "Run Build Tests (download)" - run: GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} php src/globals/test-extensions.php download_cmd ${{ matrix.os }} ${{ matrix.php }} + run: php src/globals/test-extensions.php download_cmd ${{ matrix.os }} ${{ matrix.php }} - name: "Run Build Tests (build)" run: php src/globals/test-extensions.php build_cmd ${{ matrix.os }} ${{ matrix.php }} diff --git a/config/ext.json b/config/ext.json index f8630697..a5eca9f4 100644 --- a/config/ext.json +++ b/config/ext.json @@ -304,12 +304,14 @@ }, "intl": { "support": { - "Windows": "no", "BSD": "wip" }, "type": "builtin", - "lib-depends": [ + "lib-depends-unix": [ "icu" + ], + "lib-depends-windows": [ + "icu-static-win" ] }, "ldap": { @@ -336,6 +338,9 @@ }, "type": "builtin", "arg-type": "none", + "ext-depends": [ + "xml" + ], "target": [ "static" ] diff --git a/config/lib.json b/config/lib.json index dc792c3b..1a195f66 100644 --- a/config/lib.json +++ b/config/lib.json @@ -207,6 +207,18 @@ "libicudata.a" ] }, + "icu-static-win": { + "source": "icu-static-win", + "static-libs-windows": [ + "icudt.lib", + "icuin.lib", + "icuio.lib", + "icuuc.lib" + ], + "headers-windows": [ + "unicode" + ] + }, "imagemagick": { "source": "imagemagick", "static-libs-unix": [ diff --git a/config/source.json b/config/source.json index 57a10a4e..b3c9cd62 100644 --- a/config/source.json +++ b/config/source.json @@ -342,6 +342,14 @@ "path": "LICENSE" } }, + "icu-static-win": { + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/icu-static-windows-x64/icu-static-windows-x64.zip", + "license": { + "type": "text", + "text": "none" + } + }, "igbinary": { "type": "url", "url": "https://pecl.php.net/get/igbinary", diff --git a/src/SPC/builder/extension/intl.php b/src/SPC/builder/extension/intl.php index 56ce1c61..0c1e323d 100644 --- a/src/SPC/builder/extension/intl.php +++ b/src/SPC/builder/extension/intl.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace SPC\builder\extension; use SPC\builder\Extension; +use SPC\builder\windows\WindowsBuilder; use SPC\store\FileSystem; use SPC\util\CustomExt; @@ -13,13 +14,15 @@ class intl extends Extension { public function patchBeforeBuildconf(): bool { - // TODO: remove the following line when https://github.com/php/php-src/pull/14002 will be released - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/intl/config.m4', 'PHP_CXX_COMPILE_STDCXX(11', 'PHP_CXX_COMPILE_STDCXX(17'); - // Also need to use clang++ -std=c++17 to force override the default C++ standard - if (is_string($env = getenv('CXX')) && !str_contains($env, 'std=c++17')) { - f_putenv('CXX=' . $env . ' -std=c++17'); + if ($this->builder instanceof WindowsBuilder) { + FileSystem::replaceFileStr( + SOURCE_PATH . '/php-src/ext/intl/config.w32', + 'EXTENSION("intl", "php_intl.c intl_convert.c intl_convertcpp.cpp intl_error.c ", true,', + 'EXTENSION("intl", "php_intl.c intl_convert.c intl_convertcpp.cpp intl_error.c ", PHP_INTL_SHARED,' + ); + return true; } - return true; + return false; } public function patchBeforeSharedPhpize(): bool diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index f9e9b6a1..b2181c7f 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -28,7 +28,7 @@ class LinuxBuilder extends UnixBuilderBase // check musl-cross make installed if we use musl-cross-make $arch = arch2gnu(php_uname('m')); - GlobalEnvManager::init($this); + GlobalEnvManager::init(); if (getenv('SPC_LIBC') === 'musl' && !SystemUtil::isMuslDist()) { $this->setOptionIfNotExist('library_path', "LIBRARY_PATH=\"/usr/local/musl/{$arch}-linux-musl/lib\""); diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index d43aab4a..173ec954 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -28,7 +28,7 @@ class MacOSBuilder extends UnixBuilderBase $this->options = $options; // apply global environment variables - GlobalEnvManager::init($this); + GlobalEnvManager::init(); // ---------- set necessary compile vars ---------- // concurrency diff --git a/src/SPC/builder/windows/WindowsBuilder.php b/src/SPC/builder/windows/WindowsBuilder.php index c7643143..c7450050 100644 --- a/src/SPC/builder/windows/WindowsBuilder.php +++ b/src/SPC/builder/windows/WindowsBuilder.php @@ -33,7 +33,7 @@ class WindowsBuilder extends BuilderBase { $this->options = $options; - GlobalEnvManager::init($this); + GlobalEnvManager::init(); // ---------- set necessary options ---------- // set sdk (require visual studio 16 or 17) diff --git a/src/SPC/builder/windows/library/icu_static_win.php b/src/SPC/builder/windows/library/icu_static_win.php new file mode 100644 index 00000000..c152c6e7 --- /dev/null +++ b/src/SPC/builder/windows/library/icu_static_win.php @@ -0,0 +1,27 @@ +source_dir}\\x64-windows-static\\lib\\icudt.lib", "{$this->getLibDir()}\\icudt.lib"); + copy("{$this->source_dir}\\x64-windows-static\\lib\\icuin.lib", "{$this->getLibDir()}\\icuin.lib"); + copy("{$this->source_dir}\\x64-windows-static\\lib\\icuio.lib", "{$this->getLibDir()}\\icuio.lib"); + copy("{$this->source_dir}\\x64-windows-static\\lib\\icuuc.lib", "{$this->getLibDir()}\\icuuc.lib"); + + // create libpq folder in buildroot/includes/libpq + if (!file_exists("{$this->getIncludeDir()}\\unicode")) { + mkdir("{$this->getIncludeDir()}\\unicode"); + } + + FileSystem::copyDir("{$this->source_dir}\\x64-windows-static\\include\\unicode", "{$this->getIncludeDir()}\\unicode"); + } +} diff --git a/src/SPC/command/DeleteDownloadCommand.php b/src/SPC/command/DeleteDownloadCommand.php index 0306de4c..1eeddf7e 100644 --- a/src/SPC/command/DeleteDownloadCommand.php +++ b/src/SPC/command/DeleteDownloadCommand.php @@ -22,6 +22,8 @@ class DeleteDownloadCommand extends BaseCommand { $this->addArgument('sources', InputArgument::REQUIRED, 'The sources/packages will be deleted, comma separated'); $this->addOption('all', 'A', null, 'Delete all downloaded and locked sources/packages'); + $this->addOption('pre-built-only', 'W', null, 'Delete only pre-built sources/packages, not the original ones'); + $this->addOption('source-only', 'S', null, 'Delete only sources, not the pre-built packages'); } public function initialize(InputInterface $input, OutputInterface $output): void @@ -51,10 +53,11 @@ class DeleteDownloadCommand extends BaseCommand $deleted_sources = []; foreach ($chosen_sources as $source) { $source = trim($source); - foreach ([$source, Downloader::getPreBuiltLockName($source)] as $name) { - if (LockFile::get($name)) { - $deleted_sources[] = $name; - } + if (LockFile::get($source) && !$this->getOption('pre-built-only')) { + $deleted_sources[] = $source; + } + if (LockFile::get(Downloader::getPreBuiltLockName($source)) && !$this->getOption('source-only')) { + $deleted_sources[] = Downloader::getPreBuiltLockName($source); } } diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 26bd8ffc..69d3a649 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -99,9 +99,6 @@ class SourcePatcher } // patch capstone FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"'); - if ($builder instanceof LinuxBuilder && getenv('SPC_LIBC') === 'glibc') { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Zend/zend_operators.h', '# define ZEND_USE_ASM_ARITHMETIC 1', '# define ZEND_USE_ASM_ARITHMETIC 0'); - } } /** diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index 6f04b328..fa5c9cf5 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace SPC\util; -use SPC\builder\BuilderBase; use SPC\builder\linux\SystemUtil; use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; @@ -24,11 +23,10 @@ class GlobalEnvManager /** * Initialize the environment variables * - * @param null|BuilderBase $builder Builder * @throws RuntimeException * @throws WrongUsageException */ - public static function init(?BuilderBase $builder = null): void + public static function init(): void { // Check pre-defined env vars exists if (getenv('BUILD_ROOT_PATH') === false) { @@ -37,7 +35,7 @@ class GlobalEnvManager // Define env vars for unix if (is_unix()) { - self::putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH')); + self::addPathIfNotExists(BUILD_BIN_PATH); self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config'); self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig'); } @@ -55,10 +53,73 @@ class GlobalEnvManager self::putenv("SPC_LINUX_DEFAULT_CXX={$arch}-linux-musl-g++"); self::putenv("SPC_LINUX_DEFAULT_AR={$arch}-linux-musl-ar"); self::putenv("SPC_LINUX_DEFAULT_LD={$arch}-linux-musl-ld"); - GlobalEnvManager::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH')); + self::addPathIfNotExists('/usr/local/musl/bin'); + self::addPathIfNotExists("/usr/local/musl/{$arch}-linux-musl/bin"); } } + $ini = self::readIniFile(); + + $default_put_list = []; + foreach ($ini['global'] as $k => $v) { + if (getenv($k) === false) { + $default_put_list[$k] = $v; + self::putenv("{$k}={$v}"); + } + } + $os_ini = match (PHP_OS_FAMILY) { + 'Windows' => $ini['windows'] ?? [], + 'Darwin' => $ini['macos'] ?? [], + 'Linux' => $ini['linux'] ?? [], + 'BSD' => $ini['freebsd'] ?? [], + default => [], + }; + foreach ($os_ini as $k => $v) { + if (getenv($k) === false) { + $default_put_list[$k] = $v; + self::putenv("{$k}={$v}"); + } + } + // apply second time + $ini2 = self::readIniFile(); + + foreach ($ini2['global'] as $k => $v) { + if (isset($default_put_list[$k]) && $default_put_list[$k] !== $v) { + self::putenv("{$k}={$v}"); + } + } + $os_ini2 = match (PHP_OS_FAMILY) { + 'Windows' => $ini2['windows'] ?? [], + 'Darwin' => $ini2['macos'] ?? [], + 'Linux' => $ini2['linux'] ?? [], + 'BSD' => $ini2['freebsd'] ?? [], + default => [], + }; + foreach ($os_ini2 as $k => $v) { + if (isset($default_put_list[$k]) && $default_put_list[$k] !== $v) { + self::putenv("{$k}={$v}"); + } + } + } + + public static function putenv(string $val): void + { + f_putenv($val); + self::$env_cache[] = $val; + } + + private static function addPathIfNotExists(string $path): void + { + if (is_unix() && !str_contains(getenv('PATH'), $path)) { + self::putenv("PATH={$path}:" . getenv('PATH')); + } + } + + /** + * @throws WrongUsageException + */ + private static function readIniFile(): array + { // Init env.ini file, read order: // WORKING_DIR/config/env.ini // ROOT_DIR/config/env.ini @@ -100,32 +161,6 @@ class GlobalEnvManager break; } } - self::applyConfig($ini['global']); - match (PHP_OS_FAMILY) { - 'Windows' => self::applyConfig($ini['windows']), - 'Darwin' => self::applyConfig($ini['macos']), - 'Linux' => self::applyConfig($ini['linux']), - 'BSD' => self::applyConfig($ini['freebsd']), - default => null, - }; - - if (str_contains(getenv('CC'), 'zig')) { - // add to path - } - } - - public static function putenv(string $val): void - { - f_putenv($val); - self::$env_cache[] = $val; - } - - private static function applyConfig(array $ini): void - { - foreach ($ini as $k => $v) { - if (getenv($k) === false) { - self::putenv($k . '=' . $v); - } - } + return $ini; } } diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 990cbdd9..70758f85 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -27,9 +27,9 @@ $test_os = [ // 'ubuntu-latest', // 'ubuntu-22.04', // 'ubuntu-24.04', - 'ubuntu-22.04-arm', + // 'ubuntu-22.04-arm', // 'ubuntu-24.04-arm', - // 'windows-latest', + 'windows-latest', ]; // whether enable thread safe @@ -48,8 +48,8 @@ $prefer_pre_built = true; // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'apcu,ast,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,iconv,libxml,mbregex,mbstring,opcache,openssl,pcntl,phar,posix,readline,session,simplexml,sockets,sodium,tokenizer,xml,xmlreader,xmlwriter,zip,zlib', - 'Windows' => 'xlswriter,openssl', + 'Linux', 'Darwin' => 'curl', + 'Windows' => 'intl', }; // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`).