diff --git a/bin/spc-alpine-docker b/bin/spc-alpine-docker index 2640ffba..dc6eaa36 100755 --- a/bin/spc-alpine-docker +++ b/bin/spc-alpine-docker @@ -108,8 +108,7 @@ RUN apk update; \ wget \ xz \ gettext-dev \ - binutils-gold \ - patchelf + binutils-gold RUN curl -#fSL https://dl.static-php.dev/static-php-cli/bulk/php-8.4.4-cli-linux-\$(uname -m).tar.gz | tar -xz -C /usr/local/bin && \ chmod +x /usr/local/bin/php diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 68f85109..286ef985 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -92,11 +92,6 @@ RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc RUN source /etc/bashrc RUN yum install -y which -RUN curl -fsSL -o patchelf.tgz https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-$SPC_USE_ARCH.tar.gz && \ - mkdir -p /patchelf && \ - tar -xzf patchelf.tgz -C /patchelf --strip-components=1 && \ - cp /patchelf/bin/patchelf /usr/bin/ - RUN curl -o cmake.tgz -#fSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$SPC_USE_ARCH.tar.gz && \ mkdir /cmake && \ tar -xzf cmake.tgz -C /cmake --strip-components 1 diff --git a/config/artifact.json b/config/artifact.json index c8fd6621..ad8507b9 100644 --- a/config/artifact.json +++ b/config/artifact.json @@ -1,135 +1,4 @@ { - "vswhere": { - "binary": { - "windows-x86_64": { - "type": "url", - "url": "https://github.com/microsoft/vswhere/releases/download/3.1.7/vswhere.exe", - "extract": "{pkg_root_path}/bin/vswhere.exe" - } - } - }, - "musl-wrapper": { - "source": "https://musl.libc.org/releases/musl-1.2.5.tar.gz" - }, - "php-src": { - "source": { - "type": "php-release" - } - }, - "php-sdk-binary-tools": { - "binary": { - "windows-x86_64": { - "type": "git", - "rev": "master", - "url": "https://github.com/php/php-sdk-binary-tools.git", - "extract": "{php_sdk_path}" - } - } - }, - "go-xcaddy": { - "binary": "custom" - }, - "musl-toolchain": { - "binary": { - "linux-x86_64": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/x86_64-musl-toolchain.tgz", - "extract": "{pkg_root_path}/musl-toolchain" - }, - "linux-aarch64": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz", - "extract": "{pkg_root_path}/musl-toolchain" - } - } - }, - "pkg-config": { - "source": "https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz", - "binary": { - "linux-x86_64": { - "type": "ghrel", - "repo": "static-php/static-php-cli-hosted", - "match": "pkg-config-aarch64-linux-musl-1.2.5.txz", - "extract": { - "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" - } - }, - "linux-aarch64": { - "type": "ghrel", - "repo": "static-php/static-php-cli-hosted", - "match": "pkg-config-x86_64-linux-musl-1.2.5.txz", - "extract": { - "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" - } - }, - "macos-x86_64": { - "type": "ghrel", - "repo": "static-php/static-php-cli-hosted", - "match": "pkg-config-x86_64-darwin.txz", - "extract": { - "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" - } - }, - "macos-aarch64": { - "type": "ghrel", - "repo": "static-php/static-php-cli-hosted", - "match": "pkg-config-aarch64-darwin.txz", - "extract": "{pkg_root_path}" - } - } - }, - "strawberry-perl": { - "binary": { - "windows-x86_64": { - "type": "url", - "url": "https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip", - "extract": "{pkg_root_path}/strawberry-perl" - } - } - }, - "upx": { - "binary": { - "linux-x86_64": { - "type": "ghrel", - "repo": "upx/upx", - "match": "upx.+-amd64_linux\\.tar\\.xz", - "extract": { - "upx": "{pkg_root_path}/bin/upx" - } - }, - "linux-aarch64": { - "type": "ghrel", - "repo": "upx/upx", - "match": "upx.+-arm64_linux\\.tar\\.xz", - "extract": { - "upx": "{pkg_root_path}/bin/upx" - } - }, - "windows-x86_64": { - "type": "ghrel", - "repo": "upx/upx", - "match": "upx.+-win64\\.zip", - "extract": { - "upx.exe": "{pkg_root_path}/bin/upx.exe" - } - } - } - }, - "zig": { - "binary": "custom" - }, - "nasm": { - "binary": { - "windows-x86_64": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/nasm/nasm-2.16.01-win64.zip", - "extract": { - "nasm.exe": "{php_sdk_path}/bin/nasm.exe", - "ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe" - } - } - } - }, "amqp": { "source": { "type": "url", @@ -395,6 +264,9 @@ "repo": "guanzhi/GmSSL" } }, + "go-xcaddy": { + "binary": "custom" + }, "grpc": { "binary": "hosted", "source": { @@ -733,13 +605,6 @@ "extract": "php-src/ext/memcached" } }, - "mimalloc": { - "source": { - "type": "ghtagtar", - "repo": "microsoft/mimalloc", - "match": "v2\\.\\d\\.[^3].*" - } - }, "micro": { "source": { "type": "git", @@ -748,6 +613,13 @@ "url": "https://github.com/static-php/phpmicro" } }, + "mimalloc": { + "source": { + "type": "ghtagtar", + "repo": "microsoft/mimalloc", + "match": "v2\\.\\d\\.[^3].*" + } + }, "mongodb": { "source": { "type": "ghrel", @@ -765,6 +637,35 @@ "extract": "php-src/ext/msgpack" } }, + "musl-toolchain": { + "binary": { + "linux-x86_64": { + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/x86_64-musl-toolchain.tgz", + "extract": "{pkg_root_path}/musl-toolchain" + }, + "linux-aarch64": { + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz", + "extract": "{pkg_root_path}/musl-toolchain" + } + } + }, + "musl-wrapper": { + "source": "https://musl.libc.org/releases/musl-1.2.5.tar.gz" + }, + "nasm": { + "binary": { + "windows-x86_64": { + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/nasm/nasm-2.16.01-win64.zip", + "extract": { + "nasm.exe": "{php_sdk_path}/bin/nasm.exe", + "ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe" + } + } + } + }, "ncurses": { "binary": "hosted", "source": { @@ -850,6 +751,56 @@ "extract": "php-src/ext/pdo_sqlsrv" } }, + "php-sdk-binary-tools": { + "binary": { + "windows-x86_64": { + "type": "git", + "rev": "master", + "url": "https://github.com/php/php-sdk-binary-tools.git", + "extract": "{php_sdk_path}" + } + } + }, + "php-src": { + "source": { + "type": "php-release" + } + }, + "pkg-config": { + "binary": { + "linux-x86_64": { + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-aarch64-linux-musl-1.2.5.txz", + "extract": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } + }, + "linux-aarch64": { + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-x86_64-linux-musl-1.2.5.txz", + "extract": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } + }, + "macos-x86_64": { + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-x86_64-darwin.txz", + "extract": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } + }, + "macos-aarch64": { + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-aarch64-darwin.txz", + "extract": "{pkg_root_path}" + } + }, + "source": "https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz" + }, "postgresql": { "source": { "type": "ghtagtar", @@ -950,6 +901,15 @@ "extract": "php-src/ext/sqlsrv" } }, + "strawberry-perl": { + "binary": { + "windows-x86_64": { + "type": "url", + "url": "https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip", + "extract": "{pkg_root_path}/strawberry-perl" + } + } + }, "swoole": { "source": { "type": "ghtar", @@ -982,6 +942,43 @@ "version": "2.3.12" } }, + "upx": { + "binary": { + "linux-x86_64": { + "type": "ghrel", + "repo": "upx/upx", + "match": "upx.+-amd64_linux\\.tar\\.xz", + "extract": { + "upx": "{pkg_root_path}/bin/upx" + } + }, + "linux-aarch64": { + "type": "ghrel", + "repo": "upx/upx", + "match": "upx.+-arm64_linux\\.tar\\.xz", + "extract": { + "upx": "{pkg_root_path}/bin/upx" + } + }, + "windows-x86_64": { + "type": "ghrel", + "repo": "upx/upx", + "match": "upx.+-win64\\.zip", + "extract": { + "upx.exe": "{pkg_root_path}/bin/upx.exe" + } + } + } + }, + "vswhere": { + "binary": { + "windows-x86_64": { + "type": "url", + "url": "https://github.com/microsoft/vswhere/releases/download/3.1.7/vswhere.exe", + "extract": "{pkg_root_path}/bin/vswhere.exe" + } + } + }, "watcher": { "source": { "type": "ghtar", @@ -1041,6 +1038,9 @@ "extract": "php-src/ext/yaml" } }, + "zig": { + "binary": "custom" + }, "zlib": { "binary": "hosted", "source": { diff --git a/config/env.ini b/config/env.ini index 8e25aa6e..bd2f3d4f 100644 --- a/config/env.ini +++ b/config/env.ini @@ -122,17 +122,20 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="" +; optional, path to openssl conf. This affects where openssl will look for the default CA. +; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls +OPENSSLDIR="" + [macos] ; build target: macho or macho (possibly we could support macho-universal in the future) ; Currently we do not support universal and cross-compilation for macOS. SPC_TARGET=native-macos ; compiler environments -CC=${SPC_LINUX_DEFAULT_CC} -CXX=${SPC_LINUX_DEFAULT_CXX} -AR=${SPC_LINUX_DEFAULT_AR} -LD=${SPC_LINUX_DEFAULT_LD} +CC=clang +CXX=clang++ +AR=ar +LD=ld ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build -; this will be added to all CFLAGS and CXXFLAGS for the library builds SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os" SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os" SPC_DEFAULT_LD_FLAGS="" @@ -150,3 +153,5 @@ SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable- SPC_CMD_VAR_PHP_EMBED_TYPE="static" ; EXTRA_CFLAGS for `configure` and `make` php SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Werror=unknown-warning-option ${SPC_DEFAULT_C_FLAGS}" +; minimum compatible macOS version (LLVM vars, availability not guaranteed) +MACOSX_DEPLOYMENT_TARGET=12.0 diff --git a/config/ext.json b/config/ext.json index d3fd2aa2..566974b9 100644 --- a/config/ext.json +++ b/config/ext.json @@ -127,6 +127,14 @@ "sockets" ] }, + "excimer": { + "support": { + "Windows": "wip", + "BSD": "wip" + }, + "type": "external", + "source": "ext-excimer" + }, "exif": { "type": "builtin" }, @@ -232,11 +240,13 @@ "BSD": "wip" }, "type": "external", - "source": "grpc", + "source": "ext-grpc", "arg-type-unix": "enable-path", "cpp-extension": true, "lib-depends": [ - "grpc" + "zlib", + "openssl", + "libcares" ] }, "iconv": { @@ -408,8 +418,7 @@ "ext-depends": [ "zlib", "session" - ], - "build-with-php": true + ] }, "memcached": { "support": { @@ -487,6 +496,40 @@ "zlib" ] }, + "mysqlnd_ed25519": { + "type": "external", + "source": "mysqlnd_ed25519", + "arg-type": "enable", + "target": [ + "shared" + ], + "ext-depends": [ + "mysqlnd" + ], + "lib-depends": [ + "libsodium" + ], + "lib-suggests": [ + "openssl" + ] + }, + "mysqlnd_parsec": { + "type": "external", + "source": "mysqlnd_parsec", + "arg-type": "enable", + "target": [ + "shared" + ], + "ext-depends": [ + "mysqlnd" + ], + "lib-depends": [ + "libsodium" + ], + "lib-suggests": [ + "openssl" + ] + }, "oci8": { "type": "wip", "support": { diff --git a/config/lib.json b/config/lib.json index 47f3c7b8..3be97248 100644 --- a/config/lib.json +++ b/config/lib.json @@ -361,6 +361,9 @@ "source": "libargon2", "static-libs-unix": [ "libargon2.a" + ], + "lib-suggests": [ + "libsodium" ] }, "libavif": { diff --git a/config/pkg.ext.json b/config/pkg.ext.json index 70fe34e6..b1e819eb 100644 --- a/config/pkg.ext.json +++ b/config/pkg.ext.json @@ -1,66 +1,66 @@ { "ext-amqp": { - "type": "php-extension", - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - }, + "artifact": "amqp", "depends": [ "librabbitmq" ], "depends@windows": [ "ext-openssl" ], - "artifact": "amqp", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "support": { + "BSD": "wip" + }, + "arg-type": "custom" + }, + "type": "php-extension" }, "ext-apcu": { - "type": "php-extension", "artifact": "apcu", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "php-extension" }, "ext-ast": { - "type": "php-extension", "artifact": "ast", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "php-extension" }, "ext-bcmath": { "type": "php-extension" }, "ext-brotli": { - "type": "php-extension", - "php-extension": { - "arg-type": "enable" - }, + "artifact": "ext-brotli", "depends": [ "brotli" ], - "artifact": "ext-brotli", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "arg-type": "enable" + }, + "type": "php-extension" }, "ext-bz2": { - "type": "php-extension", + "depends": [ + "bzip2" + ], "php-extension": { "arg-type@windows": "with", "arg-type": "with-path" }, - "depends": [ - "bzip2" - ] + "type": "php-extension" }, "ext-calendar": { "type": "php-extension" @@ -69,43 +69,49 @@ "type": "php-extension" }, "ext-curl": { - "type": "php-extension", - "php-extension": { - "arg-type": "with", - "notes": true - }, "depends": [ "curl" ], "depends@windows": [ "ext-zlib", "ext-openssl" - ] + ], + "php-extension": { + "arg-type": "with", + "notes": true + }, + "type": "php-extension" }, "ext-dba": { - "type": "php-extension", "php-extension": { "arg-type": "custom" }, "suggests": [ "qdbm" - ] + ], + "type": "php-extension" }, "ext-dio": { - "type": "php-extension", + "artifact": "dio", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip" } }, - "artifact": "dio", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-dom": { - "type": "php-extension", + "depends": [ + "libxml2", + "zlib" + ], + "depends@windows": [ + "ext-xml" + ], "php-extension": { "support": { "BSD": "wip" @@ -113,24 +119,17 @@ "arg-type": "custom", "arg-type@windows": "with" }, - "depends": [ - "libxml2", - "zlib" - ], - "depends@windows": [ - "ext-xml" - ] + "type": "php-extension" }, "ext-ds": { - "type": "php-extension", "artifact": "ext-ds", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "php-extension" }, "ext-enchant": { - "type": "php-extension", "php-extension": { "support": { "Windows": "wip", @@ -138,24 +137,33 @@ "Darwin": "wip", "Linux": "wip" } - } + }, + "type": "php-extension" }, "ext-ev": { - "type": "php-extension", - "php-extension": { - "arg-type@windows": "with" - }, + "artifact": "ev", "depends": [ "ext-sockets" ], - "artifact": "ev", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "arg-type@windows": "with" + }, + "type": "php-extension" }, "ext-event": { - "type": "php-extension", + "artifact": "ext-event", + "depends": [ + "libevent", + "ext-openssl" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", @@ -164,24 +172,21 @@ "arg-type": "custom", "notes": true }, - "depends": [ - "libevent", - "ext-openssl" - ], "suggests": [ "ext-sockets" ], - "artifact": "ext-event", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-exif": { "type": "php-extension" }, "ext-ffi": { - "type": "php-extension", + "depends": [ + "libffi" + ], + "depends@windows": [ + "libffi-win" + ], "php-extension": { "support": { "Linux": "partial", @@ -190,12 +195,7 @@ "arg-type": "custom", "notes": true }, - "depends@windows": [ - "libffi-win" - ], - "depends": [ - "libffi" - ] + "type": "php-extension" }, "ext-fileinfo": { "type": "php-extension" @@ -204,13 +204,17 @@ "type": "php-extension" }, "ext-ftp": { - "type": "php-extension", "suggests": [ "openssl" - ] + ], + "type": "php-extension" }, "ext-gd": { - "type": "php-extension", + "depends": [ + "zlib", + "libpng", + "ext-zlib" + ], "php-extension": { "support": { "BSD": "wip" @@ -219,20 +223,18 @@ "arg-type@windows": "with", "notes": true }, - "depends": [ - "zlib", - "libpng", - "ext-zlib" - ], "suggests": [ "libavif", "libwebp", "libjpeg", "freetype" - ] + ], + "type": "php-extension" }, "ext-gettext": { - "type": "php-extension", + "depends": [ + "gettext" + ], "php-extension": { "support": { "Windows": "wip", @@ -240,12 +242,18 @@ }, "arg-type": "with-path" }, - "depends": [ - "gettext" - ] + "type": "php-extension" }, "ext-glfw": { - "type": "php-extension", + "artifact": "ext-glfw", + "depends": [ + "glfw" + ], + "depends@windows": [], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", @@ -255,18 +263,12 @@ "arg-type": "custom", "notes": true }, - "depends": [ - "glfw" - ], - "depends@windows": [], - "artifact": "ext-glfw", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-gmp": { - "type": "php-extension", + "depends": [ + "gmp" + ], "php-extension": { "support": { "Windows": "wip", @@ -274,28 +276,34 @@ }, "arg-type": "with-path" }, - "depends": [ - "gmp" - ] + "type": "php-extension" }, "ext-gmssl": { - "type": "php-extension", + "artifact": "ext-gmssl", + "depends": [ + "gmssl" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip" } }, + "type": "php-extension" + }, + "ext-grpc": { + "artifact": "grpc", "depends": [ - "gmssl" + "grpc" ], - "artifact": "ext-gmssl", + "lang": "cpp", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-grpc": { - "type": "php-extension", + }, "php-extension": { "support": { "Windows": "wip", @@ -303,18 +311,15 @@ }, "arg-type": "enable-path" }, - "depends": [ - "grpc" - ], - "lang": "cpp", - "artifact": "grpc", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-iconv": { - "type": "php-extension", + "depends": [ + "libiconv" + ], + "depends@windows": [ + "libiconv-win" + ], "php-extension": { "support": { "BSD": "wip" @@ -322,15 +327,14 @@ "arg-type": "with-path", "arg-type@windows": "with" }, - "depends@windows": [ - "libiconv-win" - ], - "depends": [ - "libiconv" - ] + "type": "php-extension" }, "ext-igbinary": { - "type": "php-extension", + "artifact": "igbinary", + "license": { + "type": "file", + "path": "COPYING" + }, "php-extension": { "support": { "BSD": "wip" @@ -340,33 +344,17 @@ "ext-session", "ext-apcu" ], - "artifact": "igbinary", - "license": { - "type": "file", - "path": "COPYING" - } + "type": "php-extension" }, "ext-imagick": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - }, + "artifact": "ext-imagick", "depends": [ "imagemagick" ], - "artifact": "ext-imagick", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-imap": { - "type": "php-extension", + }, "php-extension": { "support": { "Windows": "wip", @@ -375,22 +363,38 @@ "arg-type": "custom", "notes": true }, + "type": "php-extension" + }, + "ext-imap": { + "artifact": "ext-imap", "depends": [ "imap" ], - "suggests": [ - "ext-openssl" - ], - "artifact": "ext-imap", "license": { "type": "file", "path": [ "LICENSE" ] - } + }, + "php-extension": { + "support": { + "Windows": "wip", + "BSD": "wip" + }, + "arg-type": "custom", + "notes": true + }, + "suggests": [ + "ext-openssl" + ], + "type": "php-extension" }, "ext-inotify": { - "type": "php-extension", + "artifact": "inotify", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "no", @@ -398,28 +402,26 @@ "Darwin": "no" } }, - "artifact": "inotify", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-intl": { - "type": "php-extension", + "depends": [ + "icu" + ], + "depends@windows": [ + "icu-static-win" + ], "php-extension": { "support": { "BSD": "wip" } }, - "depends@windows": [ - "icu-static-win" - ], - "depends": [ - "icu" - ] + "type": "php-extension" }, "ext-ldap": { - "type": "php-extension", + "depends": [ + "ldap" + ], "php-extension": { "support": { "Windows": "wip", @@ -427,17 +429,17 @@ }, "arg-type": "with-path" }, - "depends": [ - "ldap" - ], "suggests": [ "gmp", "libsodium", "ext-openssl" - ] + ], + "type": "php-extension" }, "ext-libxml": { - "type": "php-extension", + "depends": [ + "ext-xml" + ], "php-extension": { "support": { "BSD": "wip" @@ -447,12 +449,19 @@ "build-static": true, "build-with-php": true }, - "depends": [ - "ext-xml" - ] + "type": "php-extension" }, "ext-lz4": { - "type": "php-extension", + "artifact": "ext-lz4", + "depends": [ + "liblz4" + ], + "license": { + "type": "file", + "path": [ + "LICENSE" + ] + }, "php-extension": { "support": { "Windows": "wip", @@ -460,37 +469,27 @@ }, "arg-type": "custom" }, - "depends": [ - "liblz4" - ], - "artifact": "ext-lz4", - "license": { - "type": "file", - "path": [ - "LICENSE" - ] - } + "type": "php-extension" }, "ext-mbregex": { - "type": "php-extension", + "depends": [ + "onig", + "ext-mbstring" + ], "php-extension": { "arg-type": "custom", "build-shared": false, "build-static": true }, - "depends": [ - "onig", - "ext-mbstring" - ] + "type": "php-extension" }, "ext-mbstring": { - "type": "php-extension", "php-extension": { "arg-type": "custom" - } + }, + "type": "php-extension" }, "ext-mcrypt": { - "type": "php-extension", "php-extension": { "support": { "Windows": "no", @@ -499,10 +498,19 @@ "Linux": "no" }, "notes": true - } + }, + "type": "php-extension" }, "ext-memcache": { - "type": "php-extension", + "artifact": "ext-memcache", + "depends": [ + "ext-zlib", + "ext-session" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", @@ -511,18 +519,21 @@ "arg-type": "custom", "build-with-php": true }, + "type": "php-extension" + }, + "ext-memcached": { + "artifact": "memcached", "depends": [ - "ext-zlib", - "ext-session" + "libmemcached", + "fastlz", + "ext-session", + "ext-zlib" ], - "artifact": "ext-memcache", + "lang": "cpp", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-memcached": { - "type": "php-extension", + }, "php-extension": { "support": { "Windows": "wip", @@ -530,27 +541,24 @@ }, "arg-type": "custom" }, - "depends": [ - "libmemcached", - "fastlz", - "ext-session", - "ext-zlib" - ], "suggests": [ "zstd", "ext-igbinary", "ext-msgpack", "ext-session" ], - "lang": "cpp", - "artifact": "memcached", + "type": "php-extension" + }, + "ext-mongodb": { + "artifact": "mongodb", + "frameworks": [ + "CoreFoundation", + "Security" + ], "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-mongodb": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip", @@ -564,18 +572,17 @@ "zstd", "zlib" ], - "frameworks": [ - "CoreFoundation", - "Security" + "type": "php-extension" + }, + "ext-msgpack": { + "artifact": "msgpack", + "depends": [ + "ext-session" ], - "artifact": "mongodb", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-msgpack": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip" @@ -583,37 +590,29 @@ "arg-type@windows": "enable", "arg-type": "with" }, - "depends": [ - "ext-session" - ], - "artifact": "msgpack", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-mysqli": { - "type": "php-extension", + "depends": [ + "ext-mysqlnd" + ], "php-extension": { "arg-type": "with", "build-with-php": true }, - "depends": [ - "ext-mysqlnd" - ] + "type": "php-extension" }, "ext-mysqlnd": { - "type": "php-extension", + "depends": [ + "zlib" + ], "php-extension": { "arg-type@windows": "with", "build-with-php": true }, - "depends": [ - "zlib" - ] + "type": "php-extension" }, "ext-oci8": { - "type": "php-extension", "php-extension": { "support": { "Windows": "wip", @@ -622,10 +621,13 @@ "Linux": "no" }, "notes": true - } + }, + "type": "php-extension" }, "ext-odbc": { - "type": "php-extension", + "depends": [ + "unixodbc" + ], "php-extension": { "support": { "BSD": "wip", @@ -633,47 +635,52 @@ }, "arg-type": "custom" }, - "depends": [ - "unixodbc" - ] + "type": "php-extension" }, "ext-opcache": { - "type": "php-extension", "php-extension": { "arg-type@windows": "enable", "arg-type": "custom", "zend-extension": true - } + }, + "type": "php-extension" }, "ext-openssl": { - "type": "php-extension", + "depends": [ + "openssl", + "zlib", + "ext-zlib" + ], "php-extension": { "arg-type": "custom", "arg-type@windows": "with", "build-with-php": true, "notes": true }, - "depends": [ - "openssl", - "zlib", - "ext-zlib" - ] + "type": "php-extension" }, "ext-opentelemetry": { - "type": "php-extension", + "artifact": "opentelemetry", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip" } }, - "artifact": "opentelemetry", + "type": "php-extension" + }, + "ext-parallel": { + "artifact": "parallel", + "depends@windows": [ + "pthreads4w" + ], "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-parallel": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip" @@ -681,17 +688,13 @@ "arg-type@windows": "with", "notes": true }, - "depends@windows": [ - "pthreads4w" - ], - "artifact": "parallel", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-password-argon2": { - "type": "php-extension", + "depends": [ + "libargon2", + "openssl" + ], "php-extension": { "support": { "Windows": "wip", @@ -700,48 +703,52 @@ "arg-type": "custom", "notes": true }, - "depends": [ - "libargon2", - "openssl" - ] + "type": "php-extension" }, "ext-pcntl": { - "type": "php-extension", "php-extension": { "support": { "Windows": "no" } - } + }, + "type": "php-extension" }, "ext-pdo": { "type": "php-extension" }, "ext-pdo_mysql": { - "type": "php-extension", - "php-extension": { - "arg-type": "with" - }, "depends": [ "ext-pdo", "ext-mysqlnd" - ] + ], + "php-extension": { + "arg-type": "with" + }, + "type": "php-extension" }, "ext-pdo_odbc": { - "type": "php-extension", + "depends": [ + "unixodbc", + "ext-pdo", + "ext-odbc" + ], "php-extension": { "support": { "BSD": "wip" }, "arg-type": "custom" }, - "depends": [ - "unixodbc", - "ext-pdo", - "ext-odbc" - ] + "type": "php-extension" }, "ext-pdo_pgsql": { - "type": "php-extension", + "depends": [ + "postgresql", + "ext-pdo", + "ext-pgsql" + ], + "depends@windows": [ + "postgresql-win" + ], "php-extension": { "support": { "BSD": "wip" @@ -749,49 +756,47 @@ "arg-type": "with-path", "arg-type@windows": "custom" }, - "depends@windows": [ - "postgresql-win" - ], - "depends": [ - "postgresql", - "ext-pdo", - "ext-pgsql" - ] + "type": "php-extension" }, "ext-pdo_sqlite": { - "type": "php-extension", - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with" - }, "depends": [ "sqlite", "ext-pdo", "ext-sqlite3" - ] - }, - "ext-pdo_sqlsrv": { - "type": "php-extension", + ], "php-extension": { "support": { "BSD": "wip" }, "arg-type": "with" }, + "type": "php-extension" + }, + "ext-pdo_sqlsrv": { + "artifact": "pdo_sqlsrv", "depends": [ "ext-pdo", "ext-sqlsrv" ], - "artifact": "pdo_sqlsrv", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "support": { + "BSD": "wip" + }, + "arg-type": "with" + }, + "type": "php-extension" }, "ext-pgsql": { - "type": "php-extension", + "depends": [ + "postgresql" + ], + "depends@windows": [ + "postgresql-win" + ], "php-extension": { "support": { "BSD": "wip" @@ -799,43 +804,43 @@ "arg-type": "custom", "notes": true }, - "depends@windows": [ - "postgresql-win" - ], - "depends": [ - "postgresql" - ] + "type": "php-extension" }, "ext-phar": { - "type": "php-extension", "depends": [ "ext-zlib" - ] + ], + "type": "php-extension" }, "ext-posix": { - "type": "php-extension", "php-extension": { "support": { "Windows": "no" } - } + }, + "type": "php-extension" }, "ext-protobuf": { - "type": "php-extension", + "artifact": "protobuf", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", "BSD": "wip" } }, - "artifact": "protobuf", + "type": "php-extension" + }, + "ext-rar": { + "artifact": "rar", + "lang": "cpp", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-rar": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip", @@ -843,15 +848,18 @@ }, "notes": true }, + "type": "php-extension" + }, + "ext-rdkafka": { + "artifact": "ext-rdkafka", + "depends": [ + "librdkafka" + ], "lang": "cpp", - "artifact": "rar", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-rdkafka": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip", @@ -859,18 +867,12 @@ }, "arg-type": "custom" }, - "depends": [ - "librdkafka" - ], - "lang": "cpp", - "artifact": "ext-rdkafka", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-readline": { - "type": "php-extension", + "depends": [ + "libedit" + ], "php-extension": { "support": { "Windows": "wip", @@ -880,12 +882,17 @@ "build-shared": false, "build-static": true }, - "depends": [ - "libedit" - ] + "type": "php-extension" }, "ext-redis": { - "type": "php-extension", + "artifact": "redis", + "license": { + "type": "file", + "path": [ + "LICENSE", + "COPYING" + ] + }, "php-extension": { "support": { "BSD": "wip" @@ -899,38 +906,36 @@ "ext-igbinary", "ext-msgpack" ], - "artifact": "redis", - "license": { - "type": "file", - "path": [ - "LICENSE", - "COPYING" - ] - } + "type": "php-extension" }, "ext-session": { - "type": "php-extension", "php-extension": { "build-with-php": true - } + }, + "type": "php-extension" }, "ext-shmop": { - "type": "php-extension", "php-extension": { "build-with-php": true - } + }, + "type": "php-extension" }, "ext-simdjson": { - "type": "php-extension", - "lang": "cpp", "artifact": "ext-simdjson", + "lang": "cpp", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "php-extension" }, "ext-simplexml": { - "type": "php-extension", + "depends": [ + "libxml2" + ], + "depends@windows": [ + "ext-xml" + ], "php-extension": { "support": { "BSD": "wip" @@ -938,15 +943,18 @@ "arg-type": "custom", "build-with-php": true }, - "depends": [ - "libxml2" - ], - "depends@windows": [ - "ext-xml" - ] + "type": "php-extension" }, "ext-snappy": { - "type": "php-extension", + "artifact": "ext-snappy", + "depends": [ + "snappy" + ], + "lang": "cpp", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", @@ -954,21 +962,15 @@ }, "arg-type": "custom" }, - "depends": [ - "snappy" - ], "suggests": [ "ext-apcu" ], - "lang": "cpp", - "artifact": "ext-snappy", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-snmp": { - "type": "php-extension", + "depends": [ + "net-snmp" + ], "php-extension": { "support": { "Windows": "wip", @@ -977,40 +979,45 @@ "arg-type@windows": "with", "arg-type": "with" }, - "depends": [ - "net-snmp" - ] + "type": "php-extension" }, "ext-soap": { - "type": "php-extension", + "depends": [ + "ext-libxml", + "ext-session" + ], "php-extension": { "support": { "BSD": "wip" }, "arg-type": "custom" }, - "depends": [ - "ext-libxml", - "ext-session" - ] + "type": "php-extension" }, "ext-sockets": { "type": "php-extension" }, "ext-sodium": { - "type": "php-extension", + "depends": [ + "libsodium" + ], "php-extension": { "support": { "BSD": "wip" }, "arg-type": "with" }, - "depends": [ - "libsodium" - ] + "type": "php-extension" }, "ext-spx": { - "type": "php-extension", + "artifact": "spx", + "depends": [ + "zlib" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip", @@ -1019,17 +1026,12 @@ "arg-type": "custom", "notes": true }, - "depends": [ - "zlib" - ], - "artifact": "spx", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-sqlite3": { - "type": "php-extension", + "depends": [ + "sqlite" + ], "php-extension": { "support": { "BSD": "wip" @@ -1038,17 +1040,10 @@ "arg-type@windows": "with", "build-with-php": true }, - "depends": [ - "sqlite" - ] + "type": "php-extension" }, "ext-sqlsrv": { - "type": "php-extension", - "php-extension": { - "support": { - "BSD": "wip" - } - }, + "artifact": "sqlsrv", "depends": [ "unixodbc" ], @@ -1056,14 +1051,28 @@ "ext-pcntl" ], "lang": "cpp", - "artifact": "sqlsrv", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "support": { + "BSD": "wip" + } + }, + "type": "php-extension" }, "ext-ssh2": { - "type": "php-extension", + "artifact": "ext-ssh2", + "depends": [ + "libssh2", + "ext-openssl", + "ext-zlib" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip" @@ -1071,27 +1080,10 @@ "arg-type": "with-path", "arg-type@windows": "with" }, - "depends": [ - "libssh2", - "ext-openssl", - "ext-zlib" - ], - "artifact": "ext-ssh2", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-swoole": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - }, + "artifact": "swoole", "depends": [ "libcares", "brotli", @@ -1100,6 +1092,19 @@ "ext-openssl", "ext-curl" ], + "lang": "cpp", + "license": { + "type": "file", + "path": "LICENSE" + }, + "php-extension": { + "support": { + "Windows": "no", + "BSD": "wip" + }, + "arg-type": "custom", + "notes": true + }, "suggests": [ "zstd", "ext-sockets", @@ -1112,35 +1117,15 @@ "zstd", "liburing" ], - "lang": "cpp", - "artifact": "swoole", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-swoole-hook-mysql": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "arg-type": "none", - "notes": true - }, "depends": [ "ext-mysqlnd", "ext-pdo", "ext-pdo_mysql", "ext-swoole" ], - "suggests": [ - "ext-mysqli" - ] - }, - "ext-swoole-hook-odbc": { - "type": "php-extension", "php-extension": { "support": { "Windows": "no", @@ -1149,14 +1134,33 @@ "arg-type": "none", "notes": true }, + "suggests": [ + "ext-mysqli" + ], + "type": "php-extension" + }, + "ext-swoole-hook-odbc": { "depends": [ "unixodbc", "ext-pdo", "ext-swoole" - ] + ], + "php-extension": { + "support": { + "Windows": "no", + "BSD": "wip" + }, + "arg-type": "none", + "notes": true + }, + "type": "php-extension" }, "ext-swoole-hook-pgsql": { - "type": "php-extension", + "depends": [ + "ext-pgsql", + "ext-pdo", + "ext-swoole" + ], "php-extension": { "support": { "Windows": "no", @@ -1166,14 +1170,14 @@ "arg-type": "none", "notes": true }, - "depends": [ - "ext-pgsql", - "ext-pdo", - "ext-swoole" - ] + "type": "php-extension" }, "ext-swoole-hook-sqlite": { - "type": "php-extension", + "depends": [ + "ext-sqlite3", + "ext-pdo", + "ext-swoole" + ], "php-extension": { "support": { "Windows": "no", @@ -1182,14 +1186,14 @@ "arg-type": "none", "notes": true }, - "depends": [ - "ext-sqlite3", - "ext-pdo", - "ext-swoole" - ] + "type": "php-extension" }, "ext-swow": { - "type": "php-extension", + "artifact": "swow", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip" @@ -1203,40 +1207,38 @@ "ext-openssl", "ext-curl" ], - "artifact": "swow", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-sysvmsg": { - "type": "php-extension", "php-extension": { "support": { "Windows": "no", "BSD": "wip" } - } + }, + "type": "php-extension" }, "ext-sysvsem": { - "type": "php-extension", "php-extension": { "support": { "Windows": "no", "BSD": "wip" } - } + }, + "type": "php-extension" }, "ext-sysvshm": { - "type": "php-extension", "php-extension": { "support": { "BSD": "wip" } - } + }, + "type": "php-extension" }, "ext-tidy": { - "type": "php-extension", + "depends": [ + "tidy" + ], "php-extension": { "support": { "Windows": "wip", @@ -1244,50 +1246,37 @@ }, "arg-type": "with-path" }, - "depends": [ - "tidy" - ] + "type": "php-extension" }, "ext-tokenizer": { - "type": "php-extension", "php-extension": { "build-with-php": true - } + }, + "type": "php-extension" }, "ext-trader": { - "type": "php-extension", + "artifact": "ext-trader", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip", "Windows": "wip" } }, - "artifact": "ext-trader", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-uuid": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - }, + "artifact": "ext-uuid", "depends": [ "libuuid" ], - "artifact": "ext-uuid", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-uv": { - "type": "php-extension", + }, "php-extension": { "support": { "Windows": "wip", @@ -1295,18 +1284,33 @@ }, "arg-type": "with-path" }, + "type": "php-extension" + }, + "ext-uv": { + "artifact": "ext-uv", "depends": [ "libuv", "ext-sockets" ], - "artifact": "ext-uv", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "support": { + "Windows": "wip", + "BSD": "wip" + }, + "arg-type": "with-path" + }, + "type": "php-extension" }, "ext-xdebug": { - "type": "php-extension", + "artifact": "xdebug", + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", @@ -1319,14 +1323,17 @@ "notes": true, "zend-extension": true }, - "artifact": "xdebug", + "type": "php-extension" + }, + "ext-xhprof": { + "artifact": "xhprof", + "depends": [ + "ext-ctype" + ], "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-xhprof": { - "type": "php-extension", + }, "php-extension": { "support": { "Windows": "wip", @@ -1335,17 +1342,18 @@ "build-with-php": true, "notes": true }, + "type": "php-extension" + }, + "ext-xlswriter": { + "artifact": "xlswriter", "depends": [ - "ext-ctype" + "ext-zlib", + "ext-zip" ], - "artifact": "xhprof", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-xlswriter": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip" @@ -1355,18 +1363,15 @@ "suggests": [ "openssl" ], - "depends": [ - "ext-zlib", - "ext-zip" - ], - "artifact": "xlswriter", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-xml": { - "type": "php-extension", + "depends": [ + "libxml2" + ], + "depends@windows": [ + "ext-iconv" + ], "php-extension": { "support": { "BSD": "wip" @@ -1376,32 +1381,16 @@ "build-with-php": true, "notes": true }, - "depends": [ - "libxml2" - ], - "depends@windows": [ - "ext-iconv" - ] + "type": "php-extension" }, "ext-xmlreader": { - "type": "php-extension", - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "build-with-php": true - }, "depends": [ "libxml2" ], "depends@windows": [ "ext-xml", "ext-dom" - ] - }, - "ext-xmlwriter": { - "type": "php-extension", + ], "php-extension": { "support": { "BSD": "wip" @@ -1409,15 +1398,30 @@ "arg-type": "custom", "build-with-php": true }, + "type": "php-extension" + }, + "ext-xmlwriter": { "depends": [ "libxml2" ], "depends@windows": [ "ext-xml" - ] + ], + "php-extension": { + "support": { + "BSD": "wip" + }, + "arg-type": "custom", + "build-with-php": true + }, + "type": "php-extension" }, "ext-xsl": { - "type": "php-extension", + "depends": [ + "libxslt", + "ext-xml", + "ext-dom" + ], "php-extension": { "support": { "Windows": "wip", @@ -1425,46 +1429,49 @@ }, "arg-type": "with-path" }, - "depends": [ - "libxslt", - "ext-xml", - "ext-dom" - ] + "type": "php-extension" }, "ext-xz": { - "type": "php-extension", - "php-extension": { - "arg-type": "with" - }, + "artifact": "ext-xz", "depends": [ "xz" ], - "artifact": "ext-xz", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "arg-type": "with" + }, + "type": "php-extension" }, "ext-yac": { - "type": "php-extension", + "artifact": "yac", + "depends": [ + "fastlz", + "ext-igbinary" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "BSD": "wip" }, "arg-type": "custom" }, + "type": "php-extension" + }, + "ext-yaml": { + "artifact": "yaml", "depends": [ - "fastlz", - "ext-igbinary" + "libyaml" ], - "artifact": "yac", "license": { "type": "file", "path": "LICENSE" - } - }, - "ext-yaml": { - "type": "php-extension", + }, "php-extension": { "support": { "BSD": "wip" @@ -1472,24 +1479,13 @@ "arg-type@windows": "with", "arg-type": "with-path" }, - "depends": [ - "libyaml" - ], - "artifact": "yaml", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" }, "ext-zip": { - "type": "php-extension", - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "arg-type@windows": "enable" - }, + "artifact": "ext-zip", + "depends": [ + "libzip" + ], "depends@windows": [ "libzip", "zlib", @@ -1498,17 +1494,23 @@ "ext-zlib", "ext-bz2" ], - "depends": [ - "libzip" - ], - "artifact": "ext-zip", "license": { "type": "file", "path": "LICENSE" - } + }, + "php-extension": { + "support": { + "BSD": "wip" + }, + "arg-type": "custom", + "arg-type@windows": "enable" + }, + "type": "php-extension" }, "ext-zlib": { - "type": "php-extension", + "depends": [ + "zlib" + ], "php-extension": { "arg-type": "custom", "arg-type@windows": "enable", @@ -1516,12 +1518,17 @@ "build-static": true, "build-with-php": true }, - "depends": [ - "zlib" - ] + "type": "php-extension" }, "ext-zstd": { - "type": "php-extension", + "artifact": "ext-zstd", + "depends": [ + "zstd" + ], + "license": { + "type": "file", + "path": "LICENSE" + }, "php-extension": { "support": { "Windows": "wip", @@ -1529,13 +1536,6 @@ }, "arg-type": "custom" }, - "depends": [ - "zstd" - ], - "artifact": "ext-zstd", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "php-extension" } } diff --git a/config/pkg.lib.json b/config/pkg.lib.json index 79e1a853..6cade9b7 100644 --- a/config/pkg.lib.json +++ b/config/pkg.lib.json @@ -1,54 +1,62 @@ { "attr": { - "type": "library", "artifact": "attr", "license": { "type": "file", "path": "doc/COPYING.LGPL" - } + }, + "type": "library" }, "brotli": { - "type": "library", + "artifact": "brotli", "headers": [ "brotli" ], + "license": { + "type": "file", + "path": "LICENSE" + }, "pkg-configs": [ "libbrotlicommon", "libbrotlidec", "libbrotlienc" ], - "artifact": "brotli", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "bzip2": { - "type": "library", + "artifact": "bzip2", "headers": [ "bzlib.h" ], - "artifact": "bzip2", "license": { "type": "text", "text": "This program, \"bzip2\", the associated library \"libbzip2\", and all documentation, are copyright (C) 1996-2010 Julian R Seward. All rights reserved. \n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n 2. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n 4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nJulian Seward, jseward@bzip.org bzip2/libbzip2 version 1.0.6 of 6 September 2010\n\nPATENTS: To the best of my knowledge, bzip2 and libbzip2 do not use any patented algorithms. However, I do not have the resources to carry out a patent search. Therefore I cannot give any guarantee of the above statement." - } + }, + "type": "library" }, "curl": { - "type": "library", + "artifact": "curl", + "depends": [ + "openssl", + "zlib" + ], "depends@windows": [ "zlib", "libssh2", "nghttp2" ], - "depends": [ - "openssl", - "zlib" + "frameworks": [ + "CoreFoundation", + "CoreServices", + "SystemConfiguration" ], - "suggests@windows": [ - "brotli", - "zstd" + "headers": [ + "curl" ], + "license": { + "type": "file", + "path": "COPYING" + }, "suggests": [ "libssh2", "brotli", @@ -59,150 +67,142 @@ "libcares", "ldap" ], - "headers": [ - "curl" + "suggests@windows": [ + "brotli", + "zstd" ], - "frameworks": [ - "CoreFoundation", - "CoreServices", - "SystemConfiguration" - ], - "artifact": "curl", - "license": { - "type": "file", - "path": "COPYING" - } + "type": "library" }, "fastlz": { - "type": "library", + "artifact": "fastlz", "headers": [ "fastlz/fastlz.h" ], - "artifact": "fastlz", "license": { "type": "file", "path": "LICENSE.MIT" - } + }, + "type": "library" }, "freetype": { - "type": "library", + "artifact": "freetype", "depends": [ "zlib" ], - "suggests": [ - "libpng", - "bzip2", - "brotli" - ], "headers": [ "freetype2/freetype/freetype.h", "freetype2/ft2build.h" ], - "artifact": "freetype", "license": { "type": "file", "path": "LICENSE.TXT" - } + }, + "suggests": [ + "libpng", + "bzip2", + "brotli" + ], + "type": "library" }, "gettext": { - "type": "library", + "artifact": "gettext", "depends": [ "libiconv" ], - "suggests": [ - "ncurses", - "libxml2" - ], "frameworks": [ "CoreFoundation" ], - "artifact": "gettext", "license": { "type": "file", "path": "gettext-runtime/intl/COPYING.LIB" - } + }, + "suggests": [ + "ncurses", + "libxml2" + ], + "type": "library" }, "glfw": { - "type": "library", + "artifact": "ext-glfw", "frameworks": [ "CoreVideo", "OpenGL", "Cocoa", "IOKit" ], - "artifact": "ext-glfw", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "gmp": { - "type": "library", + "artifact": "gmp", "headers": [ "gmp.h" ], - "artifact": "gmp", "license": { "type": "text", "text": "Since version 6, GMP is distributed under the dual licenses, GNU LGPL v3 and GNU GPL v2. These licenses make the library free to use, share, and improve, and allow you to pass on the result. The GNU licenses give freedoms, but also set firm restrictions on the use with non-free programs." - } + }, + "type": "library" }, "gmssl": { - "type": "library", + "artifact": "gmssl", "frameworks": [ "Security" ], - "artifact": "gmssl", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "grpc": { - "type": "library", + "artifact": "grpc", "depends": [ "zlib", "openssl", "libcares" ], - "pkg-configs": [ - "grpc" - ], "frameworks": [ "CoreFoundation" ], - "artifact": "grpc", "license": { "type": "file", "path": "LICENSE" - } + }, + "pkg-configs": [ + "grpc" + ], + "type": "library" }, "icu": { - "type": "library", + "artifact": "icu", + "license": { + "type": "file", + "path": "LICENSE" + }, "pkg-configs": [ "icu-uc", "icu-i18n", "icu-io" ], - "artifact": "icu", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "icu-static-win": { - "type": "library", + "artifact": "icu-static-win", "headers@windows": [ "unicode" ], - "artifact": "icu-static-win", "license": { "type": "text", "text": "none" - } + }, + "type": "library" }, "imagemagick": { - "type": "library", + "artifact": "imagemagick", "depends": [ "zlib", "libjpeg", @@ -214,183 +214,183 @@ "libheif", "bzip2" ], + "license": { + "type": "file", + "path": "LICENSE" + }, + "pkg-configs": [ + "Magick++-7.Q16HDRI", + "MagickCore-7.Q16HDRI", + "MagickWand-7.Q16HDRI" + ], "suggests": [ "zstd", "xz", "libzip", "libxml2" ], - "pkg-configs": [ - "Magick++-7.Q16HDRI", - "MagickCore-7.Q16HDRI", - "MagickWand-7.Q16HDRI" - ], - "artifact": "imagemagick", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "imap": { - "type": "library", - "suggests": [ - "openssl" - ], "artifact": "imap", "license": { "type": "file", "path": "LICENSE" - } + }, + "suggests": [ + "openssl" + ], + "type": "library" }, "jbig": { - "type": "library", + "artifact": "jbig", "headers": [ "jbig.h", "jbig85.h", "jbig_ar.h" ], - "artifact": "jbig", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "ldap": { - "type": "library", + "artifact": "ldap", "depends": [ "openssl", "zlib", "gmp", "libsodium" ], + "license": { + "type": "file", + "path": "LICENSE" + }, "pkg-configs": [ "ldap", "lber" ], - "artifact": "ldap", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "lerc": { - "type": "library", "artifact": "lerc", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libacl": { - "type": "library", + "artifact": "libacl", "depends": [ "attr" ], - "artifact": "libacl", "license": { "type": "file", "path": "doc/COPYING.LGPL" - } + }, + "type": "library" }, "libaom": { - "type": "library", "artifact": "libaom", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libargon2": { - "type": "library", "artifact": "libargon2", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libavif": { - "type": "library", "artifact": "libavif", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libcares": { - "type": "library", + "artifact": "libcares", "headers": [ "ares.h", "ares_dns.h", "ares_nameser.h" ], - "artifact": "libcares", "license": { "type": "file", "path": "LICENSE.md" - } + }, + "type": "library" }, "libde265": { - "type": "library", "artifact": "libde265", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "libedit": { - "type": "library", + "artifact": "libedit", "depends": [ "ncurses" ], - "artifact": "libedit", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "libevent": { - "type": "library", + "artifact": "libevent", "depends": [ "openssl" ], - "artifact": "libevent", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libffi": { - "type": "library", + "artifact": "libffi", + "headers": [ + "ffi.h", + "ffitarget.h" + ], "headers@windows": [ "ffi.h", "fficonfig.h", "ffitarget.h" ], - "headers": [ - "ffi.h", - "ffitarget.h" - ], - "artifact": "libffi", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libffi-win": { - "type": "library", + "artifact": "libffi-win", "headers@windows": [ "ffi.h", "ffitarget.h", "fficonfig.h" ], - "artifact": "libffi-win", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libheif": { - "type": "library", + "artifact": "libheif", "depends": [ "libde265", "libwebp", @@ -398,113 +398,121 @@ "zlib", "brotli" ], - "artifact": "libheif", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "libiconv": { - "type": "library", + "artifact": "libiconv", "headers": [ "iconv.h", "libcharset.h", "localcharset.h" ], - "artifact": "libiconv", "license": { "type": "file", "path": "COPYING.LIB" - } + }, + "type": "library" }, "libiconv-win": { - "type": "library", "artifact": "libiconv-win", "license": { "type": "file", "path": "source/COPYING" - } + }, + "type": "library" }, "libjpeg": { - "type": "library", - "suggests@windows": [ - "zlib" - ], "artifact": "libjpeg", "license": { "type": "file", "path": "LICENSE.md" - } + }, + "suggests@windows": [ + "zlib" + ], + "type": "library" }, "libjxl": { - "type": "library", + "artifact": "libjxl", "depends": [ "brotli", "libjpeg", "libpng", "libwebp" ], + "license": { + "type": "file", + "path": "LICENSE" + }, "pkg-configs": [ "libjxl", "libjxl_cms", "libjxl_threads", "libhwy" ], - "artifact": "libjxl", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "liblz4": { - "type": "library", "artifact": "liblz4", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libmemcached": { - "type": "library", "artifact": "libmemcached", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libpng": { - "type": "library", + "artifact": "libpng", "depends": [ "zlib" ], - "headers@windows": [ - "png.h", - "pngconf.h" - ], "headers": [ "png.h", "pngconf.h", "pnglibconf.h" ], - "artifact": "libpng", + "headers@windows": [ + "png.h", + "pngconf.h" + ], "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "librabbitmq": { - "type": "library", + "artifact": "librabbitmq", "depends": [ "openssl" ], - "artifact": "librabbitmq", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "librdkafka": { - "type": "library", + "artifact": "librdkafka", + "license": { + "type": "file", + "path": "LICENSE" + }, + "pkg-configs": [ + "rdkafka++-static", + "rdkafka-static" + ], "suggests": [ "curl", "liblz4", @@ -512,26 +520,18 @@ "zlib", "zstd" ], - "pkg-configs": [ - "rdkafka++-static", - "rdkafka-static" - ], - "artifact": "librdkafka", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "libsodium": { - "type": "library", "artifact": "libsodium", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "libssh2": { - "type": "library", + "artifact": "libssh2", "depends": [ "openssl" ], @@ -540,18 +540,22 @@ "libssh2_publickey.h", "libssh2_sftp.h" ], - "artifact": "libssh2", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "libtiff": { - "type": "library", + "artifact": "libtiff", "depends": [ "zlib", "libjpeg" ], + "license": { + "type": "file", + "path": "LICENSE.md" + }, "suggests": [ "lerc", "libwebp", @@ -559,41 +563,36 @@ "xz", "zstd" ], - "artifact": "libtiff", - "license": { - "type": "file", - "path": "LICENSE.md" - } + "type": "library" }, "liburing": { - "type": "library", + "artifact": "liburing", "headers@linux": [ "liburing/", "liburing.h" ], + "license": { + "type": "file", + "path": "COPYING" + }, "pkg-configs": [ "liburing", "liburing-ffi" ], - "artifact": "liburing", - "license": { - "type": "file", - "path": "COPYING" - } + "type": "library" }, "libuuid": { - "type": "library", + "artifact": "libuuid", "headers": [ "uuid/uuid.h" ], - "artifact": "libuuid", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "libuv": { - "type": "library", "artifact": "libuv", "license": [ { @@ -604,10 +603,15 @@ "type": "file", "path": "LICENSE-extra" } - ] + ], + "type": "library" }, "libwebp": { - "type": "library", + "artifact": "libwebp", + "license": { + "type": "file", + "path": "COPYING" + }, "pkg-configs": [ "libwebp", "libwebpdecoder", @@ -615,206 +619,202 @@ "libwebpmux", "libsharpyuv" ], - "artifact": "libwebp", - "license": { - "type": "file", - "path": "COPYING" - } + "type": "library" }, "libxml2": { - "type": "library", - "depends@windows": [ - "libiconv-win" - ], + "artifact": "libxml2", "depends": [ "libiconv" ], - "suggests@windows": [ - "zlib" + "depends@windows": [ + "libiconv-win" + ], + "headers": [ + "libxml2" + ], + "license": { + "type": "file", + "path": "Copyright" + }, + "pkg-configs": [ + "libxml-2.0" ], "suggests": [ "xz", "zlib" ], - "headers": [ - "libxml2" + "suggests@windows": [ + "zlib" ], - "pkg-configs": [ - "libxml-2.0" - ], - "artifact": "libxml2", - "license": { - "type": "file", - "path": "Copyright" - } + "type": "library" }, "libxslt": { - "type": "library", + "artifact": "libxslt", "depends": [ "libxml2" ], - "artifact": "libxslt", "license": { "type": "file", "path": "Copyright" - } + }, + "type": "library" }, "libyaml": { - "type": "library", + "artifact": "libyaml", "headers": [ "yaml.h" ], - "artifact": "libyaml", "license": { "type": "file", "path": "License" - } + }, + "type": "library" }, "libzip": { - "type": "library", + "artifact": "libzip", + "depends": [ + "zlib" + ], "depends@windows": [ "zlib", "bzip2", "xz" ], - "depends": [ - "zlib" - ], - "suggests@windows": [ - "zstd", - "openssl" + "headers": [ + "zip.h", + "zipconf.h" ], + "license": { + "type": "file", + "path": "LICENSE" + }, "suggests": [ "bzip2", "xz", "zstd", "openssl" ], - "headers": [ - "zip.h", - "zipconf.h" + "suggests@windows": [ + "zstd", + "openssl" ], - "artifact": "libzip", - "license": { - "type": "file", - "path": "LICENSE" - } + "type": "library" }, "mimalloc": { - "type": "library", "artifact": "mimalloc", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "ncurses": { - "type": "library", "artifact": "ncurses", - "static-libs@unix": [ - "libncurses.a" - ], "license": { "type": "file", "path": "COPYING" - } + }, + "static-libs@unix": [ + "libncurses.a" + ], + "type": "library" }, "net-snmp": { - "type": "library", + "artifact": "net-snmp", "depends": [ "openssl", "zlib" ], + "license": { + "type": "file", + "path": "COPYING" + }, "pkg-configs": [ "netsnmp", "netsnmp-agent" ], - "artifact": "net-snmp", - "license": { - "type": "file", - "path": "COPYING" - } + "type": "library" }, "nghttp2": { - "type": "library", + "artifact": "nghttp2", "depends": [ "zlib", "openssl" ], + "headers": [ + "nghttp2" + ], + "license": { + "type": "file", + "path": "COPYING" + }, "suggests": [ "libxml2", "nghttp3", "ngtcp2" ], - "headers": [ - "nghttp2" - ], - "artifact": "nghttp2", - "license": { - "type": "file", - "path": "COPYING" - } + "type": "library" }, "nghttp3": { - "type": "library", + "artifact": "nghttp3", "depends": [ "openssl" ], "headers": [ "nghttp3" ], - "artifact": "nghttp3", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "ngtcp2": { - "type": "library", + "artifact": "ngtcp2", "depends": [ "openssl" ], - "suggests": [ - "nghttp3", - "brotli" - ], "headers": [ "ngtcp2" ], - "artifact": "ngtcp2", "license": { "type": "file", "path": "COPYING" - } + }, + "suggests": [ + "nghttp3", + "brotli" + ], + "type": "library" }, "onig": { - "type": "library", + "artifact": "onig", "headers": [ "oniggnu.h", "oniguruma.h" ], - "artifact": "onig", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "openssl": { - "type": "library", + "artifact": "openssl", "depends": [ "zlib" ], "headers": [ "openssl" ], - "artifact": "openssl", "license": { "type": "file", "path": "LICENSE.txt" - } + }, + "type": "library" }, "postgresql": { - "type": "library", + "artifact": "postgresql", "depends": [ "libiconv", "libxml2", @@ -822,69 +822,69 @@ "zlib", "libedit" ], + "license": { + "type": "file", + "path": "COPYRIGHT" + }, + "pkg-configs": [ + "libpq" + ], "suggests": [ "icu", "libxslt", "ldap", "zstd" ], - "pkg-configs": [ - "libpq" - ], - "artifact": "postgresql", - "license": { - "type": "file", - "path": "COPYRIGHT" - } + "type": "library" }, "postgresql-win": { - "type": "library", "artifact": "postgresql-win", "license": { "type": "text", "text": "PostgreSQL Database Management System\n(also known as Postgres, formerly as Postgres95)\n\nPortions Copyright (c) 1996-2025, The PostgreSQL Global Development Group\n\nPortions Copyright (c) 1994, The Regents of the University of California\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose, without fee, and without a written\nagreement is hereby granted, provided that the above copyright notice\nand this paragraph and the following two paragraphs appear in all\ncopies.\n\nIN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY\nFOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,\nINCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS\nDOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF\nTHE POSSIBILITY OF SUCH DAMAGE.\n\nTHE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\nON AN \"AS IS\" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS\nTO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - } + }, + "type": "library" }, "pthreads4w": { - "type": "library", "artifact": "pthreads4w", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "qdbm": { - "type": "library", + "artifact": "qdbm", "headers@windows": [ "depot.h" ], - "artifact": "qdbm", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "re2c": { - "type": "library", "artifact": "re2c", "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" }, "readline": { - "type": "library", + "artifact": "readline", "depends": [ "ncurses" ], - "artifact": "readline", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "snappy": { - "type": "library", + "artifact": "snappy", "depends": [ "zlib" ], @@ -894,99 +894,99 @@ "snappy-sinksource.h", "snappy-stubs-public.h" ], - "artifact": "snappy", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "sqlite": { - "type": "library", + "artifact": "sqlite", "headers": [ "sqlite3.h", "sqlite3ext.h" ], - "artifact": "sqlite", "license": { "type": "text", "text": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give." - } + }, + "type": "library" }, "tidy": { - "type": "library", "artifact": "tidy", "license": { "type": "file", "path": "README/LICENSE.md" - } + }, + "type": "library" }, "unixodbc": { - "type": "library", + "artifact": "unixodbc", "depends": [ "libiconv" ], - "artifact": "unixodbc", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "watcher": { - "type": "library", + "artifact": "watcher", "headers": [ "wtr/watcher-c.h" ], - "artifact": "watcher", "license": { "type": "file", "path": "license" - } + }, + "type": "library" }, "xz": { - "type": "library", + "artifact": "xz", "depends": [ "libiconv" ], + "headers": [ + "lzma" + ], "headers@windows": [ "lzma", "lzma.h" ], - "headers": [ - "lzma" - ], - "artifact": "xz", "license": { "type": "file", "path": "COPYING" - } + }, + "type": "library" }, "zlib": { - "type": "library", + "artifact": "zlib", "headers": [ "zlib.h", "zconf.h" ], - "artifact": "zlib", "license": { "type": "text", "text": "(C) 1995-2022 Jean-loup Gailly and Mark Adler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n claim that you wrote the original software. If you use this software\n in a product, an acknowledgment in the product documentation would be\n appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n\nJean-loup Gailly Mark Adler\njloup@gzip.org madler@alumni.caltech.edu" - } + }, + "type": "library" }, "zstd": { - "type": "library", - "headers@windows": [ - "zstd.h", - "zstd_errors.h" - ], + "artifact": "zstd", "headers": [ "zdict.h", "zstd.h", "zstd_errors.h" ], - "artifact": "zstd", + "headers@windows": [ + "zstd.h", + "zstd_errors.h" + ], "license": { "type": "file", "path": "LICENSE" - } + }, + "type": "library" } } diff --git a/config/pkg.target.json b/config/pkg.target.json index 2ae49f40..8e04df90 100644 --- a/config/pkg.target.json +++ b/config/pkg.target.json @@ -1,58 +1,5 @@ { - "vswhere": { - "type": "target", - "artifact": "vswhere", - "static-bins@windows": [ - "vswhere.exe" - ] - }, - "pkg-config": { - "type": "target", - "static-bins": [ - "pkg-config" - ], - "artifact": "pkg-config" - }, - "php": { - "type": "target", - "artifact": "php-src", - "depends@macos": [ - "libxml2" - ] - }, - "php-cli": { - "type": "virtual-target", - "depends": [ - "php" - ] - }, - "php-micro": { - "type": "virtual-target", - "artifact": "micro", - "depends": [ - "php" - ] - }, - "php-cgi": { - "type": "virtual-target", - "depends": [ - "php" - ] - }, - "php-fpm": { - "type": "virtual-target", - "depends": [ - "php" - ] - }, - "php-embed": { - "type": "virtual-target", - "depends": [ - "php" - ] - }, "frankenphp": { - "type": "virtual-target", "artifact": "frankenphp", "depends": [ "php-embed", @@ -62,37 +9,90 @@ "php-embed", "go-xcaddy", "libxml2" - ] + ], + "type": "virtual-target" }, "go-xcaddy": { - "type": "target", "artifact": "go-xcaddy", "static-bins": [ "xcaddy" - ] + ], + "type": "target" }, "musl-toolchain": { - "type": "target", - "artifact": "musl-toolchain" - }, - "strawberry-perl": { - "type": "target", - "artifact": "strawberry-perl" - }, - "upx": { - "type": "target", - "artifact": "upx" - }, - "zig": { - "type": "target", - "artifact": "zig" + "artifact": "musl-toolchain", + "type": "target" }, "nasm": { - "type": "target", - "artifact": "nasm" + "artifact": "nasm", + "type": "target" + }, + "php": { + "artifact": "php-src", + "depends@macos": [ + "libxml2" + ], + "type": "target" + }, + "php-cgi": { + "depends": [ + "php" + ], + "type": "virtual-target" + }, + "php-cli": { + "depends": [ + "php" + ], + "type": "virtual-target" + }, + "php-embed": { + "depends": [ + "php" + ], + "type": "virtual-target" + }, + "php-fpm": { + "depends": [ + "php" + ], + "type": "virtual-target" + }, + "php-micro": { + "artifact": "micro", + "depends": [ + "php" + ], + "type": "virtual-target" }, "php-sdk-binary-tools": { - "type": "target", - "artifact": "php-sdk-binary-tools" + "artifact": "php-sdk-binary-tools", + "type": "target" + }, + "pkg-config": { + "artifact": "pkg-config", + "static-bins": [ + "pkg-config" + ], + "type": "target" + }, + "strawberry-perl": { + "artifact": "strawberry-perl", + "type": "target" + }, + "upx": { + "artifact": "upx", + "type": "target" + }, + "vswhere": { + "artifact": "vswhere", + "static-bins@windows": [ + "vswhere.exe" + ], + "type": "target" + }, + "zig": { + "artifact": "zig", + "type": "target" } } diff --git a/config/source.json b/config/source.json index 9a80cd05..03626015 100644 --- a/config/source.json +++ b/config/source.json @@ -126,13 +126,23 @@ }, "ext-event": { "type": "url", - "url": "https://bitbucket.org/osmanov/pecl-event/get/3.0.8.tar.gz", + "url": "https://bitbucket.org/osmanov/pecl-event/get/3.1.4.tar.gz", "path": "php-src/ext/event", "license": { "type": "file", "path": "LICENSE" } }, + "ext-excimer": { + "type": "url", + "url": "https://pecl.php.net/get/excimer", + "path": "php-src/ext/excimer", + "filename": "excimer.tgz", + "license": { + "type": "file", + "path": "LICENSE" + } + }, "ext-glfw": { "type": "git", "url": "https://github.com/mario-deluna/php-glfw", @@ -151,6 +161,18 @@ "path": "LICENSE" } }, + "ext-grpc": { + "type": "url", + "url": "https://pecl.php.net/get/grpc", + "path": "php-src/ext/grpc", + "filename": "grpc.tgz", + "license": { + "type": "file", + "path": [ + "LICENSE" + ] + } + }, "ext-imagick": { "type": "url", "url": "https://pecl.php.net/get/imagick", @@ -670,9 +692,10 @@ } }, "libpng": { - "type": "git", - "url": "https://github.com/glennrp/libpng.git", - "rev": "libpng16", + "type": "ghtagtar", + "repo": "pnggroup/libpng", + "match": "v1\\.6\\.\\d+", + "query": "?per_page=150", "provide-pre-built": true, "license": { "type": "file", @@ -680,9 +703,9 @@ } }, "librabbitmq": { - "type": "git", - "url": "https://github.com/alanxz/rabbitmq-c.git", - "rev": "master", + "type": "ghtar", + "repo": "alanxz/rabbitmq-c", + "prefer-stable": true, "license": { "type": "file", "path": "LICENSE" @@ -699,7 +722,7 @@ "libsodium": { "type": "ghrel", "repo": "jedisct1/libsodium", - "match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz", + "match": "libsodium-(?!1\\.0\\.21)\\d+(\\.\\d+)*\\.tar\\.gz", "prefer-stable": true, "provide-pre-built": true, "license": { @@ -771,8 +794,9 @@ ] }, "libwebp": { - "type": "url", - "url": "https://github.com/webmproject/libwebp/archive/refs/tags/v1.3.2.tar.gz", + "type": "ghtagtar", + "repo": "webmproject/libwebp", + "match": "v1\\.\\d+\\.\\d+$", "provide-pre-built": true, "license": { "type": "file", @@ -780,8 +804,10 @@ } }, "libxml2": { - "type": "url", - "url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.12.5.tar.gz", + "type": "ghtagtar", + "repo": "GNOME/libxml2", + "match": "v2\\.\\d+\\.\\d+$", + "provide-pre-built": false, "license": { "type": "file", "path": "Copyright" @@ -868,6 +894,24 @@ "path": "LICENSE" } }, + "mysqlnd_ed25519": { + "type": "pie", + "repo": "mariadb/mysqlnd_ed25519", + "path": "php-src/ext/mysqlnd_ed25519", + "license": { + "type": "file", + "path": "LICENSE" + } + }, + "mysqlnd_parsec": { + "type": "pie", + "repo": "mariadb/mysqlnd_parsec", + "path": "php-src/ext/mysqlnd_parsec", + "license": { + "type": "file", + "path": "LICENSE" + } + }, "ncurses": { "type": "filelist", "url": "https://ftp.gnu.org/pub/gnu/ncurses/", @@ -1169,9 +1213,8 @@ } }, "xdebug": { - "type": "url", - "url": "https://pecl.php.net/get/xdebug", - "filename": "xdebug.tgz", + "type": "pie", + "repo": "xdebug/xdebug", "license": { "type": "file", "path": "LICENSE" diff --git a/docs/en/guide/manual-build.md b/docs/en/guide/manual-build.md index 28f0ec87..319022ca 100644 --- a/docs/en/guide/manual-build.md +++ b/docs/en/guide/manual-build.md @@ -549,22 +549,24 @@ otherwise it will be executed repeatedly in other events. The following are the supported `patch_point` event names and corresponding locations: -| Event name | Event description | -|------------------------------|----------------------------------------------------------------------------------------------------| -| before-libs-extract | Triggered before the dependent libraries extracted | -| after-libs-extract | Triggered after the compiled dependent libraries extracted | -| before-php-extract | Triggered before PHP source code extracted | -| after-php-extract | Triggered after PHP source code extracted | -| before-micro-extract | Triggered before phpmicro extract | -| after-micro-extract | Triggered after phpmicro extracted | -| before-exts-extract | Triggered before the extension (to be compiled) extracted to the PHP source directory | -| after-exts-extract | Triggered after the extension extracted to the PHP source directory | -| before-library[*name*]-build | Triggered before the library named `name` is compiled (such as `before-library[postgresql]-build`) | -| after-library[*name*]-build | Triggered after the library named `name` is compiled | -| before-php-buildconf | Triggered before compiling PHP command `./buildconf` | -| before-php-configure | Triggered before compiling PHP command `./configure` | -| before-php-make | Triggered before compiling PHP command `make` | -| before-sanity-check | Triggered after compiling PHP but before running extended checks | +| Event name | Event description | +|---------------------------------|----------------------------------------------------------------------------------------------------| +| before-libs-extract | Triggered before the dependent libraries extracted | +| after-libs-extract | Triggered after the compiled dependent libraries extracted | +| before-php-extract | Triggered before PHP source code extracted | +| after-php-extract | Triggered after PHP source code extracted | +| before-micro-extract | Triggered before phpmicro extract | +| after-micro-extract | Triggered after phpmicro extracted | +| before-exts-extract | Triggered before the extension (to be compiled) extracted to the PHP source directory | +| after-exts-extract | Triggered after the extension extracted to the PHP source directory | +| before-library[*name*]-build | Triggered before the library named `name` is compiled (such as `before-library[postgresql]-build`) | +| after-library[*name*]-build | Triggered after the library named `name` is compiled | +| after-shared-ext[*name*]-build | Triggered after the shared extension named `name` is compiled | +| before-shared-ext[*name*]-build | Triggered before the shared extension named `name` is compiled | +| before-php-buildconf | Triggered before compiling PHP command `./buildconf` | +| before-php-configure | Triggered before compiling PHP command `./configure` | +| before-php-make | Triggered before compiling PHP command `make` | +| before-sanity-check | Triggered after compiling PHP but before running extended checks | The following is a simple example of temporarily modifying the PHP source code. Enable the CLI function to search for the `php.ini` configuration in the current working directory: diff --git a/docs/zh/guide/manual-build.md b/docs/zh/guide/manual-build.md index 4c24cab8..d7745a02 100644 --- a/docs/zh/guide/manual-build.md +++ b/docs/zh/guide/manual-build.md @@ -500,6 +500,8 @@ bin/spc dev:sort-config ext | after-exts-extract | 在要编译的扩展解压到 PHP 源码目录后触发 | | before-library[*name*]-build | 在名称为 `name` 的库编译前触发(如 `before-library[postgresql]-build`) | | after-library[*name*]-build | 在名称为 `name` 的库编译后触发 | +| after-shared-ext[*name*]-build | 在名称为 `name` 的共享扩展编译后触发(如 `after-shared-ext[redis]-build`) | +| before-shared-ext[*name*]-build | 在名称为 `name` 的共享扩展编译前触发 | | before-php-buildconf | 在编译 PHP 命令 `./buildconf` 前触发 | | before-php-configure | 在编译 PHP 命令 `./configure` 前触发 | | before-php-make | 在编译 PHP 命令 `make` 前触发 | diff --git a/phpstan.neon b/phpstan.neon index cf6e4974..45e512ba 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,7 @@ parameters: reportUnmatchedIgnoredErrors: false level: 4 + phpVersion: 80400 paths: - ./src/ ignoreErrors: diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index 414c3bde..19fdd41d 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -34,7 +34,7 @@ use Symfony\Component\Console\Application; */ final class ConsoleApplication extends Application { - public const string VERSION = '3.0.0-dev'; + public const string VERSION = '2.8.0'; public function __construct() { diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 08b403e6..925a4c8e 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -385,6 +385,9 @@ class Extension logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)'); return; } + if ((string) Config::getExt($this->getName(), 'type') === 'addon') { + return; + } logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)'); foreach ($this->dependencies as $dependency) { if (!$dependency instanceof Extension) { @@ -395,13 +398,12 @@ class Extension $dependency->buildShared([...$visited, $this->getName()]); } } - if (Config::getExt($this->getName(), 'type') === 'addon') { - return; - } + $this->builder->emitPatchPoint('before-shared-ext[' . $this->getName() . ']-build'); match (PHP_OS_FAMILY) { 'Darwin', 'Linux' => $this->buildUnixShared(), default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'), }; + $this->builder->emitPatchPoint('after-shared-ext[' . $this->getName() . ']-build'); } catch (SPCException $e) { $e->bindExtensionInfo(['extension_name' => $this->getName()]); throw $e; @@ -452,12 +454,17 @@ class Extension // process *.so file $soFile = BUILD_MODULES_PATH . '/' . $this->getName() . '.so'; + $soDest = $soFile; + preg_match('/-release\s+(\S*)/', getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), $matches); + if (!empty($matches[1])) { + $soDest = str_replace('.so', '-' . $matches[1] . '.so', $soFile); + } if (!file_exists($soFile)) { throw new ValidationException("extension {$this->getName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getName()} build"); } /** @var UnixBuilderBase $builder */ $builder = $this->builder; - $builder->deployBinary($soFile, $soFile, false); + $builder->deployBinary($soFile, $soDest, false); } /** @@ -543,6 +550,7 @@ class Extension 'CFLAGS' => $config['cflags'], 'CXXFLAGS' => $config['cflags'], 'LDFLAGS' => $config['ldflags'], + 'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), 'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"), 'LD_LIBRARY_PATH' => BUILD_LIB_PATH, ]; diff --git a/src/SPC/builder/LibraryBase.php b/src/SPC/builder/LibraryBase.php index c88e8d96..383faa41 100644 --- a/src/SPC/builder/LibraryBase.php +++ b/src/SPC/builder/LibraryBase.php @@ -184,18 +184,18 @@ abstract class LibraryBase // extract first if not exists if (!is_dir($this->source_dir)) { - $this->getBuilder()->emitPatchPoint('before-library[ ' . static::NAME . ']-extract'); + $this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-extract'); SourceManager::initSource(libs: [static::NAME], source_only: true); - $this->getBuilder()->emitPatchPoint('after-library[ ' . static::NAME . ']-extract'); + $this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-extract'); } if (!$this->patched && $this->patchBeforeBuild()) { file_put_contents($this->source_dir . '/.spc.patched', 'PATCHED!!!'); } - $this->getBuilder()->emitPatchPoint('before-library[ ' . static::NAME . ']-build'); + $this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-build'); $this->build(); $this->installLicense(); - $this->getBuilder()->emitPatchPoint('after-library[ ' . static::NAME . ']-build'); + $this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-build'); return LIB_STATUS_OK; } @@ -346,19 +346,19 @@ abstract class LibraryBase */ protected function installLicense(): void { - FileSystem::createDir(BUILD_ROOT_PATH . '/source-licenses/' . $this->getName()); $source = Config::getLib($this->getName(), 'source'); + FileSystem::createDir(BUILD_ROOT_PATH . "/source-licenses/{$source}"); $license_files = Config::getSource($source)['license'] ?? []; if (is_assoc_array($license_files)) { $license_files = [$license_files]; } foreach ($license_files as $index => $license) { if ($license['type'] === 'text') { - FileSystem::writeFile(BUILD_ROOT_PATH . '/source-licenses/' . $this->getName() . "/{$index}.txt", $license['text']); + FileSystem::writeFile(BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt", $license['text']); continue; } if ($license['type'] === 'file') { - copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . '/source-licenses/' . $this->getName() . "/{$index}.txt"); + copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt"); } } } @@ -375,8 +375,17 @@ abstract class LibraryBase return false; } } + $pkg_config_path = getenv('PKG_CONFIG_PATH') ?: ''; + $search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)); foreach (Config::getLib(static::NAME, 'pkg-configs', []) as $name) { - if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$name}.pc")) { + $found = false; + foreach ($search_paths as $path) { + if (file_exists($path . "/{$name}.pc")) { + $found = true; + break; + } + } + if (!$found) { return false; } } diff --git a/src/SPC/builder/extension/excimer.php b/src/SPC/builder/extension/excimer.php new file mode 100644 index 00000000..03dd8f22 --- /dev/null +++ b/src/SPC/builder/extension/excimer.php @@ -0,0 +1,19 @@ +builder instanceof WindowsBuilder) { throw new ValidationException('grpc extension does not support windows yet'); } - if (file_exists(SOURCE_PATH . '/php-src/ext/grpc')) { - return false; - } - // soft link to the grpc source code - if (is_dir($this->source_dir . '/src/php/ext/grpc')) { - shell()->exec('ln -s ' . $this->source_dir . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc'); - } else { - throw new ValidationException('Cannot find grpc source code in ' . $this->source_dir . '/src/php/ext/grpc'); - } + FileSystem::replaceFileStr( + $this->source_dir . '/src/php/ext/grpc/call.c', + 'zend_exception_get_default(TSRMLS_C),', + 'zend_ce_exception,', + ); if (SPCTarget::getTargetOS() === 'Darwin') { FileSystem::replaceFileRegex( - SOURCE_PATH . '/php-src/ext/grpc/config.m4', + $this->source_dir . '/config.m4', '/GRPC_LIBDIR=.*$/m', 'GRPC_LIBDIR=' . BUILD_LIB_PATH . "\n" . 'LDFLAGS="$LDFLAGS -framework CoreFoundation"' ); diff --git a/src/SPC/builder/extension/imagick.php b/src/SPC/builder/extension/imagick.php index bef772ee..a548a8a3 100644 --- a/src/SPC/builder/extension/imagick.php +++ b/src/SPC/builder/extension/imagick.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace SPC\builder\extension; use SPC\builder\Extension; +use SPC\toolchain\ToolchainManager; +use SPC\toolchain\ZigToolchain; use SPC\util\CustomExt; #[CustomExt('imagick')] @@ -19,7 +21,9 @@ class imagick extends Extension protected function splitLibsIntoStaticAndShared(string $allLibs): array { [$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs); - if (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) { + if (ToolchainManager::getToolchainClass() !== ZigToolchain::class && + (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) + ) { $static .= ' -l:libstdc++.a'; $shared = str_replace('-lstdc++', '', $shared); } diff --git a/src/SPC/builder/extension/memcache.php b/src/SPC/builder/extension/memcache.php index b63fa47a..32cb301c 100644 --- a/src/SPC/builder/extension/memcache.php +++ b/src/SPC/builder/extension/memcache.php @@ -18,6 +18,9 @@ class memcache extends Extension public function patchBeforeBuildconf(): bool { + if (!$this->isBuildStatic()) { + return false; + } FileSystem::replaceFileStr( SOURCE_PATH . '/php-src/ext/memcache/config9.m4', 'if test -d $abs_srcdir/src ; then', @@ -43,4 +46,27 @@ EOF ); return true; } + + public function patchBeforeSharedConfigure(): bool + { + if (!$this->isBuildShared()) { + return false; + } + FileSystem::replaceFileStr( + SOURCE_PATH . '/php-src/ext/memcache/config9.m4', + 'if test -d $abs_srcdir/main ; then', + 'if test -d $abs_srcdir/src ; then', + ); + FileSystem::replaceFileStr( + SOURCE_PATH . '/php-src/ext/memcache/config9.m4', + 'export CPPFLAGS="$CPPFLAGS $INCLUDES -I$abs_srcdir/main"', + 'export CPPFLAGS="$CPPFLAGS $INCLUDES"', + ); + return true; + } + + protected function getExtraEnv(): array + { + return ['CFLAGS' => '-std=c17']; + } } diff --git a/src/SPC/builder/extension/mongodb.php b/src/SPC/builder/extension/mongodb.php index 745417bb..08861e4e 100644 --- a/src/SPC/builder/extension/mongodb.php +++ b/src/SPC/builder/extension/mongodb.php @@ -24,4 +24,9 @@ class mongodb extends Extension $arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled '; return clean_spaces($arg); } + + public function getExtraEnv(): array + { + return ['CFLAGS' => '-std=c17']; + } } diff --git a/src/SPC/builder/extension/mysqlnd_ed25519.php b/src/SPC/builder/extension/mysqlnd_ed25519.php new file mode 100644 index 00000000..7b2b4abc --- /dev/null +++ b/src/SPC/builder/extension/mysqlnd_ed25519.php @@ -0,0 +1,22 @@ +getConfigureArg(); + } +} diff --git a/src/SPC/builder/extension/mysqlnd_parsec.php b/src/SPC/builder/extension/mysqlnd_parsec.php new file mode 100644 index 00000000..d044b1c5 --- /dev/null +++ b/src/SPC/builder/extension/mysqlnd_parsec.php @@ -0,0 +1,22 @@ +getConfigureArg(); + } +} diff --git a/src/SPC/builder/extension/password_argon2.php b/src/SPC/builder/extension/password_argon2.php index 30e6fd2c..d42fe4e3 100644 --- a/src/SPC/builder/extension/password_argon2.php +++ b/src/SPC/builder/extension/password_argon2.php @@ -24,25 +24,6 @@ class password_argon2 extends Extension } } - public function patchBeforeMake(): bool - { - $patched = parent::patchBeforeMake(); - if ($this->builder->getLib('libsodium') !== null) { - $extraLibs = getenv('SPC_EXTRA_LIBS'); - if ($extraLibs !== false) { - $extraLibs = str_replace( - [BUILD_LIB_PATH . '/libargon2.a', BUILD_LIB_PATH . '/libsodium.a'], - ['', BUILD_LIB_PATH . '/libargon2.a ' . BUILD_LIB_PATH . '/libsodium.a'], - $extraLibs, - ); - $extraLibs = trim(preg_replace('/\s+/', ' ', $extraLibs)); // normalize spacing - f_putenv('SPC_EXTRA_LIBS=' . $extraLibs); - return true; - } - } - return $patched; - } - public function getConfigureArg(bool $shared = false): string { if ($this->builder->getLib('openssl') !== null) { diff --git a/src/SPC/builder/extension/pgsql.php b/src/SPC/builder/extension/pgsql.php index f22f7ba6..06efa8b1 100644 --- a/src/SPC/builder/extension/pgsql.php +++ b/src/SPC/builder/extension/pgsql.php @@ -45,7 +45,7 @@ class pgsql extends Extension protected function getExtraEnv(): array { return [ - 'CFLAGS' => '-Wno-int-conversion', + 'CFLAGS' => '-std=c17 -Wno-int-conversion', ]; } } diff --git a/src/SPC/builder/extension/swoole.php b/src/SPC/builder/extension/swoole.php index f6ff5931..4e292a36 100644 --- a/src/SPC/builder/extension/swoole.php +++ b/src/SPC/builder/extension/swoole.php @@ -17,6 +17,7 @@ class swoole extends Extension public function patchBeforeMake(): bool { $patched = parent::patchBeforeMake(); + FileSystem::replaceFileStr($this->source_dir . '/ext-src/php_swoole_private.h', 'PHP_VERSION_ID > 80500', 'PHP_VERSION_ID >= 80600'); if ($this->builder instanceof MacOSBuilder) { // Fix swoole with event extension conflict bug $util_path = shell()->execWithResult('xcrun --show-sdk-path', false)[1][0] . '/usr/include/util.h'; diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 0d6f77fb..004c37de 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -283,11 +283,14 @@ class LinuxBuilder extends UnixBuilderBase // process libphp.so for shared embed $libphpSo = BUILD_LIB_PATH . '/libphp.so'; + $libphpSoDest = BUILD_LIB_PATH . '/libphp.so'; if (file_exists($libphpSo)) { - // post actions: rename libphp.so to libphp-.so if -release is set in LDFLAGS - $this->processLibphpSoFile($libphpSo); // deploy libphp.so - $this->deployBinary($libphpSo, $libphpSo, false); + preg_match('/-release\s+(\S*)/', getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), $matches); + if (!empty($matches[1])) { + $libphpSoDest = str_replace('.so', '-' . $matches[1] . '.so', $libphpSo); + } + $this->deployBinary($libphpSo, $libphpSoDest, false); } // process shared extensions build-with-php @@ -324,74 +327,6 @@ class LinuxBuilder extends UnixBuilderBase ]); } - private function processLibphpSoFile(string $libphpSo): void - { - $ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: ''; - $libDir = BUILD_LIB_PATH; - $modulesDir = BUILD_MODULES_PATH; - $realLibName = 'libphp.so'; - $cwd = getcwd(); - - if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) { - $release = $matches[1]; - $realLibName = "libphp-{$release}.so"; - $libphpRelease = "{$libDir}/{$realLibName}"; - if (!file_exists($libphpRelease) && file_exists($libphpSo)) { - rename($libphpSo, $libphpRelease); - } - if (file_exists($libphpRelease)) { - chdir($libDir); - if (file_exists($libphpSo)) { - unlink($libphpSo); - } - symlink($realLibName, 'libphp.so'); - shell()->exec(sprintf( - 'patchelf --set-soname %s %s', - escapeshellarg($realLibName), - escapeshellarg($libphpRelease) - )); - } - if (is_dir($modulesDir)) { - chdir($modulesDir); - foreach ($this->getExts() as $ext) { - if (!$ext->isBuildShared()) { - continue; - } - $name = $ext->getName(); - $versioned = "{$name}-{$release}.so"; - $unversioned = "{$name}.so"; - $src = "{$modulesDir}/{$versioned}"; - $dst = "{$modulesDir}/{$unversioned}"; - if (is_file($src)) { - rename($src, $dst); - shell()->exec(sprintf( - 'patchelf --set-soname %s %s', - escapeshellarg($unversioned), - escapeshellarg($dst) - )); - } - } - } - chdir($cwd); - } - - $target = "{$libDir}/{$realLibName}"; - if (file_exists($target)) { - [, $output] = shell()->execWithResult('readelf -d ' . escapeshellarg($target)); - $output = implode("\n", $output); - if (preg_match('/SONAME.*\[(.+)]/', $output, $sonameMatch)) { - $currentSoname = $sonameMatch[1]; - if ($currentSoname !== basename($target)) { - shell()->exec(sprintf( - 'patchelf --set-soname %s %s', - escapeshellarg(basename($target)), - escapeshellarg($target) - )); - } - } - } - } - /** * Patch micro.sfx after UPX compression. * micro needs special section handling in LinuxBuilder. diff --git a/src/SPC/builder/linux/library/liburing.php b/src/SPC/builder/linux/library/liburing.php index 82249cf8..9a67f50c 100644 --- a/src/SPC/builder/linux/library/liburing.php +++ b/src/SPC/builder/linux/library/liburing.php @@ -6,6 +6,8 @@ namespace SPC\builder\linux\library; use SPC\builder\linux\SystemUtil; use SPC\store\FileSystem; +use SPC\toolchain\GccNativeToolchain; +use SPC\toolchain\ToolchainManager; use SPC\util\executor\UnixAutoconfExecutor; use SPC\util\SPCTarget; @@ -15,26 +17,19 @@ class liburing extends LinuxLibraryBase public function patchBeforeBuild(): bool { - if (!SystemUtil::isMuslDist()) { - return false; + if (SystemUtil::isMuslDist()) { + FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath'); + return true; } - FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath'); - return true; + return false; } protected function build(): void { - $use_libc = SPCTarget::getLibc() !== 'glibc' || version_compare(SPCTarget::getLibcVersion(), '2.30', '>='); + $use_libc = ToolchainManager::getToolchainClass() !== GccNativeToolchain::class || version_compare(SPCTarget::getLibcVersion(), '2.30', '>='); $make = UnixAutoconfExecutor::create($this); - if (!$use_libc) { - $make->appendEnv([ - 'CC' => 'gcc', // libc-less version fails to compile with clang or zig - 'CXX' => 'g++', - 'AR' => 'ar', - 'LD' => 'ld', - ]); - } else { + if ($use_libc) { $make->appendEnv([ 'CFLAGS' => '-D_GNU_SOURCE', ]); @@ -51,7 +46,7 @@ class liburing extends LinuxLibraryBase $use_libc ? '--use-libc' : '', ) ->configure() - ->make('library', 'install ENABLE_SHARED=0', with_clean: false); + ->make('library ENABLE_SHARED=0', 'install ENABLE_SHARED=0', with_clean: false); $this->patchPkgconfPrefix(); } diff --git a/src/SPC/builder/linux/library/openssl.php b/src/SPC/builder/linux/library/openssl.php index d9e04b32..bfc3936b 100644 --- a/src/SPC/builder/linux/library/openssl.php +++ b/src/SPC/builder/linux/library/openssl.php @@ -21,6 +21,7 @@ declare(strict_types=1); namespace SPC\builder\linux\library; +use SPC\builder\linux\SystemUtil; use SPC\store\FileSystem; class openssl extends LinuxLibraryBase @@ -51,6 +52,9 @@ class openssl extends LinuxLibraryBase $zlib_extra = ''; } + $openssl_dir = getenv('OPENSSLDIR') ?: null; + // TODO: in v3 use the following: $openssl_dir ??= SystemUtil::getOSRelease()['dist'] === 'redhat' ? '/etc/pki/tls' : '/etc/ssl'; + $openssl_dir ??= '/etc/ssl'; $ex_lib = trim($ex_lib); shell()->cd($this->source_dir)->initializeEnv($this) @@ -58,10 +62,11 @@ class openssl extends LinuxLibraryBase "{$env} ./Configure no-shared {$extra} " . '--prefix=' . BUILD_ROOT_PATH . ' ' . '--libdir=' . BUILD_LIB_PATH . ' ' . - '--openssldir=/etc/ssl ' . + "--openssldir={$openssl_dir} " . "{$zlib_extra}" . 'enable-pie ' . 'no-legacy ' . + 'no-tests ' . "linux-{$arch}" ) ->exec('make clean') diff --git a/src/SPC/builder/traits/UnixLibraryTrait.php b/src/SPC/builder/traits/UnixLibraryTrait.php index 868cf6f7..ec1e7c2b 100644 --- a/src/SPC/builder/traits/UnixLibraryTrait.php +++ b/src/SPC/builder/traits/UnixLibraryTrait.php @@ -34,7 +34,7 @@ trait UnixLibraryTrait $files = array_map(fn ($x) => "{$x}.pc", $conf_pc); } foreach ($files as $name) { - $realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name); + $realpath = realpath(BUILD_LIB_PATH . '/pkgconfig/' . $name); if ($realpath === false) { throw new PatchException('pkg-config prefix patcher', 'Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] in ' . BUILD_LIB_PATH . '/pkgconfig/ !'); } diff --git a/src/SPC/builder/traits/UnixSystemUtilTrait.php b/src/SPC/builder/traits/UnixSystemUtilTrait.php index b1ef9db4..ff75bf7c 100644 --- a/src/SPC/builder/traits/UnixSystemUtilTrait.php +++ b/src/SPC/builder/traits/UnixSystemUtilTrait.php @@ -72,12 +72,8 @@ trait UnixSystemUtilTrait if (!is_file($symbol_file)) { throw new SPCInternalException("The symbol file {$symbol_file} does not exist, please check if nm command is available."); } - // https://github.com/ziglang/zig/issues/24662 - if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - return '-Wl,--export-dynamic'; - } - // macOS - if (SPCTarget::getTargetOS() !== 'Linux') { + // macOS/zig + if (SPCTarget::getTargetOS() !== 'Linux' || ToolchainManager::getToolchainClass() === ZigToolchain::class) { return "-Wl,-exported_symbols_list,{$symbol_file}"; } return "-Wl,--dynamic-list={$symbol_file}"; diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index d98059cb..464c9b2f 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -145,11 +145,10 @@ abstract class UnixBuilderBase extends BuilderBase throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}"); } - // extract debug info - $this->extractDebugInfo($dst); - - // strip if (!$this->getOption('no-strip')) { + // extract debug info + $this->extractDebugInfo($dst); + // extra strip $this->stripBinary($dst); } @@ -236,8 +235,10 @@ abstract class UnixBuilderBase extends BuilderBase $lens .= ' -static'; } $dynamic_exports = ''; + $embedType = 'static'; // if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { + $embedType = 'shared'; if (PHP_OS_FAMILY === 'Darwin') { $ext_path = 'DYLD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$DYLD_LIBRARY_PATH '; } else { @@ -256,18 +257,19 @@ abstract class UnixBuilderBase extends BuilderBase } } $cc = getenv('CC'); + [$ret, $out] = shell()->cd($sample_file_path)->execWithResult("{$cc} -o embed embed.c {$lens} {$dynamic_exports}"); if ($ret !== 0) { throw new ValidationException( - 'embed failed sanity check: build failed. Error message: ' . implode("\n", $out), - validation_module: 'static libphp.a sanity check' + 'embed failed to build. Error message: ' . implode("\n", $out), + validation_module: $embedType . ' libphp embed build sanity check' ); } [$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed'); if ($ret !== 0 || trim(implode('', $output)) !== 'hello') { throw new ValidationException( - 'embed failed sanity check: run failed. Error message: ' . implode("\n", $output), - validation_module: 'static libphp.a sanity check' + 'embed failed to run. Error message: ' . implode("\n", $output), + validation_module: $embedType . ' libphp embed run sanity check' ); } } diff --git a/src/SPC/builder/unix/library/gmp.php b/src/SPC/builder/unix/library/gmp.php index f09976d8..97a88ba1 100644 --- a/src/SPC/builder/unix/library/gmp.php +++ b/src/SPC/builder/unix/library/gmp.php @@ -10,7 +10,14 @@ trait gmp { protected function build(): void { - UnixAutoconfExecutor::create($this)->configure()->make(); + UnixAutoconfExecutor::create($this) + ->appendEnv([ + 'CFLAGS' => '-std=c17', + ]) + ->configure( + '--enable-fat' + ) + ->make(); $this->patchPkgconfPrefix(['gmp.pc']); } } diff --git a/src/SPC/builder/unix/library/libjxl.php b/src/SPC/builder/unix/library/libjxl.php index 13f8481b..4c922d9d 100644 --- a/src/SPC/builder/unix/library/libjxl.php +++ b/src/SPC/builder/unix/library/libjxl.php @@ -29,13 +29,17 @@ trait libjxl ); if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $cmake->addConfigureArgs( - '-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE', - '-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE', - '-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE', - '-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE', - '-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE' - ); + $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; + $has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); + if (!$has_avx512) { + $cmake->addConfigureArgs( + '-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE', + '-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE', + '-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE', + '-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE', + '-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE' + ); + } } $cmake->build(); diff --git a/src/SPC/builder/unix/library/libwebp.php b/src/SPC/builder/unix/library/libwebp.php index 46a88af4..015fa73b 100644 --- a/src/SPC/builder/unix/library/libwebp.php +++ b/src/SPC/builder/unix/library/libwebp.php @@ -10,8 +10,26 @@ trait libwebp { protected function build(): void { + $code = '#include +int main() { return _mm256_cvtsi256_si32(_mm256_setzero_si256()); }'; + $cc = getenv('CC') ?: 'gcc'; + [$ret] = shell()->execWithResult("printf '%s' '{$code}' | {$cc} -x c -mavx2 -o /dev/null - 2>&1"); + $disableAvx2 = $ret !== 0 && GNU_ARCH === 'x86_64' && PHP_OS_FAMILY === 'Linux'; + UnixCMakeExecutor::create($this) - ->addConfigureArgs('-DWEBP_BUILD_EXTRAS=ON') + ->addConfigureArgs( + '-DWEBP_BUILD_EXTRAS=OFF', + '-DWEBP_BUILD_ANIM_UTILS=OFF', + '-DWEBP_BUILD_CWEBP=OFF', + '-DWEBP_BUILD_DWEBP=OFF', + '-DWEBP_BUILD_GIF2WEBP=OFF', + '-DWEBP_BUILD_IMG2WEBP=OFF', + '-DWEBP_BUILD_VWEBP=OFF', + '-DWEBP_BUILD_WEBPINFO=OFF', + '-DWEBP_BUILD_WEBPMUX=OFF', + '-DWEBP_BUILD_FUZZTEST=OFF', + $disableAvx2 ? '-DWEBP_ENABLE_SIMD=OFF' : '' + ) ->build(); // patch pkgconfig $this->patchPkgconfPrefix(patch_option: PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR); diff --git a/src/SPC/builder/unix/library/ncurses.php b/src/SPC/builder/unix/library/ncurses.php index 27725c3d..cb8c10df 100644 --- a/src/SPC/builder/unix/library/ncurses.php +++ b/src/SPC/builder/unix/library/ncurses.php @@ -16,6 +16,7 @@ trait ncurses UnixAutoconfExecutor::create($this) ->appendEnv([ + 'CFLAGS' => '-std=c17', 'LDFLAGS' => SPCTarget::isStatic() ? '-static' : '', ]) ->configure( @@ -29,7 +30,7 @@ trait ncurses '--without-tests', '--without-dlsym', '--without-debug', - '-enable-symlinks', + '--enable-symlinks', "--bindir={$this->getBinDir()}", "--includedir={$this->getIncludeDir()}", "--libdir={$this->getLibDir()}", diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index 6e0cb606..a72f3a1a 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -50,7 +50,7 @@ trait postgresql $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false)); $env_vars = [ - 'CFLAGS' => $config['cflags'], + 'CFLAGS' => $config['cflags'] . ' -std=c17', 'CPPFLAGS' => '-DPIC', 'LDFLAGS' => $config['ldflags'], 'LIBS' => $config['libs'], diff --git a/src/SPC/builder/windows/library/curl.php b/src/SPC/builder/windows/library/curl.php index 1229dbd6..bba130e1 100644 --- a/src/SPC/builder/windows/library/curl.php +++ b/src/SPC/builder/windows/library/curl.php @@ -30,7 +30,6 @@ class curl extends WindowsLibraryBase '-DCMAKE_BUILD_TYPE=Release ' . '-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_STATIC_LIBS=ON ' . - '-DCURL_STATICLIB=ON ' . '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . '-DBUILD_CURL_EXE=OFF ' . // disable curl.exe '-DBUILD_TESTING=OFF ' . // disable tests @@ -42,9 +41,9 @@ class curl extends WindowsLibraryBase '-DCURL_USE_OPENSSL=OFF ' . // disable openssl due to certificate issue '-DCURL_ENABLE_SSL=ON ' . '-DUSE_NGHTTP2=ON ' . // enable nghttp2 + '-DSHARE_LIB_OBJECT=OFF ' . // disable shared lib object '-DCURL_USE_LIBSSH2=ON ' . // enable libssh2 '-DENABLE_IPV6=ON ' . // enable ipv6 - '-DNGHTTP2_CFLAGS="/DNGHTTP2_STATICLIB" ' . $alt ) ->execWithWrapper( @@ -53,5 +52,7 @@ class curl extends WindowsLibraryBase ); // move libcurl.lib to libcurl_a.lib rename(BUILD_LIB_PATH . '\libcurl.lib', BUILD_LIB_PATH . '\libcurl_a.lib'); + + FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\curl\curl.h', '#ifdef CURL_STATICLIB', '#if 1'); } } diff --git a/src/SPC/builder/windows/library/nghttp2.php b/src/SPC/builder/windows/library/nghttp2.php index 7e6e999d..5a1c6bf1 100644 --- a/src/SPC/builder/windows/library/nghttp2.php +++ b/src/SPC/builder/windows/library/nghttp2.php @@ -29,11 +29,16 @@ class nghttp2 extends WindowsLibraryBase '-DBUILD_SHARED_LIBS=OFF ' . '-DENABLE_STATIC_CRT=ON ' . '-DENABLE_LIB_ONLY=ON ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . + '-DENABLE_STATIC_CRT=ON ' . + '-DENABLE_DOC=OFF ' . + '-DBUILD_TESTING=OFF ' ) ->execWithWrapper( $this->builder->makeSimpleWrapper('cmake'), "--build build --config Release --target install -j{$this->builder->concurrency}" ); + + FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\nghttp2\nghttp2.h', '#ifdef NGHTTP2_STATICLIB', '#if 1'); } } diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index 08a2b4dc..6e4c5034 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -22,7 +22,6 @@ class LinuxToolCheckList 'bzip2', 'cmake', 'gcc', 'g++', 'patch', 'binutils-gold', 'libtoolize', 'which', - 'patchelf', ]; public const TOOLS_DEBIAN = [ @@ -31,7 +30,6 @@ class LinuxToolCheckList 'tar', 'unzip', 'gzip', 'gcc', 'g++', 'bzip2', 'cmake', 'patch', 'xz', 'libtoolize', 'which', - 'patchelf', ]; public const TOOLS_RHEL = [ @@ -39,8 +37,7 @@ class LinuxToolCheckList 'git', 'autoconf', 'automake', 'tar', 'unzip', 'gzip', 'gcc', 'g++', 'bzip2', 'cmake', 'patch', 'which', - 'xz', 'libtool', 'gettext-devel', - 'patchelf', 'file', + 'xz', 'libtool', 'gettext-devel', 'file', ]; public const TOOLS_ARCH = [ diff --git a/src/SPC/store/Downloader.php b/src/SPC/store/Downloader.php index 63bec807..ccf61dd8 100644 --- a/src/SPC/store/Downloader.php +++ b/src/SPC/store/Downloader.php @@ -97,8 +97,9 @@ class Downloader public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array { logger()->debug("finding {$name} source from github {$type} tarball"); + $source['query'] ??= ''; $data = json_decode(self::curlExec( - url: "https://api.github.com/repos/{$source['repo']}/{$type}", + url: "https://api.github.com/repos/{$source['repo']}/{$type}{$source['query']}", hooks: [[CurlHook::class, 'setupGithubToken']], retries: self::getRetryAttempts() ), true, 512, JSON_THROW_ON_ERROR); @@ -108,6 +109,9 @@ class Downloader if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { continue; } + if (($rel['draft'] ?? false) === true && (($source['prefer-stable'] ?? false) || !$rel['tarball_url'])) { + continue; + } if (!($source['match'] ?? null)) { $url = $rel['tarball_url'] ?? null; break; diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 3b88a2bc..1d0815ce 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -408,13 +408,13 @@ class FileSystem continue; } $sub_file = self::convertPath($dir . '/' . $v); - if (is_dir($sub_file)) { - # 如果是 目录 且 递推 , 则递推添加下级文件 - if (!self::removeDir($sub_file)) { + if (is_link($sub_file) || is_file($sub_file)) { + if (!unlink($sub_file)) { return false; } - } elseif (is_link($sub_file) || is_file($sub_file)) { - if (!unlink($sub_file)) { + } elseif (is_dir($sub_file)) { + # 如果是 目录 且 递推 , 则递推添加下级文件 + if (!self::removeDir($sub_file)) { return false; } } @@ -572,6 +572,44 @@ class FileSystem return file_put_contents($file, implode('', $lines)); } + /** + * Move file or directory, handling cross-device scenarios + * Uses rename() if possible, falls back to copy+delete for cross-device moves + * + * @param string $source Source path + * @param string $dest Destination path + */ + public static function moveFileOrDir(string $source, string $dest): void + { + $source = self::convertPath($source); + $dest = self::convertPath($dest); + + // Check if source and dest are on the same device to avoid cross-device rename errors + $source_stat = @stat($source); + $dest_parent = dirname($dest); + $dest_stat = @stat($dest_parent); + + // Only use rename if on same device + if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) { + if (@rename($source, $dest)) { + return; + } + } + + // Fall back to copy + delete for cross-device moves or if rename failed + if (is_dir($source)) { + self::copyDir($source, $dest); + self::removeDir($source); + } else { + if (!copy($source, $dest)) { + throw new FileSystemException("Failed to copy file from {$source} to {$dest}"); + } + if (!unlink($source)) { + throw new FileSystemException("Failed to remove source file: {$source}"); + } + } + } + private static function extractArchive(string $filename, string $target): void { // Create base dir @@ -648,44 +686,6 @@ class FileSystem }; } - /** - * Move file or directory, handling cross-device scenarios - * Uses rename() if possible, falls back to copy+delete for cross-device moves - * - * @param string $source Source path - * @param string $dest Destination path - */ - private static function moveFileOrDir(string $source, string $dest): void - { - $source = self::convertPath($source); - $dest = self::convertPath($dest); - - // Check if source and dest are on the same device to avoid cross-device rename errors - $source_stat = @stat($source); - $dest_parent = dirname($dest); - $dest_stat = @stat($dest_parent); - - // Only use rename if on same device - if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) { - if (@rename($source, $dest)) { - return; - } - } - - // Fall back to copy + delete for cross-device moves or if rename failed - if (is_dir($source)) { - self::copyDir($source, $dest); - self::removeDir($source); - } else { - if (!copy($source, $dest)) { - throw new FileSystemException("Failed to copy file from {$source} to {$dest}"); - } - if (!unlink($source)) { - throw new FileSystemException("Failed to remove source file: {$source}"); - } - } - } - /** * Unzip file with stripping top-level directory */ diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index f628544f..0068f53e 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -25,6 +25,7 @@ class SourcePatcher FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchFfiCentos7FixO3strncmp']); FileSystem::addSourceExtractHook('sqlsrv', [__CLASS__, 'patchSQLSRVWin32']); FileSystem::addSourceExtractHook('pdo_sqlsrv', [__CLASS__, 'patchSQLSRVWin32']); + FileSystem::addSourceExtractHook('pdo_sqlsrv', [__CLASS__, 'patchSQLSRVPhp85']); FileSystem::addSourceExtractHook('yaml', [__CLASS__, 'patchYamlWin32']); FileSystem::addSourceExtractHook('libyaml', [__CLASS__, 'patchLibYaml']); FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchImapLicense']); @@ -432,6 +433,23 @@ class SourcePatcher return false; } + /** + * Fix the compilation issue of pdo_sqlsrv with php 8.5 + */ + public static function patchSQLSRVPhp85(): bool + { + $source_dir = SOURCE_PATH . '/php-src/ext/pdo_sqlsrv'; + if (!file_exists($source_dir . '/config.m4') && is_dir($source_dir . '/source/pdo_sqlsrv')) { + FileSystem::moveFileOrDir($source_dir . '/LICENSE', $source_dir . '/source/pdo_sqlsrv/LICENSE'); + FileSystem::moveFileOrDir($source_dir . '/source/shared', $source_dir . '/source/pdo_sqlsrv/shared'); + FileSystem::moveFileOrDir($source_dir . '/source/pdo_sqlsrv', SOURCE_PATH . '/pdo_sqlsrv'); + FileSystem::removeDir($source_dir); + FileSystem::moveFileOrDir(SOURCE_PATH . '/pdo_sqlsrv', $source_dir); + 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'"); diff --git a/src/SPC/store/pkg/GoXcaddy.php b/src/SPC/store/pkg/GoXcaddy.php index 0c1c6f8c..93821aaa 100644 --- a/src/SPC/store/pkg/GoXcaddy.php +++ b/src/SPC/store/pkg/GoXcaddy.php @@ -48,10 +48,10 @@ class GoXcaddy extends CustomPackage 'macos' => 'darwin', default => throw new \InvalidArgumentException('Unsupported OS: ' . $name), }; - $go_version = '1.25.0'; + [$go_version] = explode("\n", Downloader::curlExec('https://go.dev/VERSION?m=text')); $config = [ 'type' => 'url', - 'url' => "https://go.dev/dl/go{$go_version}.{$os}-{$arch}.tar.gz", + 'url' => "https://go.dev/dl/{$go_version}.{$os}-{$arch}.tar.gz", ]; Downloader::downloadPackage($name, $config, $force); } diff --git a/src/SPC/store/pkg/Zig.php b/src/SPC/store/pkg/Zig.php index e9865dbe..c2a81c0d 100644 --- a/src/SPC/store/pkg/Zig.php +++ b/src/SPC/store/pkg/Zig.php @@ -72,8 +72,11 @@ class Zig extends CustomPackage $latest_version = null; foreach ($index_json as $version => $data) { - $latest_version = $version; - break; + // Skip the master branch, get the latest stable release + if ($version !== 'master') { + $latest_version = $version; + break; + } } if (!$latest_version) { diff --git a/src/SPC/toolchain/ZigToolchain.php b/src/SPC/toolchain/ZigToolchain.php index bb423db2..1b7cc70d 100644 --- a/src/SPC/toolchain/ZigToolchain.php +++ b/src/SPC/toolchain/ZigToolchain.php @@ -67,7 +67,8 @@ class ZigToolchain implements ToolchainInterface $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; $has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); if (!$has_avx512) { - GlobalEnvManager::putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no'); + $extra_vars = getenv('SPC_EXTRA_PHP_VARS') ?: ''; + GlobalEnvManager::putenv("SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no {$extra_vars}"); } } diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index a74d6a24..8c4fa926 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -80,7 +80,6 @@ class SPCConfigUtil $libs = $this->getLibsString($libraries, !$this->absolute_libs); // additional OS-specific libraries (e.g. macOS -lresolv) - // embed if ($extra_libs = SPCTarget::getRuntimeLibs()) { $libs .= " {$extra_libs}"; } @@ -226,9 +225,17 @@ class SPCConfigUtil // parse pkg-configs foreach ($libraries as $library) { $pc = Config::getLib($library, 'pkg-configs', []); + $pkg_config_path = getenv('PKG_CONFIG_PATH') ?: ''; + $search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)); foreach ($pc as $file) { - if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$file}.pc")) { - throw new WrongUsageException("pkg-config file '{$file}.pc' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "/pkgconfig'. Please build it first."); + $found = false; + foreach ($search_paths as $path) { + if (file_exists($path . "/{$file}.pc")) { + $found = true; + } + } + if (!$found) { + throw new WrongUsageException("pkg-config file '{$file}.pc' for lib [{$library}] does not exist. Please build it first."); } } $pc_cflags = implode(' ', $pc); @@ -257,9 +264,17 @@ class SPCConfigUtil foreach ($libraries as $library) { // add pkg-configs libs $pkg_configs = Config::getLib($library, 'pkg-configs', []); - foreach ($pkg_configs as $pkg_config) { - if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$pkg_config}.pc")) { - throw new WrongUsageException("pkg-config file '{$pkg_config}.pc' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "/pkgconfig'. Please build it first."); + $pkg_config_path = getenv('PKG_CONFIG_PATH') ?: ''; + $search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)); + foreach ($pkg_configs as $file) { + $found = false; + foreach ($search_paths as $path) { + if (file_exists($path . "/{$file}.pc")) { + $found = true; + } + } + if (!$found) { + throw new WrongUsageException("pkg-config file '{$file}.pc' for lib [{$library}] does not exist. Please build it first."); } } $pkg_configs = implode(' ', $pkg_configs); diff --git a/src/StaticPHP/Artifact/ArtifactDownloader.php b/src/StaticPHP/Artifact/ArtifactDownloader.php index 315cfb11..b53ddd8a 100644 --- a/src/StaticPHP/Artifact/ArtifactDownloader.php +++ b/src/StaticPHP/Artifact/ArtifactDownloader.php @@ -329,8 +329,7 @@ class ArtifactDownloader } if ($interactive) { $skip_msg = !empty($skipped) ? ' (Skipped ' . count($skipped) . ' artifacts for being already downloaded)' : ''; - InteractiveTerm::success("Downloaded all {$count} artifacts.{$skip_msg}", true); - echo PHP_EOL; + InteractiveTerm::success("Downloaded all {$count} artifacts.{$skip_msg}\n", true); } } } catch (SPCException $e) { diff --git a/src/StaticPHP/Command/BaseCommand.php b/src/StaticPHP/Command/BaseCommand.php index e416be26..02f84ffb 100644 --- a/src/StaticPHP/Command/BaseCommand.php +++ b/src/StaticPHP/Command/BaseCommand.php @@ -23,7 +23,6 @@ abstract class BaseCommand extends Command \___ \| __/ _` | __| |/ __| |_) | |_| | |_) | ___) | || (_| | |_| | (__| __/| _ | __/ |____/ \__\__,_|\__|_|\___|_| |_| |_|_| {version} - '; protected bool $no_motd = false; @@ -71,7 +70,7 @@ abstract class BaseCommand extends Command $version = $this->getVersionWithCommit(); if (!$this->no_motd) { $str = str_replace('{version}', '' . ConsoleColor::none("v{$version}"), '' . ConsoleColor::magenta(self::$motd)); - echo $this->input->getOption('no-ansi') ? strip_ansi_colors($str) : $str; + $this->output->writeln($this->input->getOption('no-ansi') ? strip_ansi_colors($str) : $str); } } diff --git a/src/StaticPHP/Command/Dev/SortConfigCommand.php b/src/StaticPHP/Command/Dev/SortConfigCommand.php new file mode 100644 index 00000000..aa3a9ecd --- /dev/null +++ b/src/StaticPHP/Command/Dev/SortConfigCommand.php @@ -0,0 +1,49 @@ +sortConfigFile($file); + } + $loaded_pkg_configs = Registry::getLoadedPackageConfigs(); + foreach ($loaded_pkg_configs as $file) { + $this->sortConfigFile($file); + } + return static::SUCCESS; + } + + private function sortConfigFile(mixed $file): void + { + $content = file_get_contents($file); + if ($content === false) { + $this->output->writeln("Failed to read artifact config file: {$file}"); + return; + } + $data = json_decode($content, true); + if (!is_array($data)) { + $this->output->writeln("Invalid JSON format in artifact config file: {$file}"); + return; + } + ksort($data); + foreach ($data as $artifact_name => &$config) { + ksort($config); + } + unset($config); + $new_content = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"; + file_put_contents($file, $new_content); + $this->output->writeln("Sorted artifact config file: {$file}"); + } +} diff --git a/src/StaticPHP/Config/ArtifactConfig.php b/src/StaticPHP/Config/ArtifactConfig.php index d25c6dd1..49abae92 100644 --- a/src/StaticPHP/Config/ArtifactConfig.php +++ b/src/StaticPHP/Config/ArtifactConfig.php @@ -5,31 +5,36 @@ declare(strict_types=1); namespace StaticPHP\Config; use StaticPHP\Exception\WrongUsageException; +use StaticPHP\Registry\Registry; class ArtifactConfig { private static array $artifact_configs = []; - public static function loadFromDir(string $dir): void + public static function loadFromDir(string $dir, string $registry_name): array { if (!is_dir($dir)) { throw new WrongUsageException("Directory {$dir} does not exist, cannot load artifact config."); } + $loaded = []; $files = glob("{$dir}/artifact.*.json"); if (is_array($files)) { foreach ($files as $file) { - self::loadFromFile($file); + self::loadFromFile($file, $registry_name); + $loaded[] = $file; } } if (file_exists("{$dir}/artifact.json")) { - self::loadFromFile("{$dir}/artifact.json"); + self::loadFromFile("{$dir}/artifact.json", $registry_name); + $loaded[] = "{$dir}/artifact.json"; } + return $loaded; } /** * Load artifact configurations from a specified JSON file. */ - public static function loadFromFile(string $file): void + public static function loadFromFile(string $file, string $registry_name): string { $content = file_get_contents($file); if ($content === false) { @@ -42,7 +47,9 @@ class ArtifactConfig ConfigValidator::validateAndLintArtifacts(basename($file), $data); foreach ($data as $artifact_name => $config) { self::$artifact_configs[$artifact_name] = $config; + Registry::_bindArtifactConfigFile($artifact_name, $registry_name, $file); } + return $file; } /** diff --git a/src/StaticPHP/Config/PackageConfig.php b/src/StaticPHP/Config/PackageConfig.php index dc0b3d54..56ef7ab1 100644 --- a/src/StaticPHP/Config/PackageConfig.php +++ b/src/StaticPHP/Config/PackageConfig.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace StaticPHP\Config; use StaticPHP\Exception\WrongUsageException; +use StaticPHP\Registry\Registry; use StaticPHP\Runtime\SystemTarget; class PackageConfig @@ -15,20 +16,24 @@ class PackageConfig * Load package configurations from a specified directory. * It will look for files matching the pattern 'pkg.*.json' and 'pkg.json'. */ - public static function loadFromDir(string $dir): void + public static function loadFromDir(string $dir, string $registry_name): array { if (!is_dir($dir)) { throw new WrongUsageException("Directory {$dir} does not exist, cannot load pkg.json config."); } + $loaded = []; $files = glob("{$dir}/pkg.*.json"); if (is_array($files)) { foreach ($files as $file) { - self::loadFromFile($file); + self::loadFromFile($file, $registry_name); + $loaded[] = $file; } } if (file_exists("{$dir}/pkg.json")) { - self::loadFromFile("{$dir}/pkg.json"); + self::loadFromFile("{$dir}/pkg.json", $registry_name); + $loaded[] = "{$dir}/pkg.json"; } + return $loaded; } /** @@ -36,7 +41,7 @@ class PackageConfig * * @param string $file the path to the json package configuration file */ - public static function loadFromFile(string $file): void + public static function loadFromFile(string $file, string $registry_name): string { $content = file_get_contents($file); if ($content === false) { @@ -49,7 +54,9 @@ class PackageConfig ConfigValidator::validateAndLintPackages(basename($file), $data); foreach ($data as $pkg_name => $config) { self::$package_configs[$pkg_name] = $config; + Registry::_bindPackageConfigFile($pkg_name, $registry_name, $file); } + return $file; } /** diff --git a/src/StaticPHP/ConsoleApplication.php b/src/StaticPHP/ConsoleApplication.php index 0e5371ac..9e37698c 100644 --- a/src/StaticPHP/ConsoleApplication.php +++ b/src/StaticPHP/ConsoleApplication.php @@ -9,6 +9,7 @@ use StaticPHP\Command\BuildTargetCommand; use StaticPHP\Command\Dev\EnvCommand; use StaticPHP\Command\Dev\IsInstalledCommand; use StaticPHP\Command\Dev\ShellCommand; +use StaticPHP\Command\Dev\SortConfigCommand; use StaticPHP\Command\DoctorCommand; use StaticPHP\Command\DownloadCommand; use StaticPHP\Command\ExtractCommand; @@ -27,12 +28,12 @@ class ConsoleApplication extends Application public function __construct() { - parent::__construct('static-php-cli', self::VERSION); + parent::__construct('StaticPHP', self::VERSION); require_once ROOT_DIR . '/src/bootstrap.php'; - // check registry - Registry::checkLoadedRegistries(); + // resolve registry + Registry::resolve(); /** * @var string $name @@ -59,6 +60,7 @@ class ConsoleApplication extends Application new ShellCommand(), new IsInstalledCommand(), new EnvCommand(), + new SortConfigCommand(), ]); // add additional commands from registries diff --git a/src/StaticPHP/Package/PackageInstaller.php b/src/StaticPHP/Package/PackageInstaller.php index 4c44ce92..ae3b7346 100644 --- a/src/StaticPHP/Package/PackageInstaller.php +++ b/src/StaticPHP/Package/PackageInstaller.php @@ -133,9 +133,8 @@ class PackageInstaller // show install or build options in terminal with beautiful output $this->printInstallerInfo(); - InteractiveTerm::notice('Build process will start after 2s ...'); + InteractiveTerm::notice('Build process will start after 2s ...' . PHP_EOL); sleep(2); - echo PHP_EOL; } // Early validation: check if packages can be built or installed before downloading diff --git a/src/StaticPHP/Registry/Registry.php b/src/StaticPHP/Registry/Registry.php index 4ae5df4f..e464ed47 100644 --- a/src/StaticPHP/Registry/Registry.php +++ b/src/StaticPHP/Registry/Registry.php @@ -13,9 +13,39 @@ use Symfony\Component\Yaml\Yaml; class Registry { - /** @var string[] List of loaded registry names */ + /** @var string[] List of loaded registries */ private static array $loaded_registries = []; + /** @var array Loaded registry configs */ + private static array $registry_configs = []; + + private static array $loaded_package_configs = []; + + private static array $loaded_artifact_configs = []; + + /** @var array Maps of package and artifact names to their registry config file paths (for reverse lookup) */ + private static array $package_reversed_registry_files = []; + + private static array $artifact_reversed_registry_files = []; + + /** + * Get the current registry configuration. + * "Current" depends on SPC load mode + */ + public static function getRegistryConfig(?string $registry_name = null): array + { + if ($registry_name === null && spc_mode(SPC_MODE_SOURCE)) { + return self::$registry_configs['internal']; + } + if ($registry_name !== null && isset(self::$registry_configs[$registry_name])) { + return self::$registry_configs[$registry_name]; + } + if ($registry_name === null) { + throw new RegistryException('No registry name specified.'); + } + throw new RegistryException("Registry '{$registry_name}' is not loaded."); + } + /** * Load a registry from file path. * This method handles external registries that may not be in composer autoload. @@ -48,12 +78,14 @@ class Registry return; } self::$loaded_registries[] = $registry_name; + self::$registry_configs[$registry_name] = $data; + self::$registry_configs[$registry_name]['_file'] = $registry_file; logger()->debug("Loading registry '{$registry_name}' from file: {$registry_file}"); // Load composer autoload if specified (for external registries with their own dependencies) if (isset($data['autoload']) && is_string($data['autoload'])) { - $autoload_path = self::fullpath($data['autoload'], dirname($registry_file)); + $autoload_path = FileSystem::fullpath($data['autoload'], dirname($registry_file)); if (file_exists($autoload_path)) { logger()->debug("Loading external autoload from: {$autoload_path}"); require_once $autoload_path; @@ -65,7 +97,7 @@ class Registry // load doctor items from PSR-4 directories if (isset($data['doctor']['psr-4']) && is_assoc_array($data['doctor']['psr-4'])) { foreach ($data['doctor']['psr-4'] as $namespace => $path) { - $path = self::fullpath($path, dirname($registry_file)); + $path = FileSystem::fullpath($path, dirname($registry_file)); DoctorLoader::loadFromPsr4Dir($path, $namespace, $auto_require); } } @@ -83,11 +115,11 @@ class Registry // load package configs if (isset($data['package']['config']) && is_array($data['package']['config'])) { foreach ($data['package']['config'] as $path) { - $path = self::fullpath($path, dirname($registry_file)); + $path = FileSystem::fullpath($path, dirname($registry_file)); if (is_file($path)) { - PackageConfig::loadFromFile($path); + self::$loaded_package_configs[] = PackageConfig::loadFromFile($path, $registry_name); } elseif (is_dir($path)) { - PackageConfig::loadFromDir($path); + self::$loaded_package_configs = array_merge(self::$loaded_package_configs, PackageConfig::loadFromDir($path, $registry_name)); } } } @@ -95,11 +127,11 @@ class Registry // load artifact configs if (isset($data['artifact']['config']) && is_array($data['artifact']['config'])) { foreach ($data['artifact']['config'] as $path) { - $path = self::fullpath($path, dirname($registry_file)); + $path = FileSystem::fullpath($path, dirname($registry_file)); if (is_file($path)) { - ArtifactConfig::loadFromFile($path); + self::$loaded_artifact_configs[] = ArtifactConfig::loadFromFile($path, $registry_name); } elseif (is_dir($path)) { - ArtifactConfig::loadFromDir($path); + self::$loaded_package_configs = array_merge(self::$loaded_package_configs, ArtifactConfig::loadFromDir($path, $registry_name)); } } } @@ -107,7 +139,7 @@ class Registry // load packages from PSR-4 directories if (isset($data['package']['psr-4']) && is_assoc_array($data['package']['psr-4'])) { foreach ($data['package']['psr-4'] as $namespace => $path) { - $path = self::fullpath($path, dirname($registry_file)); + $path = FileSystem::fullpath($path, dirname($registry_file)); PackageLoader::loadFromPsr4Dir($path, $namespace, $auto_require); } } @@ -125,7 +157,7 @@ class Registry // load artifacts from PSR-4 directories if (isset($data['artifact']['psr-4']) && is_assoc_array($data['artifact']['psr-4'])) { foreach ($data['artifact']['psr-4'] as $namespace => $path) { - $path = self::fullpath($path, dirname($registry_file)); + $path = FileSystem::fullpath($path, dirname($registry_file)); ArtifactLoader::loadFromPsr4Dir($path, $namespace, $auto_require); } } @@ -143,7 +175,7 @@ class Registry // load additional commands from PSR-4 directories if (isset($data['command']['psr-4']) && is_assoc_array($data['command']['psr-4'])) { foreach ($data['command']['psr-4'] as $namespace => $path) { - $path = self::fullpath($path, dirname($registry_file)); + $path = FileSystem::fullpath($path, dirname($registry_file)); $classes = FileSystem::getClassesPsr4($path, $namespace, auto_require: $auto_require); $instances = array_map(fn ($x) => new $x(), $classes); ConsoleApplication::_addAdditionalCommands($instances); @@ -187,7 +219,12 @@ class Registry } } - public static function checkLoadedRegistries(): void + /** + * Resolve loaded registries. + * This method finalizes the loading process by registering default stages + * and validating stage events. + */ + public static function resolve(): void { // Register default stages for all PhpExtensionPackage instances // This must be done after all registries are loaded to ensure custom stages take precedence @@ -217,6 +254,52 @@ class Registry self::$loaded_registries = []; } + /** + * Bind a package name to its registry config file for reverse lookup. + * + * @internal + */ + public static function _bindPackageConfigFile(string $package_name, string $registry_name, string $config_file): void + { + self::$package_reversed_registry_files[$package_name] = [ + 'registry' => $registry_name, + 'config' => $config_file, + ]; + } + + /** + * Bind an artifact name to its registry config file for reverse lookup. + * + * @internal + */ + public static function _bindArtifactConfigFile(string $artifact_name, string $registry_name, string $config_file): void + { + self::$artifact_reversed_registry_files[$artifact_name] = [ + 'registry' => $registry_name, + 'config' => $config_file, + ]; + } + + public static function getPackageConfigInfo(string $package_name): ?array + { + return self::$package_reversed_registry_files[$package_name] ?? null; + } + + public static function getArtifactConfigInfo(string $artifact_name): ?array + { + return self::$artifact_reversed_registry_files[$artifact_name] ?? null; + } + + public static function getLoadedPackageConfigs(): array + { + return self::$loaded_package_configs; + } + + public static function getLoadedArtifactConfigs(): array + { + return self::$loaded_artifact_configs; + } + /** * Parse a class entry from the classes array. * Supports two formats: @@ -253,7 +336,7 @@ class Registry // If file path is provided, require it if ($file_path !== null) { - $full_path = self::fullpath($file_path, $base_path); + $full_path = FileSystem::fullpath($file_path, $base_path); require_once $full_path; return; } @@ -266,21 +349,4 @@ class Registry " 3. Provide file path in classes map: \"{$class}\": \"path/to/file.php\"" ); } - - /** - * Return full path, resolving relative paths against a base path. - * - * @param string $path Input path (relative or absolute) - * @param string $relative_path_base Base path for relative paths - */ - private static function fullpath(string $path, string $relative_path_base): string - { - if (FileSystem::isRelativePath($path)) { - $path = $relative_path_base . DIRECTORY_SEPARATOR . $path; - } - if (!file_exists($path)) { - throw new RegistryException("Path does not exist: {$path}"); - } - return FileSystem::convertPath($path); - } } diff --git a/src/StaticPHP/Skeleton/ExecutorGenerator.php b/src/StaticPHP/Skeleton/ExecutorGenerator.php new file mode 100644 index 00000000..69d7a9f8 --- /dev/null +++ b/src/StaticPHP/Skeleton/ExecutorGenerator.php @@ -0,0 +1,36 @@ +class) { + UnixCMakeExecutor::class => [UnixCMakeExecutor::class, 'UnixCMakeExecutor::create($package)->build();'], + UnixAutoconfExecutor::class => [UnixAutoconfExecutor::class, 'UnixAutoconfExecutor::create($package)->build();'], + WindowsCMakeExecutor::class => [WindowsCMakeExecutor::class, 'WindowsCMakeExecutor::create($package)->build();'], + default => throw new ValidationException("Unsupported executor class: {$this->class}"), + }; + } +} diff --git a/src/StaticPHP/Util/FileSystem.php b/src/StaticPHP/Util/FileSystem.php index 2f540d70..1c21a92b 100644 --- a/src/StaticPHP/Util/FileSystem.php +++ b/src/StaticPHP/Util/FileSystem.php @@ -472,6 +472,23 @@ class FileSystem return file_put_contents($file, implode('', $lines)); } + /** + * Return full path, resolving relative paths against a base path. + * + * @param string $path Input path (relative or absolute) + * @param string $relative_path_base Base path for relative paths + */ + public static function fullpath(string $path, string $relative_path_base): string + { + if (FileSystem::isRelativePath($path)) { + $path = $relative_path_base . DIRECTORY_SEPARATOR . $path; + } + if (!file_exists($path)) { + throw new FileSystemException("Path does not exist: {$path}"); + } + return FileSystem::convertPath($path); + } + private static function replaceFile(string $filename, int $replace_type = REPLACE_FILE_STR, mixed $callback_or_search = null, mixed $to_replace = null): false|int { logger()->debug('Replacing file with type[' . $replace_type . ']: ' . $filename); diff --git a/src/StaticPHP/Util/InteractiveTerm.php b/src/StaticPHP/Util/InteractiveTerm.php index 1682ed1f..0570f31c 100644 --- a/src/StaticPHP/Util/InteractiveTerm.php +++ b/src/StaticPHP/Util/InteractiveTerm.php @@ -52,6 +52,7 @@ class InteractiveTerm default => logger()->info(strip_ansi_colors($message)), }; } else { + $output = $level === 'error' && $output instanceof ConsoleOutput ? $output->getErrorOutput() : $output; $output->writeln(($no_ansi ? 'strip_ansi_colors' : 'strval')($message)); } } diff --git a/src/StaticPHP/Util/System/LinuxUtil.php b/src/StaticPHP/Util/System/LinuxUtil.php index 79ad89ed..2b1adf3d 100644 --- a/src/StaticPHP/Util/System/LinuxUtil.php +++ b/src/StaticPHP/Util/System/LinuxUtil.php @@ -12,7 +12,6 @@ class LinuxUtil extends UnixUtil /** * Get current linux distro name and version. * - * @noinspection PhpMissingBreakStatementInspection * @return array{dist: string, ver: string, family: string} Linux distro info (unknown if not found) */ public static function getOSRelease(): array @@ -22,42 +21,39 @@ class LinuxUtil extends UnixUtil 'ver' => 'unknown', 'family' => 'unknown', ]; - switch (true) { - case file_exists('/etc/centos-release'): - $lines = file('/etc/centos-release'); - $centos = true; - goto rh; - case file_exists('/etc/redhat-release'): - $lines = file('/etc/redhat-release'); - $centos = false; - rh: - foreach ($lines as $line) { - if (preg_match('/release\s+(\d*(\.\d+)*)/', $line, $matches)) { - /* @phpstan-ignore-next-line */ - $ret['dist'] = $centos ? 'centos' : 'redhat'; - $ret['ver'] = $matches[1]; - } + + if (file_exists('/etc/centos-release') || file_exists('/etc/redhat-release')) { + $is_centos = file_exists('/etc/centos-release'); + $file = $is_centos ? '/etc/centos-release' : '/etc/redhat-release'; + $lines = file($file); + + foreach ($lines as $line) { + if (preg_match('/release\s+(\d*(\.\d+)*)/', $line, $matches)) { + $ret['dist'] = $is_centos ? 'centos' : 'redhat'; + $ret['ver'] = $matches[1]; } - break; - case file_exists('/etc/os-release'): - $lines = file('/etc/os-release'); - foreach ($lines as $line) { - if (preg_match('/^ID=(.*)$/', $line, $matches)) { - $ret['dist'] = $matches[1]; - } - if (preg_match('/^ID_LIKE=(.*)$/', $line, $matches)) { - $ret['family'] = $matches[1]; - } - if (preg_match('/^VERSION_ID=(.*)$/', $line, $matches)) { - $ret['ver'] = $matches[1]; - } + } + } elseif (file_exists('/etc/os-release')) { + $lines = file('/etc/os-release'); + + foreach ($lines as $line) { + if (preg_match('/^ID=(.*)$/', $line, $matches)) { + $ret['dist'] = $matches[1]; } - $ret['dist'] = trim($ret['dist'], '"\''); - $ret['ver'] = trim($ret['ver'], '"\''); - if (strcasecmp($ret['dist'], 'centos') === 0) { - $ret['dist'] = 'redhat'; + if (preg_match('/^ID_LIKE=(.*)$/', $line, $matches)) { + $ret['family'] = $matches[1]; } - break; + if (preg_match('/^VERSION_ID=(.*)$/', $line, $matches)) { + $ret['ver'] = $matches[1]; + } + } + + $ret['dist'] = trim($ret['dist'], '"\''); + $ret['ver'] = trim($ret['ver'], '"\''); + + if (strcasecmp($ret['dist'], 'centos') === 0) { + $ret['dist'] = 'redhat'; + } } return $ret; } diff --git a/src/globals/defines.php b/src/globals/defines.php index 3e6d2360..dbcb63f2 100644 --- a/src/globals/defines.php +++ b/src/globals/defines.php @@ -96,13 +96,32 @@ const SPC_STATUS_ALREADY_BUILT = 1; const SPC_DOWNLOAD_TYPE_DISPLAY_NAME = [ 'bitbuckettag' => 'BitBucket', - 'filelist' => 'website', + 'filelist' => 'File index website', 'git' => 'git', 'ghrel' => 'GitHub release', - 'ghtar', 'ghtagtar' => 'GitHub tarball', + 'ghtar' => 'GitHub release tarball', + 'ghtagtar' => 'GitHub tag tarball', 'local' => 'local dir', - 'pie' => 'PHP Installer for Extensions', + 'pie' => 'PHP Installer for Extensions (PIE)', 'url' => 'url', 'php-release' => 'php.net', 'custom' => 'custom downloader', ]; + +const SUPPORTED_OS_CATEGORY = [ + 'unix', + 'windows', + 'linux', + 'macos', +]; + +const SUPPORTED_OS_FAMILY = [ + 'Linux', + 'Darwin', + 'Windows', +]; + +const SPC_MODE_SOURCE = 1; +const SPC_MODE_VENDOR = 2; +const SPC_MODE_PHAR = 4; +const SPC_MODE_VENDOR_PHAR = SPC_MODE_VENDOR | SPC_MODE_PHAR; diff --git a/src/globals/functions.php b/src/globals/functions.php index 93cd1ae0..bb22f3a7 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -10,6 +10,31 @@ use StaticPHP\Runtime\Shell\UnixShell; use StaticPHP\Runtime\Shell\WindowsCmd; use ZM\Logger\ConsoleLogger; +/** + * Get the current SPC loading mode. If passed a mode to check, will return whether current mode matches the given mode. + */ +function spc_mode(?int $check_mode = null): bool|int +{ + $mode = SPC_MODE_SOURCE; + // if current file is in phar, then it's phar mode + if (str_starts_with(__FILE__, 'phar://') && Phar::running()) { + // judge whether it's vendor mode (inside vendor/) or source mode (inside src/) + if (basename(dirname(__FILE__, 3)) === 'static-php-cli' && basename(dirname(__FILE__, 5)) === 'vendor') { + $mode = SPC_MODE_VENDOR_PHAR; + } else { + $mode = SPC_MODE_PHAR; + } + } elseif (basename(dirname(__FILE__, 3)) === 'static-php-cli' && basename(dirname(__FILE__, 5)) === 'vendor') { + $mode = SPC_MODE_VENDOR; + } + + if ($check_mode === null) { + return $mode; + } + // use bitwise AND to check mode + return ($mode & $check_mode) !== 0; +} + /** * Judge if an array is an associative array */ diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index f44914ec..e2186c8e 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -14,8 +14,8 @@ declare(strict_types=1); // test php version (8.1 ~ 8.4 available, multiple for matrix) $test_php_version = [ // '8.1', - // '8.2', - // '8.3', + '8.2', + '8.3', '8.4', '8.5', // 'git', @@ -25,11 +25,11 @@ $test_php_version = [ $test_os = [ 'macos-15-intel', // bin/spc for x86_64 'macos-15', // bin/spc for arm64 - // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 + 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 - // 'ubuntu-24.04', // bin/spc for x86_64 + 'ubuntu-24.04', // bin/spc for x86_64 // 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 - 'ubuntu-24.04-arm', // bin/spc for arm64 + // 'ubuntu-24.04-arm', // bin/spc for arm64 // 'windows-2022', // .\bin\spc.ps1 // 'windows-2025', ]; @@ -50,14 +50,14 @@ $prefer_pre_built = false; // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'bcmath', + 'Linux', 'Darwin' => 'mysqli,gmp', 'Windows' => 'bcmath', }; // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). $shared_extensions = match (PHP_OS_FAMILY) { - 'Linux' => 'pcov', - 'Darwin' => 'pcov', + 'Linux' => 'grpc,mysqlnd_parsec,mysqlnd_ed25519', + 'Darwin' => '', 'Windows' => '', }; @@ -66,7 +66,7 @@ $with_suggested_libs = false; // If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true. $with_libs = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => '', + 'Linux', 'Darwin' => 'libwebp', 'Windows' => '', }; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index ba917332..14397d03 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -4,6 +4,6 @@ declare(strict_types=1); use Psr\Log\LogLevel; require_once __DIR__ . '/../src/bootstrap.php'; -\StaticPHP\Registry\Registry::checkLoadedRegistries(); +\StaticPHP\Registry\Registry::resolve(); logger()->setLevel(LogLevel::ERROR);