From 03510073c61097867ac5989a5312186f8a209d0d Mon Sep 17 00:00:00 2001 From: Jerry Ma Date: Tue, 5 Mar 2024 21:43:09 +0800 Subject: [PATCH] Fix windows curl build (#368) * fix curl on windows build needs nghttp2.dll bug * add curl on windows tests * cs fix * fix curl headers * exit powershell properly * reproduce zend_mm_heap corrupted * reproduce zend_mm_heap corrupted * reproduce zend_mm_heap corrupted * add for-libs option for download * add for-libs option for download * add for-libs option for download --- .github/workflows/tests.yml | 3 ++- bin/spc.ps1 | 1 + config/ext.json | 3 +++ config/lib.json | 2 +- src/SPC/builder/windows/WindowsBuilder.php | 12 +++++---- src/SPC/builder/windows/library/curl.php | 28 +++++---------------- src/SPC/builder/windows/library/nghttp2.php | 4 +-- src/SPC/command/BuildCliCommand.php | 4 +-- src/SPC/command/DownloadCommand.php | 26 ++++++++++++++++++- src/globals/test-extensions.php | 6 ++--- 10 files changed, 52 insertions(+), 37 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 21dcb0e8..789b12ee 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -164,7 +164,8 @@ jobs: timeout_minutes: 10 max_attempts: 3 retry_on: error - command: bin/spc download --for-extensions="$(php src/globals/test-extensions.php extensions)" --with-php=${{ matrix.php }} --debug + command: | + bin/spc download --for-extensions="$(php src/globals/test-extensions.php extensions)" --with-php=${{ matrix.php }} --debug - name: "Run Build Tests (build)" run: bin/spc build "$(php src/globals/test-extensions.php extensions)" $(php src/globals/test-extensions.php libs_cmd) --build-cli --build-micro --build-fpm --debug diff --git a/bin/spc.ps1 b/bin/spc.ps1 index 3a2639d0..2efd09ea 100644 --- a/bin/spc.ps1 +++ b/bin/spc.ps1 @@ -9,3 +9,4 @@ if (-not(Test-Path $PHP_Exec)) { } & "$PHP_Exec" ("bin/spc") @args +exit $LASTEXITCODE diff --git a/config/ext.json b/config/ext.json index b8fccc63..3bddb23b 100644 --- a/config/ext.json +++ b/config/ext.json @@ -52,6 +52,9 @@ "lib-depends": [ "libxml2", "zlib" + ], + "ext-depends-windows": [ + "xml" ] }, "event": { diff --git a/config/lib.json b/config/lib.json index 5b47bc91..746f508e 100644 --- a/config/lib.json +++ b/config/lib.json @@ -36,7 +36,7 @@ "libcurl.a" ], "static-libs-windows": [ - "libcurl.lib" + "libcurl_a.lib" ], "headers": [ "curl" diff --git a/src/SPC/builder/windows/WindowsBuilder.php b/src/SPC/builder/windows/WindowsBuilder.php index ff7209d5..256b392b 100644 --- a/src/SPC/builder/windows/WindowsBuilder.php +++ b/src/SPC/builder/windows/WindowsBuilder.php @@ -88,7 +88,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void if (($logo = $this->getOption('with-micro-logo')) !== null) { // realpath $logo = realpath($logo); - $micro_logo = '--enable-micro-logo=' . escapeshellarg($logo) . ' '; + $micro_logo = '--enable-micro-logo=' . $logo . ' '; } else { $micro_logo = ''; } @@ -187,10 +187,12 @@ public function buildMicro(): void SourcePatcher::patchMicro(['phar']); } - cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_micro_wrapper.bat --task-args micro"); - - if ($this->phar_patched) { - SourcePatcher::patchMicro(['phar'], true); + try { + cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_micro_wrapper.bat --task-args micro"); + } finally { + if ($this->phar_patched) { + SourcePatcher::patchMicro(['phar'], true); + } } $this->deployBinary(BUILD_TARGET_MICRO); diff --git a/src/SPC/builder/windows/library/curl.php b/src/SPC/builder/windows/library/curl.php index 4423a16c..1f25910a 100644 --- a/src/SPC/builder/windows/library/curl.php +++ b/src/SPC/builder/windows/library/curl.php @@ -12,29 +12,13 @@ class curl extends WindowsLibraryBase 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 ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DBUILD_CURL_EXE=OFF ' . - '-DUSE_ZLIB=ON ' . - '-DCURL_USE_OPENSSL=ON ' . - '-DCURL_USE_LIBLSSH2=ON ' . - '-DUSE_NGHTTP2=ON ' . // php-src with curl needs nghttp2 - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) + cmd()->cd($this->source_dir . '\winbuild') ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" + $this->builder->makeSimpleWrapper('nmake'), + '/f Makefile.vc WITH_DEVEL=' . BUILD_ROOT_PATH . ' ' . + 'WITH_PREFIX=' . BUILD_ROOT_PATH . ' ' . + 'mode=static RTLIBCFG=static WITH_SSL=static WITH_NGHTTP2=static WITH_SSH2=static ENABLE_IPV6=yes WITH_ZLIB=static MACHINE=x64 DEBUG=no' ); + FileSystem::copyDir($this->source_dir . '\include\curl', BUILD_INCLUDE_PATH . '\curl'); } } diff --git a/src/SPC/builder/windows/library/nghttp2.php b/src/SPC/builder/windows/library/nghttp2.php index a17fe89b..85332202 100644 --- a/src/SPC/builder/windows/library/nghttp2.php +++ b/src/SPC/builder/windows/library/nghttp2.php @@ -23,8 +23,8 @@ protected function build(): void '-A x64 ' . "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_STATIC_LIBS=ON ' . + '-DENABLE_SHARED_LIB=OFF ' . + '-DENABLE_STATIC_LIB=ON ' . '-DENABLE_STATIC_CRT=ON ' . '-DENABLE_LIB_ONLY=ON ' . '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildCliCommand.php index 3c5c2276..85d5e39c 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildCliCommand.php @@ -104,8 +104,8 @@ public function handle(): int $indent_texts = [ 'Build OS' => PHP_OS_FAMILY . ' (' . php_uname('m') . ')', 'Build SAPI' => $builder->getBuildTypeName($rule), - 'Extensions (' . count($extensions) . ')' => implode(', ', $extensions), - 'Libraries (' . count($libraries) . ')' => implode(', ', $libraries), + 'Extensions (' . count($extensions) . ')' => implode(',', $extensions), + 'Libraries (' . count($libraries) . ')' => implode(',', $libraries), 'Strip Binaries' => $builder->getOption('no-strip') ? 'no' : 'yes', 'Enable ZTS' => $builder->getOption('enable-zts') ? 'yes' : 'no', ]; diff --git a/src/SPC/command/DownloadCommand.php b/src/SPC/command/DownloadCommand.php index fa7f7543..a0eb4bce 100644 --- a/src/SPC/command/DownloadCommand.php +++ b/src/SPC/command/DownloadCommand.php @@ -36,6 +36,7 @@ public function configure(): void $this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"'); $this->addOption('from-zip', 'Z', InputOption::VALUE_REQUIRED, 'Fetch from zip archive'); $this->addOption('for-extensions', 'e', InputOption::VALUE_REQUIRED, 'Fetch by extensions, e.g "openssl,mbstring"'); + $this->addOption('for-libs', 'l', InputOption::VALUE_REQUIRED, 'Fetch by libraries, e.g "libcares,openssl,onig"'); $this->addOption('without-suggestions', null, null, 'Do not fetch suggested sources when using --for-extensions'); } @@ -46,6 +47,7 @@ public function initialize(InputInterface $input, OutputInterface $output): void || $input->getOption('clean') || $input->getOption('from-zip') || $input->getOption('for-extensions') + || $input->getOption('for-libs') ) { $input->setArgument('sources', ''); } @@ -112,6 +114,9 @@ public function handle(): int $ext = array_map('trim', array_filter(explode(',', $for_ext))); $sources = $this->calculateSourcesByExt($ext, !$this->getOption('without-suggestions')); array_unshift($sources, 'php-src', 'micro', 'pkg-config'); + } elseif ($for_lib = $this->getOption('for-libs')) { + $lib = array_map('trim', array_filter(explode(',', $for_lib))); + $sources = $this->calculateSourcesByLib($lib, !$this->getOption('without-suggestions')); } else { // get source list that will be downloaded $sources = array_map('trim', array_filter(explode(',', $this->getArgument('sources')))); @@ -208,7 +213,8 @@ private function downloadFromZip(string $path): int /** * Calculate the sources by extensions * - * @param array $extensions extension list + * @param array $extensions extension list + * @param bool $include_suggests include suggested libs and extensions (default: true) * @throws FileSystemException * @throws WrongUsageException */ @@ -226,4 +232,22 @@ private function calculateSourcesByExt(array $extensions, bool $include_suggests } return array_values(array_unique($sources)); } + + /** + * Calculate the sources by libraries + * + * @param array $libs library list + * @param bool $include_suggests include suggested libs (default: true) + * @throws FileSystemException + * @throws WrongUsageException + */ + private function calculateSourcesByLib(array $libs, bool $include_suggests = true): array + { + $libs = DependencyUtil::getLibs($libs, $include_suggests); + $sources = []; + foreach ($libs as $library) { + $sources[] = Config::getLib($library, 'source'); + } + return array_values(array_unique($sources)); + } } diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index cd12034c..7e549aa1 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -13,8 +13,8 @@ // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'swoole,swoole-hook-mysql,swoole-hook-pgsql,swoole-hook-sqlite,openssl,curl,pdo_mysql', - 'Windows' => 'mbstring,pdo_sqlite,mbregex,ffi', + 'Linux', 'Darwin' => 'zlib,openssl,curl,pcntl,posix,mbstring,tokenizer,phar', + 'Windows' => 'mbstring,pdo_sqlite,mbregex,ffi,curl', }; // If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`). @@ -27,7 +27,7 @@ // You can use `common`, `bulk`, `minimal` or `none`. // note: combination is only available for *nix platform. Windows must use `none` combination $base_combination = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'minimal', + 'Linux', 'Darwin' => 'none', 'Windows' => 'none', };