diff --git a/bin/spc-alpine-docker b/bin/spc-alpine-docker index dc6eaa36..cc223ba0 100755 --- a/bin/spc-alpine-docker +++ b/bin/spc-alpine-docker @@ -122,7 +122,7 @@ COPY ./composer.* /app/ ADD ./bin /app/bin RUN composer install --no-dev ADD ./config /app/config -ADD ./spc.registry.json /app/spc.registry.json +ADD ./spc.registry.yml /app/spc.registry.yml RUN bin/spc doctor --auto-fix RUN bin/spc install-pkg upx diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker deleted file mode 100755 index 286ef985..00000000 --- a/bin/spc-gnu-docker +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# This file is using docker to run commands -SPC_DOCKER_VERSION=v6 - -# Detect docker can run -if ! which docker >/dev/null; then - echo "Docker is not installed, please install docker first !" - exit 1 -fi -DOCKER_EXECUTABLE="docker" -# shellcheck disable=SC2046 -if [ $(id -u) -ne 0 ]; then - if ! docker info > /dev/null 2>&1; then - if [ "$SPC_USE_SUDO" != "yes" ] && [ "$SPC_DOCKER_DEBUG" != "yes" ]; then - echo "Docker command requires sudo" - # shellcheck disable=SC2039 - echo -n 'To use sudo to run docker, run "export SPC_USE_SUDO=yes" and run command again' - exit 1 - fi - DOCKER_EXECUTABLE="sudo docker" - fi -fi - -# Convert uname to gnu arch -CURRENT_ARCH=$(uname -m) -if [ "$CURRENT_ARCH" = "arm64" ]; then - CURRENT_ARCH=aarch64 -fi -if [ -z "$SPC_USE_ARCH" ]; then - SPC_USE_ARCH=$CURRENT_ARCH -fi -# parse SPC_USE_ARCH -case $SPC_USE_ARCH in -x86_64|amd64) - SPC_USE_ARCH=x86_64 - SPC_USE_ARCH_DOCKER=amd64 - if [ "$CURRENT_ARCH" != "x86_64" ]; then - PLATFORM_ARG="--platform linux/amd64" - fi - ;; -aarch64|arm64) - SPC_USE_ARCH=aarch64 - SPC_USE_ARCH_DOCKER=arm64 - if [ "$CURRENT_ARCH" != "aarch64" ]; then - PLATFORM_ARG="--platform linux/arm64" - fi - ;; -*) - echo "Current arch is not supported to run in docker: $SPC_USE_ARCH" - exit 1 - ;; -esac -# detect if we need to use qemu-static -if [ "$SPC_USE_ARCH" != "$CURRENT_ARCH" ]; then - if [ "$(uname -s)" = "Linux" ]; then - echo "* Using different arch needs to setup qemu-static for docker !" - $DOCKER_EXECUTABLE run --rm --privileged multiarch/qemu-user-static --reset -p yes > /dev/null - fi -fi - -# Detect docker env is setup -if ! $DOCKER_EXECUTABLE images | grep -q cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION; then - echo "Docker container does not exist. Building docker image ..." - $DOCKER_EXECUTABLE buildx build $PLATFORM_ARG -t cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION -f- . <> /etc/bashrc -RUN source /etc/bashrc -RUN yum install -y which - -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 - -WORKDIR /app -COPY ./composer.* /app/ -ADD ./bin/setup-runtime /app/bin/setup-runtime -ADD ./bin/spc /app/bin/spc -RUN /app/bin/setup-runtime -ADD ./src /app/src -RUN /app/bin/php /app/bin/composer install --no-dev -ENV SPC_LIBC=glibc -ENV PATH="/app/bin:/cmake/bin:/opt/rh/devtoolset-10/root/usr/bin:\$PATH" - -ADD ./config /app/config -RUN CC=gcc bin/spc doctor --auto-fix --debug -RUN bin/spc install-pkg upx -RUN if [ -f /app/buildroot/bin/re2c ]; then \ - cp /app/buildroot/bin/re2c /usr/local/bin/re2c ;\ - fi - -RUN curl -o make.tgz -fsSL https://ftp.gnu.org/gnu/make/make-4.4.tar.gz && \ - tar -zxvf make.tgz && \ - cd make-4.4 && \ - ./configure && \ - make && \ - make install && \ - ln -sf /usr/local/bin/make /usr/bin/make - -RUN curl -o automake.tgz -fsSL https://ftp.gnu.org/gnu/automake/automake-1.17.tar.xz && \ - tar -xvf automake.tgz && \ - cd automake-1.17 && \ - ./configure && \ - make && \ - make install && \ - ln -sf /usr/local/bin/automake /usr/bin/automake - -RUN mv /app/pkgroot/\$(uname -m)-linux /app/pkgroot-private -ADD bin/docker-entrypoint.sh /bin/docker-entrypoint.sh -RUN chmod +x /bin/docker-entrypoint.sh -ENTRYPOINT ["/bin/docker-entrypoint.sh"] -EOF -fi - -# Check if in ci (local terminal can execute with -it) -if [ -t 0 ]; then - INTERACT=-it -else - INTERACT='' -fi - -# Mounting volumes -MOUNT_LIST="" -# shellcheck disable=SC2089 -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/config:/app/config" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/src:/app/src" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/buildroot:/app/buildroot" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/source:/app/source" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/app/dist" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot" -MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/log:/app/log" -if [ -f "$(pwd)/craft.yml" ]; then - MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/craft.yml:/app/craft.yml" -fi - -# Apply env in temp env file -echo 'SPC_DEFAULT_C_FLAGS=-fPIC' > /tmp/spc-gnu-docker.env -echo 'SPC_LIBC=glibc' >> /tmp/spc-gnu-docker.env - -# Environment variable passthrough -ENV_LIST="" -ENV_LIST="$ENV_LIST -e SPC_FIX_DEPLOY_ROOT="$(pwd)"" -if [ ! -z "$GITHUB_TOKEN" ]; then - ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN" -fi - -# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app -FRANKENPHP_APP_PATH="" -NEW_ARGS=() -while [ $# -gt 0 ]; do - case "$1" in - --with-frankenphp-app=*) - FRANKENPHP_APP_PATH="${1#*=}" - NEW_ARGS+=("--with-frankenphp-app=/app/app") - shift - ;; - --with-frankenphp-app) - if [ -n "${2:-}" ]; then - FRANKENPHP_APP_PATH="$2" - NEW_ARGS+=("--with-frankenphp-app=/app/app") - shift 2 - else - NEW_ARGS+=("$1") - shift - fi - ;; - *) - NEW_ARGS+=("$1") - shift - ;; - esac -done - -# Normalize the path and add mount if provided -if [ -n "$FRANKENPHP_APP_PATH" ]; then - # expand ~ to $HOME - if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then - FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}" - fi - # make absolute if relative - case "$FRANKENPHP_APP_PATH" in - /*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;; - *) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;; - esac - MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app" -fi - -# Run docker -# shellcheck disable=SC2068 -# shellcheck disable=SC2086 -# shellcheck disable=SC2090 - -if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then - echo "* Debug mode enabled, run docker in interactive mode." - echo "* You can use 'exit' to exit the docker container." - echo "* You can use 'bin/spc' like normal builds." - echo "*" - echo "* Mounted directories:" - echo "* ./config: $(pwd)/config" - echo "* ./src: $(pwd)/src" - echo "* ./buildroot: $(pwd)/buildroot" - echo "* ./source: $(pwd)/source" - echo "* ./dist: $(pwd)/dist" - echo "* ./downloads: $(pwd)/downloads" - echo "* ./pkgroot: $(pwd)/pkgroot" - echo "*" - set -ex - $DOCKER_EXECUTABLE run $PLATFORM_ARG --privileged --rm -it $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash -else - $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}" -fi diff --git a/config/artifact.json b/config/artifact.json deleted file mode 100644 index ad8507b9..00000000 --- a/config/artifact.json +++ /dev/null @@ -1,1061 +0,0 @@ -{ - "amqp": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/amqp", - "filename": "amqp.tgz", - "extract": "php-src/ext/amqp" - } - }, - "apcu": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/APCu", - "filename": "apcu.tgz", - "extract": "php-src/ext/apcu" - } - }, - "ast": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/ast", - "filename": "ast.tgz", - "extract": "php-src/ext/ast" - } - }, - "attr": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://download.savannah.nongnu.org/releases/attr/attr-2.5.2.tar.gz" - }, - "source-mirror": { - "type": "url", - "url": "https://mirror.souseiseki.middlendian.com/nongnu/attr/attr-2.5.2.tar.gz" - } - }, - "brotli": { - "binary": "hosted", - "source": { - "type": "ghtagtar", - "repo": "google/brotli", - "match": "v1\\.\\d.*" - } - }, - "bzip2": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/bzip2/bzip2-1.0.8.tar.gz" - }, - "source-mirror": { - "type": "filelist", - "url": "https://sourceware.org/pub/bzip2/", - "regex": "/href=\"(?bzip2-(?[^\"]+)\\.tar\\.gz)\"/" - } - }, - "curl": { - "source": { - "type": "ghrel", - "repo": "curl/curl", - "match": "curl.+\\.tar\\.xz", - "prefer-stable": true - } - }, - "dio": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/dio", - "filename": "dio.tgz", - "extract": "php-src/ext/dio" - } - }, - "ev": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/ev", - "filename": "ev.tgz", - "extract": "php-src/ext/ev" - } - }, - "ext-brotli": { - "source": { - "type": "git", - "rev": "master", - "url": "https://github.com/kjdev/php-ext-brotli", - "extract": "php-src/ext/brotli" - } - }, - "ext-ds": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/ds", - "filename": "ds.tgz", - "extract": "php-src/ext/ds" - } - }, - "ext-event": { - "source": { - "type": "url", - "url": "https://bitbucket.org/osmanov/pecl-event/get/3.0.8.tar.gz", - "extract": "php-src/ext/event" - } - }, - "ext-glfw": { - "source": { - "type": "git", - "url": "https://github.com/mario-deluna/php-glfw", - "rev": "master" - } - }, - "ext-gmssl": { - "source": { - "type": "ghtar", - "repo": "gmssl/GmSSL-PHP", - "extract": "php-src/ext/gmssl" - } - }, - "ext-imagick": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/imagick", - "filename": "imagick.tgz", - "extract": "php-src/ext/imagick" - } - }, - "ext-imap": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/imap", - "filename": "imap.tgz", - "extract": "php-src/ext/imap" - } - }, - "ext-lz4": { - "source": { - "type": "ghtagtar", - "repo": "kjdev/php-ext-lz4", - "extract": "php-src/ext/lz4" - } - }, - "ext-memcache": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/memcache", - "filename": "memcache.tgz", - "extract": "php-src/ext/memcache" - } - }, - "ext-rdkafka": { - "source": { - "type": "ghtar", - "repo": "arnaud-lb/php-rdkafka", - "extract": "php-src/ext/rdkafka" - } - }, - "ext-simdjson": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/simdjson", - "filename": "simdjson.tgz", - "extract": "php-src/ext/simdjson" - } - }, - "ext-snappy": { - "source": { - "type": "git", - "rev": "master", - "url": "https://github.com/kjdev/php-ext-snappy", - "extract": "php-src/ext/snappy" - } - }, - "ext-ssh2": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/ssh2", - "filename": "ssh2.tgz", - "extract": "php-src/ext/ssh2" - } - }, - "ext-trader": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/trader", - "filename": "trader.tgz", - "extract": "php-src/ext/trader" - } - }, - "ext-uuid": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/uuid", - "filename": "uuid.tgz", - "extract": "php-src/ext/uuid" - } - }, - "ext-uv": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/uv", - "filename": "uv.tgz", - "extract": "php-src/ext/uv" - } - }, - "ext-xz": { - "source": { - "type": "git", - "rev": "main", - "url": "https://github.com/codemasher/php-ext-xz", - "extract": "php-src/ext/xz" - } - }, - "ext-zip": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/zip", - "filename": "ext-zip.tgz" - } - }, - "ext-zstd": { - "source": { - "type": "git", - "rev": "master", - "url": "https://github.com/kjdev/php-ext-zstd", - "extract": "php-src/ext/zstd" - } - }, - "fastlz": { - "source": { - "type": "git", - "url": "https://github.com/ariya/FastLZ.git", - "rev": "master" - } - }, - "freetype": { - "source": { - "type": "git", - "rev": "VER-2-13-2", - "url": "https://github.com/freetype/freetype" - } - }, - "gettext": { - "source": { - "type": "filelist", - "url": "https://ftp.gnu.org/pub/gnu/gettext/", - "regex": "/href=\"(?gettext-(?[^\"]+)\\.tar\\.xz)\"/" - } - }, - "gmp": { - "binary": "hosted", - "source": { - "type": "filelist", - "url": "https://gmplib.org/download/gmp/", - "regex": "/href=\"(?gmp-(?[^\"]+)\\.tar\\.xz)\"/" - }, - "source-mirror": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz" - } - }, - "gmssl": { - "binary": "hosted", - "source": { - "type": "ghtar", - "repo": "guanzhi/GmSSL" - } - }, - "go-xcaddy": { - "binary": "custom" - }, - "grpc": { - "binary": "hosted", - "source": { - "type": "git", - "regex": "v(?1.\\d+).x", - "url": "https://github.com/grpc/grpc.git" - } - }, - "icu": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "unicode-org/icu", - "match": "icu4c.+-src\\.tgz", - "prefer-stable": true - } - }, - "icu-static-win": { - "source": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/icu-static-windows-x64/icu-static-windows-x64.zip" - } - }, - "igbinary": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/igbinary", - "filename": "igbinary.tgz", - "extract": "php-src/ext/igbinary" - } - }, - "imagemagick": { - "source": { - "type": "ghtar", - "repo": "ImageMagick/ImageMagick" - } - }, - "imap": { - "source": { - "type": "git", - "url": "https://github.com/static-php/imap.git", - "rev": "master" - } - }, - "inotify": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/inotify", - "filename": "inotify.tgz", - "extract": "php-src/ext/inotify" - } - }, - "jbig": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/jbig/jbigkit-2.1.tar.gz" - }, - "source-mirror": { - "type": "url", - "url": "https://www.cl.cam.ac.uk/~mgk25/jbigkit/download/jbigkit-2.1.tar.gz" - } - }, - "ldap": { - "source": { - "type": "filelist", - "url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/", - "regex": "/href=\"(?openldap-(?[^\"]+)\\.tgz)\"/" - } - }, - "lerc": { - "binary": "hosted", - "source": { - "type": "ghtar", - "repo": "Esri/lerc", - "prefer-stable": true - } - }, - "libacl": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://download.savannah.nongnu.org/releases/acl/acl-2.3.2.tar.gz" - }, - "source-mirror": { - "type": "url", - "url": "https://mirror.souseiseki.middlendian.com/nongnu/acl/acl-2.3.2.tar.gz" - } - }, - "libaom": { - "binary": "hosted", - "source": { - "type": "git", - "rev": "main", - "url": "https://aomedia.googlesource.com/aom" - } - }, - "libargon2": { - "binary": "hosted", - "source": { - "type": "git", - "rev": "master", - "url": "https://github.com/static-php/phc-winner-argon2" - } - }, - "libavif": { - "binary": "hosted", - "source": { - "type": "ghtar", - "repo": "AOMediaCodec/libavif" - } - }, - "libcares": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "c-ares/c-ares", - "match": "c-ares-.+\\.tar\\.gz", - "prefer-stable": true - }, - "source-mirror": { - "type": "filelist", - "url": "https://c-ares.org/download/", - "regex": "/href=\"\\/download\\/(?c-ares-(?[^\"]+)\\.tar\\.gz)\"/" - } - }, - "libde265": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "strukturag/libde265", - "match": "libde265-.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libedit": { - "binary": "hosted", - "source": { - "type": "filelist", - "url": "https://thrysoee.dk/editline/", - "regex": "/href=\"(?libedit-(?[^\"]+)\\.tar\\.gz)\"/" - } - }, - "libevent": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "libevent/libevent", - "match": "libevent.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libffi": { - "source": { - "type": "ghrel", - "repo": "libffi/libffi", - "match": "libffi.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libffi-win": { - "source": { - "type": "git", - "rev": "master", - "url": "https://github.com/static-php/libffi-win.git" - } - }, - "libheif": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "strukturag/libheif", - "match": "libheif-.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libiconv": { - "binary": "hosted", - "source": { - "type": "filelist", - "url": "https://ftp.gnu.org/gnu/libiconv/", - "regex": "/href=\"(?libiconv-(?[^\"]+)\\.tar\\.gz)\"/" - }, - "source-mirror": "https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/libiconv/libiconv-spc-mirror.tar.gz" - }, - "libiconv-win": { - "source": { - "type": "git", - "rev": "master", - "url": "https://github.com/static-php/libiconv-win.git" - } - }, - "libjpeg": { - "source": { - "type": "ghtar", - "repo": "libjpeg-turbo/libjpeg-turbo" - } - }, - "libjxl": { - "source": { - "type": "git", - "url": "https://github.com/libjxl/libjxl", - "rev": "main", - "submodules": [ - "third_party/highway", - "third_party/libjpeg-turbo", - "third_party/sjpeg", - "third_party/skcms" - ] - } - }, - "liblz4": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "lz4/lz4", - "match": "lz4-.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libmemcached": { - "source": { - "type": "ghtagtar", - "repo": "awesomized/libmemcached", - "match": "1.\\d.\\d" - } - }, - "libpng": { - "binary": "hosted", - "source": { - "type": "git", - "url": "https://github.com/glennrp/libpng.git", - "rev": "libpng16" - } - }, - "librabbitmq": { - "source": { - "type": "git", - "url": "https://github.com/alanxz/rabbitmq-c.git", - "rev": "master" - } - }, - "librdkafka": { - "source": { - "type": "ghtar", - "repo": "confluentinc/librdkafka" - } - }, - "libsodium": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "jedisct1/libsodium", - "match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz", - "prefer-stable": true - } - }, - "libssh2": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "libssh2/libssh2", - "match": "libssh2.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libtiff": { - "source": { - "type": "filelist", - "url": "https://download.osgeo.org/libtiff/", - "regex": "/href=\"(?tiff-(?[^\"]+)\\.tar\\.xz)\"/" - } - }, - "liburing": { - "source": { - "type": "ghtar", - "repo": "axboe/liburing", - "prefer-stable": true - } - }, - "libuuid": { - "source": { - "type": "git", - "url": "https://github.com/static-php/libuuid.git", - "rev": "master" - } - }, - "libuv": { - "source": { - "type": "ghtar", - "repo": "libuv/libuv" - } - }, - "libwebp": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://github.com/webmproject/libwebp/archive/refs/tags/v1.3.2.tar.gz" - } - }, - "libxml2": { - "source": { - "type": "url", - "url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.12.5.tar.gz" - } - }, - "libxslt": { - "source": { - "type": "filelist", - "url": "https://download.gnome.org/sources/libxslt/1.1/", - "regex": "/href=\"(?libxslt-(?[^\"]+)\\.tar\\.xz)\"/" - } - }, - "libyaml": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "yaml/libyaml", - "match": "yaml-.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "libzip": { - "source": { - "type": "ghrel", - "repo": "nih-at/libzip", - "match": "libzip.+\\.tar\\.xz", - "prefer-stable": true - } - }, - "memcached": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/memcached", - "filename": "memcached.tgz", - "extract": "php-src/ext/memcached" - } - }, - "micro": { - "source": { - "type": "git", - "extract": "php-src/sapi/micro", - "rev": "master", - "url": "https://github.com/static-php/phpmicro" - } - }, - "mimalloc": { - "source": { - "type": "ghtagtar", - "repo": "microsoft/mimalloc", - "match": "v2\\.\\d\\.[^3].*" - } - }, - "mongodb": { - "source": { - "type": "ghrel", - "repo": "mongodb/mongo-php-driver", - "match": "mongodb.+\\.tgz", - "prefer-stable": true, - "extract": "php-src/ext/mongodb" - } - }, - "msgpack": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/msgpack", - "filename": "msgpack.tgz", - "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": { - "type": "filelist", - "url": "https://ftp.gnu.org/pub/gnu/ncurses/", - "regex": "/href=\"(?ncurses-(?[^\"]+)\\.tar\\.gz)\"/" - } - }, - "net-snmp": { - "source": { - "type": "ghtagtar", - "repo": "net-snmp/net-snmp" - } - }, - "nghttp2": { - "source": { - "type": "ghrel", - "repo": "nghttp2/nghttp2", - "match": "nghttp2.+\\.tar\\.xz", - "prefer-stable": true - } - }, - "nghttp3": { - "source": { - "type": "ghrel", - "repo": "ngtcp2/nghttp3", - "match": "nghttp3.+\\.tar\\.xz", - "prefer-stable": true - } - }, - "ngtcp2": { - "source": { - "type": "ghrel", - "repo": "ngtcp2/ngtcp2", - "match": "ngtcp2.+\\.tar\\.xz", - "prefer-stable": true - } - }, - "onig": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "kkos/oniguruma", - "match": "onig-.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "openssl": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "openssl/openssl", - "match": "openssl.+\\.tar\\.gz", - "prefer-stable": true - }, - "source-mirror": { - "type": "filelist", - "url": "https://www.openssl.org/source/", - "regex": "/href=\"(?openssl-(?[^\"]+)\\.tar\\.gz)\"/" - } - }, - "opentelemetry": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/opentelemetry", - "filename": "opentelemetry.tgz", - "extract": "php-src/ext/opentelemetry" - } - }, - "parallel": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/parallel", - "filename": "parallel.tgz", - "extract": "php-src/ext/parallel" - } - }, - "pdo_sqlsrv": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/pdo_sqlsrv", - "filename": "pdo_sqlsrv.tgz", - "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", - "repo": "postgres/postgres", - "match": "REL_18_\\d+" - } - }, - "postgresql-win": { - "source": { - "type": "url", - "url": "https://get.enterprisedb.com/postgresql/postgresql-16.8-1-windows-x64-binaries.zip" - } - }, - "protobuf": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/protobuf", - "filename": "protobuf.tgz", - "extract": "php-src/ext/protobuf" - } - }, - "pthreads4w": { - "source": { - "type": "git", - "rev": "master", - "url": "https://git.code.sf.net/p/pthreads4w/code" - } - }, - "qdbm": { - "source": { - "type": "git", - "url": "https://github.com/static-php/qdbm.git", - "rev": "main" - } - }, - "rar": { - "source": { - "type": "git", - "url": "https://github.com/static-php/php-rar.git", - "rev": "issue-php82", - "extract": "php-src/ext/rar" - } - }, - "re2c": { - "source": { - "type": "ghrel", - "repo": "skvadrik/re2c", - "match": "re2c.+\\.tar\\.xz", - "prefer-stable": true - }, - "source-mirror": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/re2c/re2c-4.3.tar.xz" - } - }, - "readline": { - "binary": "hosted", - "source": { - "type": "filelist", - "url": "https://ftp.gnu.org/pub/gnu/readline/", - "regex": "/href=\"(?readline-(?[^\"]+)\\.tar\\.gz)\"/" - } - }, - "redis": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/redis", - "filename": "redis.tgz", - "extract": "php-src/ext/redis" - } - }, - "snappy": { - "source": { - "type": "git", - "rev": "main", - "url": "https://github.com/google/snappy" - } - }, - "spx": { - "source": { - "type": "pie", - "repo": "noisebynorthwest/php-spx", - "extract": "php-src/ext/spx" - } - }, - "sqlite": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://www.sqlite.org/2024/sqlite-autoconf-3450200.tar.gz" - } - }, - "sqlsrv": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/sqlsrv", - "filename": "sqlsrv.tgz", - "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", - "repo": "swoole/swoole-src", - "match": "v6\\.+", - "prefer-stable": true, - "extract": "php-src/ext/swoole" - } - }, - "swow": { - "source": { - "type": "ghtar", - "repo": "swow/swow", - "prefer-stable": true, - "extract": "php-src/ext/swow-src" - } - }, - "tidy": { - "source": { - "type": "ghtar", - "repo": "htacg/tidy-html5", - "prefer-stable": true - } - }, - "unixodbc": { - "binary": "hosted", - "source": { - "type": "url", - "url": "https://www.unixodbc.org/unixODBC-2.3.12.tar.gz", - "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", - "repo": "e-dant/watcher", - "prefer-stable": true - } - }, - "xdebug": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/xdebug", - "filename": "xdebug.tgz" - } - }, - "xhprof": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/xhprof", - "filename": "xhprof.tgz", - "extract": "php-src/ext/xhprof-src" - } - }, - "xlswriter": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/xlswriter", - "filename": "xlswriter.tgz", - "extract": "php-src/ext/xlswriter" - } - }, - "xz": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "tukaani-project/xz", - "match": "xz.+\\.tar\\.xz", - "prefer-stable": true - }, - "source-mirror": { - "type": "url", - "url": "https://github.com/tukaani-project/xz/releases/download/v5.8.1/xz-5.8.1.tar.gz" - } - }, - "yac": { - "source": { - "type": "url", - "url": "https://pecl.php.net/get/yac", - "filename": "yac.tgz", - "extract": "php-src/ext/yac" - } - }, - "yaml": { - "source": { - "type": "git", - "rev": "php7", - "url": "https://github.com/php/pecl-file_formats-yaml", - "extract": "php-src/ext/yaml" - } - }, - "zig": { - "binary": "custom" - }, - "zlib": { - "binary": "hosted", - "source": { - "type": "ghrel", - "repo": "madler/zlib", - "match": "zlib.+\\.tar\\.gz", - "prefer-stable": true - } - }, - "zstd": { - "source": { - "type": "ghrel", - "repo": "facebook/zstd", - "match": "zstd.+\\.tar\\.gz", - "prefer-stable": true - } - } -} diff --git a/config/ext.json b/config/ext.json deleted file mode 100644 index 16a71c21..00000000 --- a/config/ext.json +++ /dev/null @@ -1,1293 +0,0 @@ -{ - "amqp": { - "support": { - "BSD": "wip" - }, - "type": "external", - "arg-type": "custom", - "source": "amqp", - "lib-depends": [ - "librabbitmq" - ], - "ext-depends-windows": [ - "openssl" - ] - }, - "apcu": { - "type": "external", - "source": "apcu" - }, - "ast": { - "type": "external", - "source": "ast" - }, - "bcmath": { - "type": "builtin" - }, - "brotli": { - "type": "external", - "source": "ext-brotli", - "arg-type": "enable", - "lib-depends": [ - "brotli" - ] - }, - "bz2": { - "type": "builtin", - "arg-type-unix": "with-path", - "arg-type-windows": "with", - "lib-depends": [ - "bzip2" - ] - }, - "calendar": { - "type": "builtin" - }, - "com_dotnet": { - "support": { - "BSD": "no", - "Linux": "no", - "Darwin": "no" - }, - "type": "builtin" - }, - "ctype": { - "type": "builtin" - }, - "curl": { - "notes": true, - "type": "builtin", - "arg-type": "with", - "lib-depends": [ - "curl" - ], - "ext-depends-windows": [ - "zlib", - "openssl", - "brotli" - ] - }, - "dba": { - "type": "builtin", - "arg-type": "custom", - "lib-suggests": [ - "qdbm" - ] - }, - "dio": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "dio" - }, - "dom": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "custom", - "arg-type-windows": "with", - "lib-depends": [ - "libxml2", - "zlib" - ], - "ext-depends-windows": [ - "xml" - ] - }, - "ds": { - "type": "external", - "source": "ext-ds" - }, - "enchant": { - "support": { - "Windows": "wip", - "BSD": "wip", - "Darwin": "wip", - "Linux": "wip" - }, - "type": "wip" - }, - "ev": { - "type": "external", - "source": "ev", - "arg-type-windows": "with", - "ext-depends": [ - "sockets" - ] - }, - "event": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "ext-event", - "arg-type": "custom", - "lib-depends": [ - "libevent" - ], - "ext-depends": [ - "openssl" - ], - "ext-suggests": [ - "sockets" - ] - }, - "excimer": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-excimer" - }, - "exif": { - "type": "builtin" - }, - "ffi": { - "support": { - "Linux": "partial", - "BSD": "wip" - }, - "notes": true, - "arg-type": "custom", - "type": "builtin", - "lib-depends-unix": [ - "libffi" - ], - "lib-depends-windows": [ - "libffi-win" - ] - }, - "fileinfo": { - "type": "builtin" - }, - "filter": { - "type": "builtin" - }, - "ftp": { - "type": "builtin", - "lib-suggests": [ - "openssl" - ] - }, - "gd": { - "support": { - "BSD": "wip" - }, - "notes": true, - "type": "builtin", - "arg-type": "custom", - "arg-type-windows": "with", - "lib-depends": [ - "zlib", - "libpng" - ], - "ext-depends": [ - "zlib" - ], - "lib-suggests": [ - "libavif", - "libwebp", - "libjpeg", - "freetype" - ] - }, - "gettext": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "lib-depends": [ - "gettext" - ] - }, - "glfw": { - "support": { - "Windows": "wip", - "BSD": "no", - "Linux": "no" - }, - "notes": true, - "type": "external", - "arg-type": "custom", - "source": "ext-glfw", - "lib-depends": [ - "glfw" - ], - "lib-depends-windows": [] - }, - "gmp": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "lib-depends": [ - "gmp" - ] - }, - "gmssl": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "ext-gmssl", - "lib-depends": [ - "gmssl" - ] - }, - "grpc": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-grpc", - "arg-type-unix": "enable-path", - "cpp-extension": true, - "lib-depends": [ - "grpc", - "zlib", - "openssl", - "libcares" - ] - }, - "iconv": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "arg-type-windows": "with", - "lib-depends-unix": [ - "libiconv" - ], - "lib-depends-windows": [ - "libiconv-win" - ] - }, - "igbinary": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "igbinary", - "ext-suggests": [ - "session", - "apcu" - ] - }, - "imagick": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "ext-imagick", - "arg-type": "custom", - "lib-depends": [ - "imagemagick" - ] - }, - "imap": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "ext-imap", - "arg-type": "custom", - "lib-depends": [ - "imap" - ], - "ext-suggests": [ - "openssl" - ] - }, - "inotify": { - "support": { - "Windows": "no", - "BSD": "wip", - "Darwin": "no" - }, - "type": "external", - "source": "inotify" - }, - "intl": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "lib-depends-unix": [ - "icu" - ], - "lib-depends-windows": [ - "icu-static-win" - ] - }, - "ldap": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "lib-depends": [ - "ldap" - ], - "lib-suggests": [ - "gmp", - "libsodium" - ], - "ext-suggests": [ - "openssl" - ] - }, - "libxml": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "none", - "ext-depends": [ - "xml" - ], - "build-with-php": true, - "target": [ - "static" - ] - }, - "lz4": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-lz4", - "arg-type": "custom", - "lib-depends": [ - "liblz4" - ] - }, - "maxminddb": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "type": "external", - "source": "ext-maxminddb", - "arg-type": "with", - "lib-depends": [ - "libmaxminddb" - ] - }, - "mbregex": { - "type": "builtin", - "arg-type": "custom", - "target": [ - "static" - ], - "ext-depends": [ - "mbstring" - ], - "lib-depends": [ - "onig" - ] - }, - "mbstring": { - "type": "builtin", - "arg-type": "custom" - }, - "mcrypt": { - "type": "wip", - "support": { - "Windows": "no", - "BSD": "no", - "Darwin": "no", - "Linux": "no" - }, - "notes": true - }, - "memcache": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-memcache", - "arg-type": "custom", - "ext-depends": [ - "zlib", - "session" - ] - }, - "memcached": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "memcached", - "arg-type": "custom", - "cpp-extension": true, - "lib-depends": [ - "libmemcached" - ], - "lib-depends-unix": [ - "libmemcached", - "fastlz" - ], - "lib-suggests": [ - "zstd" - ], - "ext-depends": [ - "session", - "zlib" - ], - "ext-suggests": [ - "igbinary", - "msgpack", - "session" - ] - }, - "mongodb": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "type": "external", - "source": "mongodb", - "arg-type": "custom", - "lib-suggests": [ - "icu", - "openssl", - "zstd", - "zlib" - ], - "frameworks": [ - "CoreFoundation", - "Security" - ] - }, - "msgpack": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "msgpack", - "arg-type-unix": "with", - "arg-type-windows": "enable", - "ext-depends": [ - "session" - ] - }, - "mysqli": { - "type": "builtin", - "arg-type": "with", - "build-with-php": true, - "ext-depends": [ - "mysqlnd" - ] - }, - "mysqlnd": { - "type": "builtin", - "arg-type-windows": "with", - "build-with-php": true, - "lib-depends": [ - "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": { - "Windows": "wip", - "BSD": "no", - "Darwin": "no", - "Linux": "no" - }, - "notes": true - }, - "odbc": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "type": "builtin", - "arg-type-unix": "custom", - "lib-depends-unix": [ - "unixodbc" - ] - }, - "opcache": { - "type": "builtin", - "arg-type-unix": "custom", - "arg-type-windows": "enable", - "zend-extension": true - }, - "openssl": { - "notes": true, - "type": "builtin", - "arg-type": "custom", - "arg-type-windows": "with", - "build-with-php": true, - "lib-depends": [ - "openssl", - "zlib" - ], - "ext-depends": [ - "zlib" - ] - }, - "opentelemetry": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "opentelemetry" - }, - "parallel": { - "support": { - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "parallel", - "arg-type-windows": "with", - "lib-depends-windows": [ - "pthreads4w" - ] - }, - "password-argon2": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "notes": true, - "type": "builtin", - "arg-type": "custom", - "lib-depends": [ - "libargon2", - "openssl" - ] - }, - "pcntl": { - "support": { - "Windows": "no" - }, - "type": "builtin", - "unix-only": true - }, - "pcov": { - "type": "external", - "source": "pcov", - "target": [ - "shared" - ] - }, - "pdo": { - "type": "builtin" - }, - "pdo_mysql": { - "type": "builtin", - "arg-type": "with", - "ext-depends": [ - "pdo", - "mysqlnd" - ] - }, - "pdo_odbc": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "custom", - "lib-depends-unix": [ - "unixodbc" - ], - "ext-depends": [ - "pdo", - "odbc" - ] - }, - "pdo_pgsql": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "arg-type-windows": "custom", - "ext-depends": [ - "pdo", - "pgsql" - ], - "lib-depends-unix": [ - "postgresql" - ], - "lib-depends-windows": [ - "postgresql-win" - ] - }, - "pdo_sqlite": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with", - "ext-depends": [ - "pdo", - "sqlite3" - ], - "lib-depends": [ - "sqlite" - ] - }, - "pdo_sqlsrv": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "pdo_sqlsrv", - "arg-type": "with", - "ext-depends": [ - "pdo", - "sqlsrv" - ] - }, - "pgsql": { - "support": { - "BSD": "wip" - }, - "notes": true, - "type": "builtin", - "arg-type": "custom", - "lib-depends-unix": [ - "postgresql" - ], - "lib-depends-windows": [ - "postgresql-win" - ] - }, - "phar": { - "type": "builtin", - "ext-depends": [ - "zlib" - ] - }, - "posix": { - "support": { - "Windows": "no" - }, - "type": "builtin", - "unix-only": true - }, - "protobuf": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "protobuf" - }, - "rar": { - "support": { - "BSD": "wip", - "Darwin": "partial" - }, - "notes": true, - "type": "external", - "source": "rar", - "cpp-extension": true - }, - "rdkafka": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "type": "external", - "source": "ext-rdkafka", - "arg-type": "custom", - "cpp-extension": true, - "lib-depends": [ - "librdkafka" - ] - }, - "readline": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "lib-depends": [ - "libedit" - ], - "target": [ - "static" - ] - }, - "redis": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "redis", - "arg-type": "custom", - "ext-suggests": [ - "session", - "igbinary", - "msgpack" - ], - "lib-suggests-unix": [ - "zstd", - "liblz4" - ] - }, - "session": { - "type": "builtin", - "build-with-php": true - }, - "shmop": { - "type": "builtin", - "build-with-php": true - }, - "simdjson": { - "type": "external", - "source": "ext-simdjson", - "cpp-extension": true - }, - "simplexml": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "custom", - "lib-depends": [ - "libxml2" - ], - "ext-depends-windows": [ - "xml" - ], - "build-with-php": true - }, - "snappy": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-snappy", - "cpp-extension": true, - "arg-type": "custom", - "lib-depends": [ - "snappy" - ], - "ext-suggests": [ - "apcu" - ] - }, - "snmp": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type-unix": "with", - "arg-type-windows": "with", - "lib-depends": [ - "net-snmp" - ] - }, - "soap": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "custom", - "ext-depends": [ - "libxml", - "session" - ] - }, - "sockets": { - "type": "builtin" - }, - "sodium": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with", - "lib-depends": [ - "libsodium" - ] - }, - "spx": { - "support": { - "BSD": "wip", - "Windows": "no" - }, - "notes": true, - "type": "external", - "source": "spx", - "arg-type": "custom", - "lib-depends": [ - "zlib" - ] - }, - "sqlite3": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "arg-type-windows": "with", - "build-with-php": true, - "lib-depends": [ - "sqlite" - ] - }, - "sqlsrv": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "sqlsrv", - "lib-depends-unix": [ - "unixodbc" - ], - "ext-depends-linux": [ - "pcntl" - ], - "cpp-extension": true - }, - "ssh2": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "ext-ssh2", - "arg-type": "with-path", - "arg-type-windows": "with", - "lib-depends": [ - "libssh2" - ], - "ext-depends": [ - "openssl", - "zlib" - ] - }, - "swoole": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "swoole", - "arg-type": "custom", - "cpp-extension": true, - "unix-only": true, - "lib-depends": [ - "libcares", - "brotli", - "nghttp2", - "zlib" - ], - "lib-suggests": [ - "zstd" - ], - "lib-suggests-linux": [ - "zstd", - "liburing" - ], - "ext-depends": [ - "openssl", - "curl" - ], - "ext-suggests": [ - "sockets", - "swoole-hook-pgsql", - "swoole-hook-mysql", - "swoole-hook-sqlite", - "swoole-hook-odbc" - ] - }, - "swoole-hook-mysql": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "notes": true, - "type": "addon", - "arg-type": "none", - "ext-depends": [ - "mysqlnd", - "pdo", - "pdo_mysql", - "swoole" - ], - "ext-suggests": [ - "mysqli" - ] - }, - "swoole-hook-odbc": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "notes": true, - "type": "addon", - "arg-type": "none", - "ext-depends": [ - "pdo", - "swoole" - ], - "lib-depends": [ - "unixodbc" - ] - }, - "swoole-hook-pgsql": { - "support": { - "Windows": "no", - "BSD": "wip", - "Darwin": "partial" - }, - "notes": true, - "type": "addon", - "arg-type": "none", - "ext-depends": [ - "pgsql", - "pdo", - "swoole" - ] - }, - "swoole-hook-sqlite": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "notes": true, - "type": "addon", - "arg-type": "none", - "ext-depends": [ - "sqlite3", - "pdo", - "swoole" - ] - }, - "swow": { - "support": { - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "swow", - "arg-type": "custom", - "lib-suggests": [ - "openssl", - "curl" - ], - "ext-suggests": [ - "openssl", - "curl" - ] - }, - "sysvmsg": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "type": "builtin", - "unix-only": true - }, - "sysvsem": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "type": "builtin", - "unix-only": true - }, - "sysvshm": { - "support": { - "BSD": "wip" - }, - "type": "builtin" - }, - "tidy": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "lib-depends": [ - "tidy" - ] - }, - "tokenizer": { - "type": "builtin", - "build-with-php": true - }, - "trader": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "type": "external", - "source": "ext-trader" - }, - "uuid": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-uuid", - "arg-type": "with-path", - "lib-depends": [ - "libuuid" - ] - }, - "uv": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-uv", - "arg-type": "with-path", - "lib-depends": [ - "libuv" - ], - "ext-depends": [ - "sockets" - ] - }, - "xdebug": { - "type": "external", - "source": "xdebug", - "target": [ - "shared" - ], - "support": { - "Windows": "wip", - "BSD": "no", - "Darwin": "partial", - "Linux": "partial" - }, - "notes": true, - "zend-extension": true - }, - "xhprof": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "notes": true, - "type": "external", - "source": "xhprof", - "ext-depends": [ - "ctype" - ], - "build-with-php": true - }, - "xlswriter": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "xlswriter", - "arg-type": "custom", - "ext-depends": [ - "zlib", - "zip" - ], - "lib-suggests": [ - "openssl" - ] - }, - "xml": { - "support": { - "BSD": "wip" - }, - "notes": true, - "type": "builtin", - "arg-type": "custom", - "arg-type-windows": "with", - "lib-depends": [ - "libxml2" - ], - "ext-depends-windows": [ - "iconv" - ], - "build-with-php": true - }, - "xmlreader": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "custom", - "lib-depends": [ - "libxml2" - ], - "ext-depends-windows": [ - "xml", - "dom" - ], - "build-with-php": true - }, - "xmlwriter": { - "support": { - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "custom", - "lib-depends": [ - "libxml2" - ], - "ext-depends-windows": [ - "xml" - ], - "build-with-php": true - }, - "xsl": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "builtin", - "arg-type": "with-path", - "lib-depends": [ - "libxslt" - ], - "ext-depends": [ - "xml", - "dom" - ] - }, - "xz": { - "type": "external", - "source": "ext-xz", - "arg-type": "with", - "lib-depends": [ - "xz" - ] - }, - "yac": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "yac", - "arg-type-unix": "custom", - "lib-depends-unix": [ - "fastlz" - ], - "ext-depends-unix": [ - "igbinary" - ] - }, - "yaml": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "yaml", - "arg-type-unix": "with-path", - "arg-type-windows": "with", - "lib-depends": [ - "libyaml" - ] - }, - "zip": { - "support": { - "BSD": "wip" - }, - "type": "external", - "source": "ext-zip", - "arg-type": "custom", - "arg-type-windows": "enable", - "lib-depends-unix": [ - "libzip" - ], - "ext-depends-windows": [ - "zlib", - "bz2" - ], - "lib-depends-windows": [ - "libzip", - "zlib", - "bzip2", - "xz" - ] - }, - "zlib": { - "type": "builtin", - "arg-type": "custom", - "arg-type-windows": "enable", - "lib-depends": [ - "zlib" - ], - "build-with-php": true, - "target": [ - "static" - ] - }, - "zstd": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "type": "external", - "source": "ext-zstd", - "arg-type": "custom", - "lib-depends": [ - "zstd" - ] - } -} diff --git a/config/lib.json b/config/lib.json deleted file mode 100644 index 4792a932..00000000 --- a/config/lib.json +++ /dev/null @@ -1,1066 +0,0 @@ -{ - "lib-base": { - "type": "root" - }, - "php": { - "type": "root", - "source": "php-src", - "lib-depends": [ - "lib-base", - "micro", - "frankenphp" - ], - "lib-depends-macos": [ - "lib-base", - "micro", - "libxml2", - "frankenphp" - ], - "lib-suggests-linux": [ - "libacl", - "brotli", - "watcher" - ], - "lib-suggests-macos": [ - "brotli", - "watcher" - ] - }, - "frankenphp": { - "source": "frankenphp", - "type": "target" - }, - "micro": { - "type": "target", - "source": "micro" - }, - "pkg-config": { - "type": "package", - "source": "pkg-config", - "bin-unix": [ - "pkg-config" - ] - }, - "attr": { - "source": "attr", - "static-libs-unix": [ - "libattr.a" - ] - }, - "brotli": { - "source": "brotli", - "pkg-configs": [ - "libbrotlicommon", - "libbrotlidec", - "libbrotlienc" - ], - "static-libs-windows": [ - "brotlicommon.lib", - "brotlienc.lib", - "brotlidec.lib" - ], - "headers": [ - "brotli" - ] - }, - "bzip2": { - "source": "bzip2", - "static-libs-unix": [ - "libbz2.a" - ], - "static-libs-windows": [ - "libbz2.lib", - "libbz2_a.lib" - ], - "headers": [ - "bzlib.h" - ] - }, - "curl": { - "source": "curl", - "static-libs-unix": [ - "libcurl.a" - ], - "static-libs-windows": [ - "libcurl_a.lib" - ], - "headers": [ - "curl" - ], - "lib-depends-unix": [ - "openssl", - "zlib" - ], - "lib-depends-windows": [ - "zlib", - "libssh2", - "nghttp2" - ], - "lib-suggests-unix": [ - "libssh2", - "brotli", - "nghttp2", - "nghttp3", - "ngtcp2", - "zstd", - "libcares", - "ldap", - "idn2", - "krb5" - ], - "lib-suggests-windows": [ - "brotli" - ], - "frameworks": [ - "CoreFoundation", - "CoreServices", - "SystemConfiguration" - ] - }, - "fastlz": { - "source": "fastlz", - "static-libs-unix": [ - "libfastlz.a" - ], - "headers": [ - "fastlz/fastlz.h" - ] - }, - "freetype": { - "source": "freetype", - "static-libs-unix": [ - "libfreetype.a" - ], - "static-libs-windows": [ - "libfreetype_a.lib" - ], - "headers-unix": [ - "freetype2/freetype/freetype.h", - "freetype2/ft2build.h" - ], - "lib-depends": [ - "zlib" - ], - "lib-suggests": [ - "libpng" - ] - }, - "gettext": { - "source": "gettext", - "static-libs-unix": [ - "libintl.a" - ], - "lib-depends": [ - "libiconv" - ], - "lib-suggests": [ - "ncurses", - "libxml2" - ], - "frameworks": [ - "CoreFoundation" - ] - }, - "glfw": { - "source": "ext-glfw", - "static-libs-unix": [ - "libglfw3.a" - ], - "frameworks": [ - "CoreVideo", - "OpenGL", - "Cocoa", - "IOKit" - ] - }, - "gmp": { - "source": "gmp", - "static-libs-unix": [ - "libgmp.a" - ], - "static-libs-windows": [ - "libgmp.lib" - ], - "headers": [ - "gmp.h" - ] - }, - "gmssl": { - "source": "gmssl", - "static-libs-unix": [ - "libgmssl.a" - ], - "static-libs-windows": [ - "gmssl.lib" - ], - "frameworks": [ - "Security" - ] - }, - "grpc": { - "source": "grpc", - "pkg-configs": [ - "grpc" - ], - "lib-depends": [ - "zlib", - "openssl", - "libcares" - ], - "cpp-library": true, - "frameworks": [ - "CoreFoundation" - ] - }, - "icu": { - "source": "icu", - "cpp-library": true, - "pkg-configs": [ - "icu-uc", - "icu-i18n", - "icu-io" - ] - }, - "icu-static-win": { - "source": "icu-static-win", - "static-libs-windows": [ - "icudt.lib", - "icuin.lib", - "icuio.lib", - "icuuc.lib" - ], - "headers-windows": [ - "unicode" - ] - }, - "idn2": { - "source": "libidn2", - "pkg-configs": [ - "libidn2" - ], - "headers": [ - "idn2.h" - ], - "lib-suggests-unix": [ - "libiconv", - "gettext", - "libunistring" - ], - "lib-depends-macos": [ - "libiconv", - "gettext" - ] - }, - "imagemagick": { - "source": "imagemagick", - "cpp-library": true, - "pkg-configs": [ - "Magick++-7.Q16HDRI", - "MagickCore-7.Q16HDRI", - "MagickWand-7.Q16HDRI" - ], - "lib-depends": [ - "zlib", - "libjpeg", - "libjxl", - "libpng", - "libwebp", - "freetype", - "libtiff", - "libheif", - "bzip2" - ], - "lib-suggests": [ - "zstd", - "xz", - "libzip", - "libxml2" - ] - }, - "imap": { - "source": "imap", - "static-libs-unix": [ - "libc-client.a" - ], - "lib-suggests": [ - "openssl" - ] - }, - "jbig": { - "source": "jbig", - "static-libs-unix": [ - "libjbig.a", - "libjbig85.a" - ], - "headers": [ - "jbig.h", - "jbig85.h", - "jbig_ar.h" - ] - }, - "krb5": { - "source": "krb5", - "pkg-configs": [ - "krb5-gssapi" - ], - "headers": [ - "krb5.h", - "gssapi/gssapi.h" - ], - "lib-depends": [ - "openssl" - ], - "lib-suggests": [ - "ldap", - "libedit" - ], - "frameworks": [ - "Kerberos" - ] - }, - "ldap": { - "source": "ldap", - "pkg-configs": [ - "ldap", - "lber" - ], - "lib-depends": [ - "openssl", - "zlib", - "gmp", - "libsodium" - ] - }, - "lerc": { - "source": "lerc", - "static-libs-unix": [ - "libLerc.a" - ], - "cpp-library": true - }, - "libacl": { - "source": "libacl", - "static-libs-unix": [ - "libacl.a" - ], - "lib-depends": [ - "attr" - ] - }, - "libaom": { - "source": "libaom", - "static-libs-unix": [ - "libaom.a" - ], - "static-libs-windows": [ - "aom.lib" - ], - "cpp-library": true - }, - "libargon2": { - "source": "libargon2", - "static-libs-unix": [ - "libargon2.a" - ], - "lib-suggests": [ - "libsodium" - ] - }, - "libavif": { - "source": "libavif", - "static-libs-unix": [ - "libavif.a" - ], - "static-libs-windows": [ - "avif.lib" - ], - "lib-depends": [ - "libaom" - ], - "lib-suggests": [ - "libwebp", - "libjpeg", - "libxml2", - "libpng" - ] - }, - "libcares": { - "source": "libcares", - "static-libs-unix": [ - "libcares.a" - ], - "headers-unix": [ - "ares.h", - "ares_dns.h", - "ares_nameser.h" - ] - }, - "libde265": { - "source": "libde265", - "static-libs-unix": [ - "libde265.a" - ], - "cpp-library": true - }, - "libedit": { - "source": "libedit", - "static-libs-unix": [ - "libedit.a" - ], - "lib-depends": [ - "ncurses" - ] - }, - "libevent": { - "source": "libevent", - "static-libs-unix": [ - "libevent.a", - "libevent_core.a", - "libevent_extra.a", - "libevent_openssl.a" - ], - "lib-depends": [ - "openssl" - ] - }, - "libffi": { - "source": "libffi", - "static-libs-unix": [ - "libffi.a" - ], - "static-libs-windows": [ - "libffi.lib" - ], - "headers-unix": [ - "ffi.h", - "ffitarget.h" - ], - "headers-windows": [ - "ffi.h", - "fficonfig.h", - "ffitarget.h" - ] - }, - "libffi-win": { - "source": "libffi-win", - "static-libs-windows": [ - "libffi.lib" - ], - "headers-windows": [ - "ffi.h", - "ffitarget.h", - "fficonfig.h" - ] - }, - "libheif": { - "source": "libheif", - "static-libs-unix": [ - "libheif.a" - ], - "lib-depends": [ - "libde265", - "libwebp", - "libaom", - "zlib", - "brotli" - ] - }, - "libiconv": { - "source": "libiconv", - "static-libs-unix": [ - "libiconv.a", - "libcharset.a" - ], - "headers": [ - "iconv.h", - "libcharset.h", - "localcharset.h" - ] - }, - "libiconv-win": { - "source": "libiconv-win", - "static-libs-windows": [ - "libiconv.lib", - "libiconv_a.lib" - ] - }, - "libjpeg": { - "source": "libjpeg", - "static-libs-unix": [ - "libjpeg.a", - "libturbojpeg.a" - ], - "static-libs-windows": [ - "libjpeg_a.lib" - ], - "lib-depends": [ - "zlib" - ] - }, - "libjxl": { - "source": "libjxl", - "pkg-configs": [ - "libjxl", - "libjxl_cms", - "libjxl_threads", - "libhwy" - ], - "lib-depends": [ - "brotli", - "libjpeg", - "libpng", - "libwebp" - ] - }, - "liblz4": { - "source": "liblz4", - "static-libs-unix": [ - "liblz4.a" - ] - }, - "libmaxminddb": { - "source": "libmaxminddb", - "static-libs-unix": [ - "libmaxminddb.a" - ], - "headers": [ - "maxminddb.h", - "maxminddb_config.h" - ] - }, - "libmemcached": { - "source": "libmemcached", - "cpp-library": true, - "static-libs-unix": [ - "libmemcached.a", - "libmemcachedprotocol.a", - "libmemcachedutil.a", - "libhashkit.a" - ] - }, - "libpng": { - "source": "libpng", - "static-libs-unix": [ - "libpng16.a" - ], - "static-libs-windows": [ - "libpng16_static.lib", - "libpng_a.lib" - ], - "headers-unix": [ - "png.h", - "pngconf.h", - "pnglibconf.h" - ], - "headers-windows": [ - "png.h", - "pngconf.h" - ], - "lib-depends": [ - "zlib" - ] - }, - "librabbitmq": { - "source": "librabbitmq", - "static-libs-unix": [ - "librabbitmq.a" - ], - "static-libs-windows": [ - "rabbitmq.4.lib" - ], - "lib-depends": [ - "openssl" - ] - }, - "librdkafka": { - "source": "librdkafka", - "pkg-configs": [ - "rdkafka++-static", - "rdkafka-static" - ], - "cpp-library": true, - "lib-suggests": [ - "curl", - "liblz4", - "openssl", - "zlib", - "zstd" - ] - }, - "libsodium": { - "source": "libsodium", - "static-libs-unix": [ - "libsodium.a" - ], - "static-libs-windows": [ - "libsodium.lib" - ] - }, - "libssh2": { - "source": "libssh2", - "static-libs-unix": [ - "libssh2.a" - ], - "static-libs-windows": [ - "libssh2.lib" - ], - "headers": [ - "libssh2.h", - "libssh2_publickey.h", - "libssh2_sftp.h" - ], - "lib-depends": [ - "openssl" - ] - }, - "libtiff": { - "source": "libtiff", - "static-libs-unix": [ - "libtiff.a" - ], - "lib-depends": [ - "zlib", - "libjpeg" - ], - "lib-suggests-unix": [ - "lerc", - "libwebp", - "jbig", - "xz", - "zstd" - ] - }, - "libunistring": { - "source": "libunistring", - "static-libs-unix": [ - "libunistring.a" - ], - "headers": [ - "unistr.h", - "unistring/" - ] - }, - "liburing": { - "source": "liburing", - "pkg-configs": [ - "liburing", - "liburing-ffi" - ], - "static-libs-linux": [ - "liburing.a", - "liburing-ffi.a" - ], - "headers-linux": [ - "liburing/", - "liburing.h" - ] - }, - "libuuid": { - "source": "libuuid", - "static-libs-unix": [ - "libuuid.a" - ], - "headers": [ - "uuid/uuid.h" - ] - }, - "libuv": { - "source": "libuv", - "static-libs-unix": [ - "libuv.a" - ] - }, - "libwebp": { - "source": "libwebp", - "pkg-configs": [ - "libwebp", - "libwebpdecoder", - "libwebpdemux", - "libwebpmux", - "libsharpyuv" - ], - "static-libs-windows": [ - "libwebp.lib", - "libwebpdecoder.lib", - "libwebpdemux.lib", - "libsharpyuv.lib" - ] - }, - "libxml2": { - "source": "libxml2", - "pkg-configs": [ - "libxml-2.0" - ], - "static-libs-windows": [ - "libxml2s.lib", - "libxml2_a.lib" - ], - "headers": [ - "libxml2" - ], - "lib-depends-unix": [ - "libiconv" - ], - "lib-suggests-unix": [ - "xz", - "zlib" - ], - "lib-depends-windows": [ - "libiconv-win" - ], - "lib-suggests-windows": [ - "zlib" - ] - }, - "libxslt": { - "source": "libxslt", - "static-libs-unix": [ - "libxslt.a", - "libexslt.a" - ], - "lib-depends": [ - "libxml2" - ] - }, - "libyaml": { - "source": "libyaml", - "static-libs-unix": [ - "libyaml.a" - ], - "static-libs-windows": [ - "yaml.lib" - ], - "headers": [ - "yaml.h" - ] - }, - "libzip": { - "source": "libzip", - "static-libs-unix": [ - "libzip.a" - ], - "static-libs-windows": [ - "zip.lib", - "libzip_a.lib" - ], - "headers": [ - "zip.h", - "zipconf.h" - ], - "lib-depends-unix": [ - "zlib" - ], - "lib-suggests-unix": [ - "bzip2", - "xz", - "zstd", - "openssl" - ], - "lib-depends-windows": [ - "zlib", - "bzip2", - "xz" - ], - "lib-suggests-windows": [ - "openssl" - ] - }, - "mimalloc": { - "source": "mimalloc", - "static-libs-unix": [ - "libmimalloc.a" - ] - }, - "ncurses": { - "source": "ncurses", - "static-libs-unix": [ - "libncurses.a" - ] - }, - "net-snmp": { - "source": "net-snmp", - "pkg-configs": [ - "netsnmp", - "netsnmp-agent" - ], - "lib-depends": [ - "openssl", - "zlib" - ] - }, - "nghttp2": { - "source": "nghttp2", - "static-libs-unix": [ - "libnghttp2.a" - ], - "static-libs-windows": [ - "nghttp2.lib" - ], - "headers": [ - "nghttp2" - ], - "lib-depends": [ - "zlib", - "openssl" - ], - "lib-suggests": [ - "libxml2", - "nghttp3", - "ngtcp2" - ] - }, - "nghttp3": { - "source": "nghttp3", - "static-libs-unix": [ - "libnghttp3.a" - ], - "static-libs-windows": [ - "nghttp3.lib" - ], - "headers": [ - "nghttp3" - ], - "lib-depends": [ - "openssl" - ] - }, - "ngtcp2": { - "source": "ngtcp2", - "static-libs-unix": [ - "libngtcp2.a", - "libngtcp2_crypto_ossl.a" - ], - "static-libs-windows": [ - "ngtcp2.lib", - "ngtcp2_crypto_ossl.lib" - ], - "headers": [ - "ngtcp2" - ], - "lib-depends": [ - "openssl" - ], - "lib-suggests": [ - "nghttp3", - "brotli" - ] - }, - "onig": { - "source": "onig", - "static-libs-unix": [ - "libonig.a" - ], - "static-libs-windows": [ - "onig.lib", - "onig_a.lib" - ], - "headers": [ - "oniggnu.h", - "oniguruma.h" - ] - }, - "openssl": { - "source": "openssl", - "pkg-configs": [ - "openssl" - ], - "static-libs-unix": [ - "libssl.a", - "libcrypto.a" - ], - "static-libs-windows": [ - "libssl.lib", - "libcrypto.lib" - ], - "headers": [ - "openssl" - ], - "lib-depends": [ - "zlib" - ] - }, - "postgresql": { - "source": "postgresql", - "pkg-configs": [ - "libpq" - ], - "lib-depends": [ - "libiconv", - "libxml2", - "openssl", - "zlib", - "libedit" - ], - "lib-suggests": [ - "icu", - "libxslt", - "ldap", - "zstd" - ] - }, - "postgresql-win": { - "source": "postgresql-win", - "static-libs": [ - "libpq.lib", - "libpgport.lib", - "libpgcommon.lib" - ] - }, - "pthreads4w": { - "source": "pthreads4w", - "static-libs-windows": [ - "libpthreadVC3.lib" - ] - }, - "qdbm": { - "source": "qdbm", - "static-libs-unix": [ - "libqdbm.a" - ], - "static-libs-windows": [ - "qdbm_a.lib" - ], - "headers-windows": [ - "depot.h" - ] - }, - "re2c": { - "source": "re2c", - "bin-unix": [ - "re2c" - ] - }, - "readline": { - "source": "readline", - "static-libs-unix": [ - "libreadline.a" - ], - "lib-depends": [ - "ncurses" - ] - }, - "snappy": { - "source": "snappy", - "cpp-library": true, - "static-libs-unix": [ - "libsnappy.a" - ], - "headers-unix": [ - "snappy.h", - "snappy-c.h", - "snappy-sinksource.h", - "snappy-stubs-public.h" - ], - "lib-depends": [ - "zlib" - ] - }, - "sqlite": { - "source": "sqlite", - "static-libs-unix": [ - "libsqlite3.a" - ], - "static-libs-windows": [ - "libsqlite3_a.lib" - ], - "headers": [ - "sqlite3.h", - "sqlite3ext.h" - ] - }, - "tidy": { - "source": "tidy", - "static-libs-unix": [ - "libtidy.a" - ] - }, - "unixodbc": { - "source": "unixodbc", - "pkg-configs": [ - "odbc", - "odbccr", - "odbcinst" - ], - "static-libs-unix": [ - "libodbc.a", - "libodbccr.a", - "libodbcinst.a" - ], - "lib-depends": [ - "libiconv" - ] - }, - "watcher": { - "source": "watcher", - "cpp-library": true, - "static-libs-unix": [ - "libwatcher-c.a" - ], - "headers": [ - "wtr/watcher-c.h" - ], - "frameworks": [ - "CoreServices" - ] - }, - "xz": { - "source": "xz", - "static-libs-unix": [ - "liblzma.a" - ], - "static-libs-windows": [ - "lzma.lib", - "liblzma_a.lib" - ], - "headers-unix": [ - "lzma" - ], - "headers-windows": [ - "lzma", - "lzma.h" - ], - "lib-depends-unix": [ - "libiconv" - ] - }, - "zlib": { - "source": "zlib", - "pkg-configs": [ - "zlib" - ], - "static-libs-unix": [ - "libz.a" - ], - "static-libs-windows": [ - "zlib_a.lib" - ], - "headers": [ - "zlib.h", - "zconf.h" - ] - }, - "zstd": { - "source": "zstd", - "pkg-configs": [ - "libzstd" - ], - "static-libs-unix": [ - "libzstd.a" - ], - "static-libs-windows": [ - [ - "zstd.lib", - "zstd_static.lib" - ] - ], - "headers-unix": [ - "zdict.h", - "zstd.h", - "zstd_errors.h" - ], - "headers-windows": [ - "zstd.h", - "zstd_errors.h" - ] - } -} diff --git a/config/pkg.ext.json b/config/pkg.ext.json deleted file mode 100644 index cbcf5ad5..00000000 --- a/config/pkg.ext.json +++ /dev/null @@ -1,1520 +0,0 @@ -{ - "ext-amqp": { - "type": "php-extension", - "artifact": "amqp", - "depends": [ - "librabbitmq" - ], - "depends@windows": [ - "ext-openssl" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-apcu": { - "type": "php-extension", - "artifact": "apcu", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-ast": { - "type": "php-extension", - "artifact": "ast", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-bcmath": { - "type": "php-extension" - }, - "ext-brotli": { - "type": "php-extension", - "artifact": "ext-brotli", - "depends": [ - "brotli" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "arg-type": "enable" - } - }, - "ext-bz2": { - "type": "php-extension", - "depends": [ - "bzip2" - ], - "php-extension": { - "arg-type@windows": "with", - "arg-type": "with-path" - } - }, - "ext-calendar": { - "type": "php-extension" - }, - "ext-ctype": { - "type": "php-extension" - }, - "ext-curl": { - "type": "php-extension", - "depends": [ - "curl" - ], - "depends@windows": [ - "ext-zlib", - "ext-openssl" - ], - "php-extension": { - "arg-type": "with", - "notes": true - } - }, - "ext-dba": { - "type": "php-extension", - "suggests": [ - "qdbm" - ], - "php-extension": { - "arg-type": "custom" - } - }, - "ext-dio": { - "type": "php-extension", - "artifact": "dio", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-dom": { - "type": "php-extension", - "depends": [ - "libxml2", - "zlib" - ], - "depends@windows": [ - "ext-xml" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "arg-type@windows": "with" - } - }, - "ext-ds": { - "type": "php-extension", - "artifact": "ext-ds", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-enchant": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip", - "Darwin": "wip", - "Linux": "wip" - } - } - }, - "ext-ev": { - "type": "php-extension", - "artifact": "ev", - "depends": [ - "ext-sockets" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "arg-type@windows": "with" - } - }, - "ext-event": { - "type": "php-extension", - "artifact": "ext-event", - "depends": [ - "libevent", - "ext-openssl" - ], - "suggests": [ - "ext-sockets" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-exif": { - "type": "php-extension" - }, - "ext-ffi": { - "type": "php-extension", - "depends": [ - "libffi" - ], - "depends@windows": [ - "libffi-win" - ], - "php-extension": { - "support": { - "Linux": "partial", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-fileinfo": { - "type": "php-extension" - }, - "ext-filter": { - "type": "php-extension" - }, - "ext-ftp": { - "type": "php-extension", - "suggests": [ - "openssl" - ] - }, - "ext-gd": { - "type": "php-extension", - "depends": [ - "zlib", - "libpng", - "ext-zlib" - ], - "suggests": [ - "libavif", - "libwebp", - "libjpeg", - "freetype" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "arg-type@windows": "with", - "notes": true - } - }, - "ext-gettext": { - "type": "php-extension", - "depends": [ - "gettext" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-gmp": { - "type": "php-extension", - "depends": [ - "gmp" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-gmssl": { - "type": "php-extension", - "artifact": "ext-gmssl", - "depends": [ - "gmssl" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-grpc": { - "type": "php-extension", - "artifact": "grpc", - "depends": [ - "grpc" - ], - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "enable-path" - } - }, - "ext-iconv": { - "type": "php-extension", - "depends": [ - "libiconv" - ], - "depends@windows": [ - "libiconv-win" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with-path", - "arg-type@windows": "with" - } - }, - "ext-igbinary": { - "type": "php-extension", - "artifact": "igbinary", - "suggests": [ - "ext-session", - "ext-apcu" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-imagick": { - "type": "php-extension", - "artifact": "ext-imagick", - "depends": [ - "imagemagick" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-imap": { - "type": "php-extension", - "artifact": "ext-imap", - "depends": [ - "imap" - ], - "suggests": [ - "ext-openssl" - ], - "license": { - "type": "file", - "path": [ - "LICENSE" - ] - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-inotify": { - "type": "php-extension", - "artifact": "inotify", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip", - "Darwin": "no" - } - } - }, - "ext-intl": { - "type": "php-extension", - "depends": [ - "icu" - ], - "depends@windows": [ - "icu-static-win" - ], - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-ldap": { - "type": "php-extension", - "depends": [ - "ldap" - ], - "suggests": [ - "gmp", - "libsodium", - "ext-openssl" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-libxml": { - "type": "php-extension", - "depends": [ - "ext-xml" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "none", - "build-shared": false, - "build-static": true, - "build-with-php": true - } - }, - "ext-lz4": { - "type": "php-extension", - "artifact": "ext-lz4", - "depends": [ - "liblz4" - ], - "license": { - "type": "file", - "path": [ - "LICENSE" - ] - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-mbregex": { - "type": "php-extension", - "depends": [ - "onig", - "ext-mbstring" - ], - "php-extension": { - "arg-type": "custom", - "build-shared": false, - "build-static": true - } - }, - "ext-mbstring": { - "type": "php-extension", - "php-extension": { - "arg-type": "custom" - } - }, - "ext-mcrypt": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no", - "BSD": "no", - "Darwin": "no", - "Linux": "no" - }, - "notes": true - } - }, - "ext-memcache": { - "type": "php-extension", - "artifact": "ext-memcache", - "depends": [ - "ext-zlib", - "ext-session" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom", - "build-with-php": true - } - }, - "ext-memcached": { - "type": "php-extension", - "artifact": "memcached", - "depends": [ - "libmemcached", - "fastlz", - "ext-session", - "ext-zlib" - ], - "suggests": [ - "zstd", - "ext-igbinary", - "ext-msgpack", - "ext-session" - ], - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-mongodb": { - "type": "php-extension", - "artifact": "mongodb", - "suggests": [ - "icu", - "openssl", - "zstd", - "zlib" - ], - "frameworks": [ - "CoreFoundation", - "Security" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "arg-type": "custom" - } - }, - "ext-msgpack": { - "type": "php-extension", - "artifact": "msgpack", - "depends": [ - "ext-session" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type@windows": "enable", - "arg-type": "with" - } - }, - "ext-mysqli": { - "type": "php-extension", - "depends": [ - "ext-mysqlnd" - ], - "php-extension": { - "arg-type": "with", - "build-with-php": true - } - }, - "ext-mysqlnd": { - "type": "php-extension", - "depends": [ - "zlib" - ], - "php-extension": { - "arg-type@windows": "with", - "build-with-php": true - } - }, - "ext-oci8": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "no", - "Darwin": "no", - "Linux": "no" - }, - "notes": true - } - }, - "ext-odbc": { - "type": "php-extension", - "depends": [ - "unixodbc" - ], - "php-extension": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "arg-type": "custom" - } - }, - "ext-opcache": { - "type": "php-extension", - "php-extension": { - "arg-type@windows": "enable", - "arg-type": "custom", - "zend-extension": true - } - }, - "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 - } - }, - "ext-opentelemetry": { - "type": "php-extension", - "artifact": "opentelemetry", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-parallel": { - "type": "php-extension", - "artifact": "parallel", - "depends@windows": [ - "pthreads4w" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type@windows": "with", - "notes": true - } - }, - "ext-password-argon2": { - "type": "php-extension", - "depends": [ - "libargon2", - "openssl" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-pcntl": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no" - } - } - }, - "ext-pdo": { - "type": "php-extension" - }, - "ext-pdo_mysql": { - "type": "php-extension", - "depends": [ - "ext-pdo", - "ext-mysqlnd" - ], - "php-extension": { - "arg-type": "with" - } - }, - "ext-pdo_odbc": { - "type": "php-extension", - "depends": [ - "unixodbc", - "ext-pdo", - "ext-odbc" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-pdo_pgsql": { - "type": "php-extension", - "depends": [ - "postgresql", - "ext-pdo", - "ext-pgsql" - ], - "depends@windows": [ - "postgresql-win" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with-path", - "arg-type@windows": "custom" - } - }, - "ext-pdo_sqlite": { - "type": "php-extension", - "depends": [ - "sqlite", - "ext-pdo", - "ext-sqlite3" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with" - } - }, - "ext-pdo_sqlsrv": { - "type": "php-extension", - "artifact": "pdo_sqlsrv", - "depends": [ - "ext-pdo", - "ext-sqlsrv" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with" - } - }, - "ext-pgsql": { - "type": "php-extension", - "depends": [ - "postgresql" - ], - "depends@windows": [ - "postgresql-win" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-phar": { - "type": "php-extension", - "depends": [ - "ext-zlib" - ] - }, - "ext-posix": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no" - } - } - }, - "ext-protobuf": { - "type": "php-extension", - "artifact": "protobuf", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - } - } - }, - "ext-rar": { - "type": "php-extension", - "artifact": "rar", - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip", - "Darwin": "partial" - }, - "notes": true - } - }, - "ext-rdkafka": { - "type": "php-extension", - "artifact": "ext-rdkafka", - "depends": [ - "librdkafka" - ], - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip", - "Windows": "wip" - }, - "arg-type": "custom" - } - }, - "ext-readline": { - "type": "php-extension", - "depends": [ - "libedit" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path", - "build-shared": false, - "build-static": true - } - }, - "ext-redis": { - "type": "php-extension", - "artifact": "redis", - "suggests": [ - "zstd", - "liblz4", - "ext-session", - "ext-igbinary", - "ext-msgpack" - ], - "license": { - "type": "file", - "path": [ - "LICENSE", - "COPYING" - ] - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-session": { - "type": "php-extension", - "php-extension": { - "build-with-php": true - } - }, - "ext-shmop": { - "type": "php-extension", - "php-extension": { - "build-with-php": true - } - }, - "ext-simdjson": { - "type": "php-extension", - "artifact": "ext-simdjson", - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-simplexml": { - "type": "php-extension", - "depends": [ - "libxml2" - ], - "depends@windows": [ - "ext-xml" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "build-with-php": true - } - }, - "ext-snappy": { - "type": "php-extension", - "artifact": "ext-snappy", - "depends": [ - "snappy" - ], - "suggests": [ - "ext-apcu" - ], - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-snmp": { - "type": "php-extension", - "depends": [ - "net-snmp" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type@windows": "with", - "arg-type": "with" - } - }, - "ext-soap": { - "type": "php-extension", - "depends": [ - "ext-libxml", - "ext-session" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-sockets": { - "type": "php-extension" - }, - "ext-sodium": { - "type": "php-extension", - "depends": [ - "libsodium" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with" - } - }, - "ext-spx": { - "type": "php-extension", - "artifact": "spx", - "depends": [ - "zlib" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip", - "Windows": "no" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-sqlite3": { - "type": "php-extension", - "depends": [ - "sqlite" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with-path", - "arg-type@windows": "with", - "build-with-php": true - } - }, - "ext-sqlsrv": { - "type": "php-extension", - "artifact": "sqlsrv", - "depends": [ - "unixodbc" - ], - "depends@linux": [ - "ext-pcntl" - ], - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-ssh2": { - "type": "php-extension", - "artifact": "ext-ssh2", - "depends": [ - "libssh2", - "ext-openssl", - "ext-zlib" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "with-path", - "arg-type@windows": "with" - } - }, - "ext-swoole": { - "type": "php-extension", - "artifact": "swoole", - "depends": [ - "libcares", - "brotli", - "nghttp2", - "zlib", - "ext-openssl", - "ext-curl" - ], - "suggests": [ - "zstd", - "ext-sockets", - "ext-swoole-hook-pgsql", - "ext-swoole-hook-mysql", - "ext-swoole-hook-sqlite", - "ext-swoole-hook-odbc" - ], - "suggests@linux": [ - "zstd", - "liburing" - ], - "lang": "cpp", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-swoole-hook-mysql": { - "type": "php-extension", - "depends": [ - "ext-mysqlnd", - "ext-pdo", - "ext-pdo_mysql", - "ext-swoole" - ], - "suggests": [ - "ext-mysqli" - ], - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "arg-type": "none", - "notes": true - } - }, - "ext-swoole-hook-odbc": { - "type": "php-extension", - "depends": [ - "unixodbc", - "ext-pdo", - "ext-swoole" - ], - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "arg-type": "none", - "notes": true - } - }, - "ext-swoole-hook-pgsql": { - "type": "php-extension", - "depends": [ - "ext-pgsql", - "ext-pdo", - "ext-swoole" - ], - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip", - "Darwin": "partial" - }, - "arg-type": "none", - "notes": true - } - }, - "ext-swoole-hook-sqlite": { - "type": "php-extension", - "depends": [ - "ext-sqlite3", - "ext-pdo", - "ext-swoole" - ], - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - }, - "arg-type": "none", - "notes": true - } - }, - "ext-swow": { - "type": "php-extension", - "artifact": "swow", - "suggests": [ - "openssl", - "curl", - "ext-openssl", - "ext-curl" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "notes": true - } - }, - "ext-sysvmsg": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - } - } - }, - "ext-sysvsem": { - "type": "php-extension", - "php-extension": { - "support": { - "Windows": "no", - "BSD": "wip" - } - } - }, - "ext-sysvshm": { - "type": "php-extension", - "php-extension": { - "support": { - "BSD": "wip" - } - } - }, - "ext-tidy": { - "type": "php-extension", - "depends": [ - "tidy" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-tokenizer": { - "type": "php-extension", - "php-extension": { - "build-with-php": true - } - }, - "ext-trader": { - "type": "php-extension", - "artifact": "ext-trader", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip", - "Windows": "wip" - } - } - }, - "ext-uuid": { - "type": "php-extension", - "artifact": "ext-uuid", - "depends": [ - "libuuid" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-uv": { - "type": "php-extension", - "artifact": "ext-uv", - "depends": [ - "libuv", - "ext-sockets" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-xdebug": { - "type": "php-extension", - "artifact": "xdebug", - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "no", - "Darwin": "partial", - "Linux": "partial" - }, - "build-shared": true, - "build-static": false, - "notes": true, - "zend-extension": true - } - }, - "ext-xhprof": { - "type": "php-extension", - "artifact": "xhprof", - "depends": [ - "ext-ctype" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "build-with-php": true, - "notes": true - } - }, - "ext-xlswriter": { - "type": "php-extension", - "artifact": "xlswriter", - "depends": [ - "ext-zlib", - "ext-zip" - ], - "suggests": [ - "openssl" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-xml": { - "type": "php-extension", - "depends": [ - "libxml2" - ], - "depends@windows": [ - "ext-iconv" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "arg-type@windows": "with", - "build-with-php": true, - "notes": true - } - }, - "ext-xmlreader": { - "type": "php-extension", - "depends": [ - "libxml2" - ], - "depends@windows": [ - "ext-xml", - "ext-dom" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "build-with-php": true - } - }, - "ext-xmlwriter": { - "type": "php-extension", - "depends": [ - "libxml2" - ], - "depends@windows": [ - "ext-xml" - ], - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "build-with-php": true - } - }, - "ext-xsl": { - "type": "php-extension", - "depends": [ - "libxslt", - "ext-xml", - "ext-dom" - ], - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "with-path" - } - }, - "ext-xz": { - "type": "php-extension", - "artifact": "ext-xz", - "depends": [ - "xz" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "arg-type": "with" - } - }, - "ext-yac": { - "type": "php-extension", - "artifact": "yac", - "depends": [ - "fastlz", - "ext-igbinary" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom" - } - }, - "ext-yaml": { - "type": "php-extension", - "artifact": "yaml", - "depends": [ - "libyaml" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type@windows": "with", - "arg-type": "with-path" - } - }, - "ext-zip": { - "type": "php-extension", - "artifact": "ext-zip", - "depends": [ - "libzip" - ], - "depends@windows": [ - "libzip", - "zlib", - "bzip2", - "xz", - "ext-zlib", - "ext-bz2" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "BSD": "wip" - }, - "arg-type": "custom", - "arg-type@windows": "enable" - } - }, - "ext-zlib": { - "type": "php-extension", - "depends": [ - "zlib" - ], - "php-extension": { - "arg-type": "custom", - "arg-type@windows": "enable", - "build-shared": false, - "build-static": true, - "build-with-php": true - } - }, - "ext-zstd": { - "type": "php-extension", - "artifact": "ext-zstd", - "depends": [ - "zstd" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "php-extension": { - "support": { - "Windows": "wip", - "BSD": "wip" - }, - "arg-type": "custom" - } - } -} diff --git a/config/pkg.lib.json b/config/pkg.lib.json deleted file mode 100644 index 6cade9b7..00000000 --- a/config/pkg.lib.json +++ /dev/null @@ -1,992 +0,0 @@ -{ - "attr": { - "artifact": "attr", - "license": { - "type": "file", - "path": "doc/COPYING.LGPL" - }, - "type": "library" - }, - "brotli": { - "artifact": "brotli", - "headers": [ - "brotli" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "libbrotlicommon", - "libbrotlidec", - "libbrotlienc" - ], - "type": "library" - }, - "bzip2": { - "artifact": "bzip2", - "headers": [ - "bzlib.h" - ], - "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": { - "artifact": "curl", - "depends": [ - "openssl", - "zlib" - ], - "depends@windows": [ - "zlib", - "libssh2", - "nghttp2" - ], - "frameworks": [ - "CoreFoundation", - "CoreServices", - "SystemConfiguration" - ], - "headers": [ - "curl" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "suggests": [ - "libssh2", - "brotli", - "nghttp2", - "nghttp3", - "ngtcp2", - "zstd", - "libcares", - "ldap" - ], - "suggests@windows": [ - "brotli", - "zstd" - ], - "type": "library" - }, - "fastlz": { - "artifact": "fastlz", - "headers": [ - "fastlz/fastlz.h" - ], - "license": { - "type": "file", - "path": "LICENSE.MIT" - }, - "type": "library" - }, - "freetype": { - "artifact": "freetype", - "depends": [ - "zlib" - ], - "headers": [ - "freetype2/freetype/freetype.h", - "freetype2/ft2build.h" - ], - "license": { - "type": "file", - "path": "LICENSE.TXT" - }, - "suggests": [ - "libpng", - "bzip2", - "brotli" - ], - "type": "library" - }, - "gettext": { - "artifact": "gettext", - "depends": [ - "libiconv" - ], - "frameworks": [ - "CoreFoundation" - ], - "license": { - "type": "file", - "path": "gettext-runtime/intl/COPYING.LIB" - }, - "suggests": [ - "ncurses", - "libxml2" - ], - "type": "library" - }, - "glfw": { - "artifact": "ext-glfw", - "frameworks": [ - "CoreVideo", - "OpenGL", - "Cocoa", - "IOKit" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "gmp": { - "artifact": "gmp", - "headers": [ - "gmp.h" - ], - "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": { - "artifact": "gmssl", - "frameworks": [ - "Security" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "grpc": { - "artifact": "grpc", - "depends": [ - "zlib", - "openssl", - "libcares" - ], - "frameworks": [ - "CoreFoundation" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "grpc" - ], - "type": "library" - }, - "icu": { - "artifact": "icu", - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "icu-uc", - "icu-i18n", - "icu-io" - ], - "type": "library" - }, - "icu-static-win": { - "artifact": "icu-static-win", - "headers@windows": [ - "unicode" - ], - "license": { - "type": "text", - "text": "none" - }, - "type": "library" - }, - "imagemagick": { - "artifact": "imagemagick", - "depends": [ - "zlib", - "libjpeg", - "libjxl", - "libpng", - "libwebp", - "freetype", - "libtiff", - "libheif", - "bzip2" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "Magick++-7.Q16HDRI", - "MagickCore-7.Q16HDRI", - "MagickWand-7.Q16HDRI" - ], - "suggests": [ - "zstd", - "xz", - "libzip", - "libxml2" - ], - "type": "library" - }, - "imap": { - "artifact": "imap", - "license": { - "type": "file", - "path": "LICENSE" - }, - "suggests": [ - "openssl" - ], - "type": "library" - }, - "jbig": { - "artifact": "jbig", - "headers": [ - "jbig.h", - "jbig85.h", - "jbig_ar.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "ldap": { - "artifact": "ldap", - "depends": [ - "openssl", - "zlib", - "gmp", - "libsodium" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "ldap", - "lber" - ], - "type": "library" - }, - "lerc": { - "artifact": "lerc", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libacl": { - "artifact": "libacl", - "depends": [ - "attr" - ], - "license": { - "type": "file", - "path": "doc/COPYING.LGPL" - }, - "type": "library" - }, - "libaom": { - "artifact": "libaom", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libargon2": { - "artifact": "libargon2", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libavif": { - "artifact": "libavif", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libcares": { - "artifact": "libcares", - "headers": [ - "ares.h", - "ares_dns.h", - "ares_nameser.h" - ], - "license": { - "type": "file", - "path": "LICENSE.md" - }, - "type": "library" - }, - "libde265": { - "artifact": "libde265", - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "libedit": { - "artifact": "libedit", - "depends": [ - "ncurses" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "libevent": { - "artifact": "libevent", - "depends": [ - "openssl" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libffi": { - "artifact": "libffi", - "headers": [ - "ffi.h", - "ffitarget.h" - ], - "headers@windows": [ - "ffi.h", - "fficonfig.h", - "ffitarget.h" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libffi-win": { - "artifact": "libffi-win", - "headers@windows": [ - "ffi.h", - "ffitarget.h", - "fficonfig.h" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libheif": { - "artifact": "libheif", - "depends": [ - "libde265", - "libwebp", - "libaom", - "zlib", - "brotli" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "libiconv": { - "artifact": "libiconv", - "headers": [ - "iconv.h", - "libcharset.h", - "localcharset.h" - ], - "license": { - "type": "file", - "path": "COPYING.LIB" - }, - "type": "library" - }, - "libiconv-win": { - "artifact": "libiconv-win", - "license": { - "type": "file", - "path": "source/COPYING" - }, - "type": "library" - }, - "libjpeg": { - "artifact": "libjpeg", - "license": { - "type": "file", - "path": "LICENSE.md" - }, - "suggests@windows": [ - "zlib" - ], - "type": "library" - }, - "libjxl": { - "artifact": "libjxl", - "depends": [ - "brotli", - "libjpeg", - "libpng", - "libwebp" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "libjxl", - "libjxl_cms", - "libjxl_threads", - "libhwy" - ], - "type": "library" - }, - "liblz4": { - "artifact": "liblz4", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libmemcached": { - "artifact": "libmemcached", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libpng": { - "artifact": "libpng", - "depends": [ - "zlib" - ], - "headers": [ - "png.h", - "pngconf.h", - "pnglibconf.h" - ], - "headers@windows": [ - "png.h", - "pngconf.h" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "librabbitmq": { - "artifact": "librabbitmq", - "depends": [ - "openssl" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "librdkafka": { - "artifact": "librdkafka", - "license": { - "type": "file", - "path": "LICENSE" - }, - "pkg-configs": [ - "rdkafka++-static", - "rdkafka-static" - ], - "suggests": [ - "curl", - "liblz4", - "openssl", - "zlib", - "zstd" - ], - "type": "library" - }, - "libsodium": { - "artifact": "libsodium", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "libssh2": { - "artifact": "libssh2", - "depends": [ - "openssl" - ], - "headers": [ - "libssh2.h", - "libssh2_publickey.h", - "libssh2_sftp.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "libtiff": { - "artifact": "libtiff", - "depends": [ - "zlib", - "libjpeg" - ], - "license": { - "type": "file", - "path": "LICENSE.md" - }, - "suggests": [ - "lerc", - "libwebp", - "jbig", - "xz", - "zstd" - ], - "type": "library" - }, - "liburing": { - "artifact": "liburing", - "headers@linux": [ - "liburing/", - "liburing.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "pkg-configs": [ - "liburing", - "liburing-ffi" - ], - "type": "library" - }, - "libuuid": { - "artifact": "libuuid", - "headers": [ - "uuid/uuid.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "libuv": { - "artifact": "libuv", - "license": [ - { - "type": "file", - "path": "LICENSE" - }, - { - "type": "file", - "path": "LICENSE-extra" - } - ], - "type": "library" - }, - "libwebp": { - "artifact": "libwebp", - "license": { - "type": "file", - "path": "COPYING" - }, - "pkg-configs": [ - "libwebp", - "libwebpdecoder", - "libwebpdemux", - "libwebpmux", - "libsharpyuv" - ], - "type": "library" - }, - "libxml2": { - "artifact": "libxml2", - "depends": [ - "libiconv" - ], - "depends@windows": [ - "libiconv-win" - ], - "headers": [ - "libxml2" - ], - "license": { - "type": "file", - "path": "Copyright" - }, - "pkg-configs": [ - "libxml-2.0" - ], - "suggests": [ - "xz", - "zlib" - ], - "suggests@windows": [ - "zlib" - ], - "type": "library" - }, - "libxslt": { - "artifact": "libxslt", - "depends": [ - "libxml2" - ], - "license": { - "type": "file", - "path": "Copyright" - }, - "type": "library" - }, - "libyaml": { - "artifact": "libyaml", - "headers": [ - "yaml.h" - ], - "license": { - "type": "file", - "path": "License" - }, - "type": "library" - }, - "libzip": { - "artifact": "libzip", - "depends": [ - "zlib" - ], - "depends@windows": [ - "zlib", - "bzip2", - "xz" - ], - "headers": [ - "zip.h", - "zipconf.h" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "suggests": [ - "bzip2", - "xz", - "zstd", - "openssl" - ], - "suggests@windows": [ - "zstd", - "openssl" - ], - "type": "library" - }, - "mimalloc": { - "artifact": "mimalloc", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "ncurses": { - "artifact": "ncurses", - "license": { - "type": "file", - "path": "COPYING" - }, - "static-libs@unix": [ - "libncurses.a" - ], - "type": "library" - }, - "net-snmp": { - "artifact": "net-snmp", - "depends": [ - "openssl", - "zlib" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "pkg-configs": [ - "netsnmp", - "netsnmp-agent" - ], - "type": "library" - }, - "nghttp2": { - "artifact": "nghttp2", - "depends": [ - "zlib", - "openssl" - ], - "headers": [ - "nghttp2" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "suggests": [ - "libxml2", - "nghttp3", - "ngtcp2" - ], - "type": "library" - }, - "nghttp3": { - "artifact": "nghttp3", - "depends": [ - "openssl" - ], - "headers": [ - "nghttp3" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "ngtcp2": { - "artifact": "ngtcp2", - "depends": [ - "openssl" - ], - "headers": [ - "ngtcp2" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "suggests": [ - "nghttp3", - "brotli" - ], - "type": "library" - }, - "onig": { - "artifact": "onig", - "headers": [ - "oniggnu.h", - "oniguruma.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "openssl": { - "artifact": "openssl", - "depends": [ - "zlib" - ], - "headers": [ - "openssl" - ], - "license": { - "type": "file", - "path": "LICENSE.txt" - }, - "type": "library" - }, - "postgresql": { - "artifact": "postgresql", - "depends": [ - "libiconv", - "libxml2", - "openssl", - "zlib", - "libedit" - ], - "license": { - "type": "file", - "path": "COPYRIGHT" - }, - "pkg-configs": [ - "libpq" - ], - "suggests": [ - "icu", - "libxslt", - "ldap", - "zstd" - ], - "type": "library" - }, - "postgresql-win": { - "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": { - "artifact": "pthreads4w", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "qdbm": { - "artifact": "qdbm", - "headers@windows": [ - "depot.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "re2c": { - "artifact": "re2c", - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - }, - "readline": { - "artifact": "readline", - "depends": [ - "ncurses" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "snappy": { - "artifact": "snappy", - "depends": [ - "zlib" - ], - "headers": [ - "snappy.h", - "snappy-c.h", - "snappy-sinksource.h", - "snappy-stubs-public.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "sqlite": { - "artifact": "sqlite", - "headers": [ - "sqlite3.h", - "sqlite3ext.h" - ], - "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": { - "artifact": "tidy", - "license": { - "type": "file", - "path": "README/LICENSE.md" - }, - "type": "library" - }, - "unixodbc": { - "artifact": "unixodbc", - "depends": [ - "libiconv" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "watcher": { - "artifact": "watcher", - "headers": [ - "wtr/watcher-c.h" - ], - "license": { - "type": "file", - "path": "license" - }, - "type": "library" - }, - "xz": { - "artifact": "xz", - "depends": [ - "libiconv" - ], - "headers": [ - "lzma" - ], - "headers@windows": [ - "lzma", - "lzma.h" - ], - "license": { - "type": "file", - "path": "COPYING" - }, - "type": "library" - }, - "zlib": { - "artifact": "zlib", - "headers": [ - "zlib.h", - "zconf.h" - ], - "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": { - "artifact": "zstd", - "headers": [ - "zdict.h", - "zstd.h", - "zstd_errors.h" - ], - "headers@windows": [ - "zstd.h", - "zstd_errors.h" - ], - "license": { - "type": "file", - "path": "LICENSE" - }, - "type": "library" - } -} diff --git a/config/pre-built.json b/config/pre-built.json deleted file mode 100644 index af8496e2..00000000 --- a/config/pre-built.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "repo": "static-php/static-php-cli-hosted", - "prefer-stable": true, - "match-pattern-linux": "{name}-{arch}-{os}-{libc}-{libcver}.txz", - "match-pattern-macos": "{name}-{arch}-{os}.txz", - "match-pattern-windows": "{name}-{arch}-{os}.tgz" -} diff --git a/config/source.json b/config/source.json deleted file mode 100644 index 18bca217..00000000 --- a/config/source.json +++ /dev/null @@ -1,1294 +0,0 @@ -{ - "php-src": { - "type": "custom", - "license": { - "type": "file", - "path": "LICENSE" - }, - "alt": false - }, - "amqp": { - "type": "url", - "url": "https://pecl.php.net/get/amqp", - "path": "php-src/ext/amqp", - "filename": "amqp.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "apcu": { - "type": "url", - "url": "https://pecl.php.net/get/APCu", - "path": "php-src/ext/apcu", - "filename": "apcu.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ast": { - "type": "url", - "url": "https://pecl.php.net/get/ast", - "path": "php-src/ext/ast", - "filename": "ast.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "attr": { - "alt": { - "type": "url", - "url": "https://mirror.souseiseki.middlendian.com/nongnu/attr/attr-2.5.2.tar.gz" - }, - "type": "url", - "url": "https://download.savannah.nongnu.org/releases/attr/attr-2.5.2.tar.gz", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "doc/COPYING.LGPL" - } - }, - "brotli": { - "type": "ghtagtar", - "repo": "google/brotli", - "match": "v1\\.\\d.*", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "bzip2": { - "alt": { - "type": "filelist", - "url": "https://sourceware.org/pub/bzip2/", - "regex": "/href=\"(?bzip2-(?[^\"]+)\\.tar\\.gz)\"/" - }, - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/bzip2/bzip2-1.0.8.tar.gz", - "provide-pre-built": true, - "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." - } - }, - "curl": { - "type": "ghrel", - "repo": "curl/curl", - "match": "curl.+\\.tar\\.xz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "dio": { - "type": "url", - "url": "https://pecl.php.net/get/dio", - "path": "php-src/ext/dio", - "filename": "dio.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ev": { - "type": "url", - "url": "https://pecl.php.net/get/ev", - "path": "php-src/ext/ev", - "filename": "ev.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-brotli": { - "type": "git", - "path": "php-src/ext/brotli", - "rev": "master", - "url": "https://github.com/kjdev/php-ext-brotli", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-ds": { - "type": "url", - "url": "https://pecl.php.net/get/ds", - "path": "php-src/ext/ds", - "filename": "ds.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-event": { - "type": "url", - "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", - "rev": "master", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-gmssl": { - "type": "ghtar", - "repo": "gmssl/GmSSL-PHP", - "path": "php-src/ext/gmssl", - "license": { - "type": "file", - "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", - "path": "php-src/ext/imagick", - "filename": "imagick.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-imap": { - "type": "url", - "url": "https://pecl.php.net/get/imap", - "path": "php-src/ext/imap", - "filename": "imap.tgz", - "license": { - "type": "file", - "path": [ - "LICENSE" - ] - } - }, - "ext-lz4": { - "type": "ghtagtar", - "repo": "kjdev/php-ext-lz4", - "path": "php-src/ext/lz4", - "license": { - "type": "file", - "path": [ - "LICENSE" - ] - } - }, - "ext-maxminddb": { - "type": "url", - "url": "https://pecl.php.net/get/maxminddb", - "filename": "ext-maxminddb.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-memcache": { - "type": "url", - "url": "https://pecl.php.net/get/memcache", - "path": "php-src/ext/memcache", - "filename": "memcache.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-rdkafka": { - "type": "ghtar", - "repo": "arnaud-lb/php-rdkafka", - "path": "php-src/ext/rdkafka", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-simdjson": { - "type": "url", - "url": "https://pecl.php.net/get/simdjson", - "path": "php-src/ext/simdjson", - "filename": "simdjson.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-snappy": { - "type": "git", - "path": "php-src/ext/snappy", - "rev": "master", - "url": "https://github.com/kjdev/php-ext-snappy", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-ssh2": { - "type": "url", - "url": "https://pecl.php.net/get/ssh2", - "path": "php-src/ext/ssh2", - "filename": "ssh2.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-trader": { - "type": "url", - "url": "https://pecl.php.net/get/trader", - "path": "php-src/ext/trader", - "filename": "trader.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-uuid": { - "type": "url", - "url": "https://pecl.php.net/get/uuid", - "path": "php-src/ext/uuid", - "filename": "uuid.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-uv": { - "type": "url", - "url": "https://pecl.php.net/get/uv", - "path": "php-src/ext/uv", - "filename": "uv.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-xz": { - "type": "git", - "path": "php-src/ext/xz", - "rev": "main", - "url": "https://github.com/codemasher/php-ext-xz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-zip": { - "type": "url", - "url": "https://pecl.php.net/get/zip", - "filename": "ext-zip.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "ext-zstd": { - "type": "git", - "path": "php-src/ext/zstd", - "rev": "master", - "url": "https://github.com/kjdev/php-ext-zstd", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "fastlz": { - "type": "git", - "url": "https://github.com/ariya/FastLZ.git", - "rev": "master", - "license": { - "type": "file", - "path": "LICENSE.MIT" - } - }, - "frankenphp": { - "type": "ghtar", - "repo": "php/frankenphp", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "freetype": { - "type": "ghtagtar", - "repo": "freetype/freetype", - "match": "VER-2-\\d+-\\d+", - "license": { - "type": "file", - "path": "LICENSE.TXT" - } - }, - "gettext": { - "type": "filelist", - "url": "https://ftp.gnu.org/pub/gnu/gettext/", - "regex": "/href=\"(?gettext-(?[^\"]+)\\.tar\\.xz)\"/", - "license": { - "type": "file", - "path": "gettext-runtime/intl/COPYING.LIB" - } - }, - "gmp": { - "type": "filelist", - "url": "https://ftp.gnu.org/gnu/gmp/", - "regex": "/href=\"(?gmp-(?[^\"]+)\\.tar\\.xz)\"/", - "provide-pre-built": true, - "alt": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz" - }, - "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." - } - }, - "gmssl": { - "type": "ghtar", - "repo": "guanzhi/GmSSL", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "grpc": { - "type": "git", - "rev": "v1.75.x", - "url": "https://github.com/grpc/grpc.git", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "icu": { - "type": "ghrel", - "repo": "unicode-org/icu", - "match": "icu4c.+-src\\.tgz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "icu-static-win": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/icu-static-windows-x64/icu-static-windows-x64.zip", - "license": { - "type": "text", - "text": "none" - } - }, - "igbinary": { - "type": "url", - "url": "https://pecl.php.net/get/igbinary", - "path": "php-src/ext/igbinary", - "filename": "igbinary.tgz", - "license": { - "type": "file", - "path": "COPYING" - } - }, - "imagemagick": { - "type": "ghtar", - "repo": "ImageMagick/ImageMagick", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "imap": { - "type": "git", - "url": "https://github.com/static-php/imap.git", - "rev": "master", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "inotify": { - "type": "url", - "url": "https://pecl.php.net/get/inotify", - "path": "php-src/ext/inotify", - "filename": "inotify.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "jbig": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/jbig/jbigkit-2.1.tar.gz", - "provide-pre-built": true, - "alt": { - "type": "url", - "url": "https://www.cl.cam.ac.uk/~mgk25/jbigkit/download/jbigkit-2.1.tar.gz" - }, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "krb5": { - "type": "url", - "url": "https://web.mit.edu/kerberos/dist/krb5/1.22/krb5-1.22.2.tar.gz", - "license": { - "type": "file", - "path": "NOTICE" - } - }, - "ldap": { - "type": "filelist", - "url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/", - "regex": "/href=\"(?openldap-(?[^\"]+)\\.tgz)\"/", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "lerc": { - "type": "ghtar", - "repo": "Esri/lerc", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libacl": { - "alt": { - "type": "url", - "url": "https://mirror.souseiseki.middlendian.com/nongnu/acl/acl-2.3.2.tar.gz" - }, - "type": "url", - "url": "https://download.savannah.nongnu.org/releases/acl/acl-2.3.2.tar.gz", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "doc/COPYING.LGPL" - } - }, - "libaom": { - "type": "git", - "rev": "main", - "url": "https://aomedia.googlesource.com/aom", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libargon2": { - "type": "git", - "rev": "master", - "url": "https://github.com/static-php/phc-winner-argon2", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libavif": { - "type": "ghtar", - "repo": "AOMediaCodec/libavif", - "provide-pre-built": false, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libcares": { - "type": "ghrel", - "repo": "c-ares/c-ares", - "match": "c-ares-.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "alt": { - "type": "filelist", - "url": "https://c-ares.org/download/", - "regex": "/href=\"\\/download\\/(?c-ares-(?[^\"]+)\\.tar\\.gz)\"/" - }, - "license": { - "type": "file", - "path": "LICENSE.md" - } - }, - "libde265": { - "type": "ghrel", - "repo": "strukturag/libde265", - "match": "libde265-.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libedit": { - "type": "filelist", - "url": "https://thrysoee.dk/editline/", - "regex": "/href=\"(?libedit-(?[^\"]+)\\.tar\\.gz)\"/", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libevent": { - "type": "ghrel", - "repo": "libevent/libevent", - "match": "libevent.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libffi": { - "type": "ghrel", - "repo": "libffi/libffi", - "match": "libffi.+\\.tar\\.gz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libffi-win": { - "type": "git", - "rev": "master", - "url": "https://github.com/static-php/libffi-win.git", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libheif": { - "type": "ghrel", - "repo": "strukturag/libheif", - "match": "libheif-.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libiconv": { - "type": "filelist", - "url": "https://ftp.gnu.org/gnu/libiconv/", - "regex": "/href=\"(?libiconv-(?[^\"]+)\\.tar\\.gz)\"/", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING.LIB" - } - }, - "libiconv-win": { - "type": "git", - "rev": "master", - "url": "https://github.com/static-php/libiconv-win.git", - "license": { - "type": "file", - "path": "source/COPYING" - } - }, - "libidn2": { - "type": "filelist", - "url": "https://ftp.gnu.org/gnu/libidn/", - "regex": "/href=\"(?libidn2-(?[^\"]+)\\.tar\\.gz)\"/", - "license": { - "type": "file", - "path": "COPYING.LESSERv3" - } - }, - "libjpeg": { - "type": "ghtar", - "repo": "libjpeg-turbo/libjpeg-turbo", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE.md" - } - }, - "libjxl": { - "type": "git", - "url": "https://github.com/libjxl/libjxl", - "rev": "main", - "submodules": [ - "third_party/highway", - "third_party/libjpeg-turbo", - "third_party/sjpeg", - "third_party/skcms" - ], - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "liblz4": { - "type": "ghrel", - "repo": "lz4/lz4", - "match": "lz4-.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libmaxminddb": { - "type": "ghrel", - "repo": "maxmind/libmaxminddb", - "match": "libmaxminddb-.+\\.tar\\.gz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libmemcached": { - "type": "ghtagtar", - "repo": "awesomized/libmemcached", - "match": "1.\\d.\\d", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libpng": { - "type": "ghtagtar", - "repo": "pnggroup/libpng", - "match": "v1\\.6\\.\\d+", - "query": "?per_page=150", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "librabbitmq": { - "type": "ghtar", - "repo": "alanxz/rabbitmq-c", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "librdkafka": { - "type": "ghtar", - "repo": "confluentinc/librdkafka", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libsodium": { - "type": "ghrel", - "repo": "jedisct1/libsodium", - "match": "libsodium-(?!1\\.0\\.21)\\d+(\\.\\d+)*\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "libssh2": { - "type": "ghrel", - "repo": "libssh2/libssh2", - "match": "libssh2.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libtiff": { - "type": "filelist", - "url": "https://download.osgeo.org/libtiff/", - "regex": "/href=\"(?tiff-(?[^\"]+)\\.tar\\.xz)\"/", - "license": { - "type": "file", - "path": "LICENSE.md" - } - }, - "libunistring": { - "type": "filelist", - "url": "https://ftp.gnu.org/gnu/libunistring/", - "regex": "/href=\"(?libunistring-(?[^\"]+)\\.tar\\.gz)\"/", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING.LIB" - } - }, - "liburing": { - "type": "ghtar", - "repo": "axboe/liburing", - "prefer-stable": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libuuid": { - "type": "git", - "url": "https://github.com/static-php/libuuid.git", - "rev": "master", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libuv": { - "type": "ghtar", - "repo": "libuv/libuv", - "license": [ - { - "type": "file", - "path": "LICENSE" - }, - { - "type": "file", - "path": "LICENSE-extra" - } - ] - }, - "libwebp": { - "type": "ghtagtar", - "repo": "webmproject/libwebp", - "match": "v1\\.\\d+\\.\\d+$", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "libxml2": { - "type": "ghtagtar", - "repo": "GNOME/libxml2", - "match": "v2\\.\\d+\\.\\d+$", - "provide-pre-built": false, - "license": { - "type": "file", - "path": "Copyright" - } - }, - "libxslt": { - "type": "filelist", - "url": "https://download.gnome.org/sources/libxslt/1.1/", - "regex": "/href=\"(?libxslt-(?[^\"]+)\\.tar\\.xz)\"/", - "license": { - "type": "file", - "path": "Copyright" - } - }, - "libyaml": { - "type": "ghrel", - "repo": "yaml/libyaml", - "match": "yaml-.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "License" - } - }, - "libzip": { - "type": "ghrel", - "repo": "nih-at/libzip", - "match": "libzip.+\\.tar\\.xz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "memcached": { - "type": "url", - "url": "https://pecl.php.net/get/memcached", - "path": "php-src/ext/memcached", - "filename": "memcached.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "micro": { - "type": "git", - "path": "php-src/sapi/micro", - "rev": "master", - "url": "https://github.com/static-php/phpmicro", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "mimalloc": { - "type": "ghtagtar", - "repo": "microsoft/mimalloc", - "match": "v2\\.\\d\\.[^3].*", - "provide-pre-built": false, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "mongodb": { - "type": "ghrel", - "repo": "mongodb/mongo-php-driver", - "path": "php-src/ext/mongodb", - "match": "mongodb.+\\.tgz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "msgpack": { - "type": "url", - "url": "https://pecl.php.net/get/msgpack", - "path": "php-src/ext/msgpack", - "filename": "msgpack.tgz", - "license": { - "type": "file", - "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/", - "regex": "/href=\"(?ncurses-(?[^\"]+)\\.tar\\.gz)\"/", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "net-snmp": { - "type": "ghtagtar", - "repo": "net-snmp/net-snmp", - "license": { - "type": "file", - "path": "COPYING" - } - }, - "nghttp2": { - "type": "ghrel", - "repo": "nghttp2/nghttp2", - "match": "nghttp2.+\\.tar\\.xz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "nghttp3": { - "type": "ghrel", - "repo": "ngtcp2/nghttp3", - "match": "nghttp3.+\\.tar\\.xz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "ngtcp2": { - "type": "ghrel", - "repo": "ngtcp2/ngtcp2", - "match": "ngtcp2.+\\.tar\\.xz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "onig": { - "type": "ghrel", - "repo": "kkos/oniguruma", - "match": "onig-.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "openssl": { - "type": "ghrel", - "repo": "openssl/openssl", - "match": "openssl.+\\.tar\\.gz", - "prefer-stable": true, - "alt": { - "type": "filelist", - "url": "https://www.openssl.org/source/", - "regex": "/href=\"(?openssl-(?[^\"]+)\\.tar\\.gz)\"/" - }, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "LICENSE.txt" - } - }, - "opentelemetry": { - "type": "url", - "url": "https://pecl.php.net/get/opentelemetry", - "path": "php-src/ext/opentelemetry", - "filename": "opentelemetry.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "parallel": { - "type": "url", - "url": "https://pecl.php.net/get/parallel", - "path": "php-src/ext/parallel", - "filename": "parallel.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "pcov": { - "type": "url", - "url": "https://pecl.php.net/get/pcov", - "filename": "pcov.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "pdo_sqlsrv": { - "type": "url", - "url": "https://pecl.php.net/get/pdo_sqlsrv", - "path": "php-src/ext/pdo_sqlsrv", - "filename": "pdo_sqlsrv.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "pkg-config": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "postgresql": { - "type": "ghtagtar", - "repo": "postgres/postgres", - "match": "REL_18_\\d+", - "license": { - "type": "file", - "path": "COPYRIGHT" - } - }, - "postgresql-win": { - "type": "url", - "url": "https://get.enterprisedb.com/postgresql/postgresql-16.8-1-windows-x64-binaries.zip", - "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." - } - }, - "protobuf": { - "type": "url", - "url": "https://pecl.php.net/get/protobuf-5.34.1.tgz", - "path": "php-src/ext/protobuf", - "filename": "protobuf.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "pthreads4w": { - "type": "git", - "rev": "master", - "url": "https://git.code.sf.net/p/pthreads4w/code", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "qdbm": { - "type": "git", - "url": "https://github.com/static-php/qdbm.git", - "rev": "main", - "license": { - "type": "file", - "path": "COPYING" - } - }, - "rar": { - "type": "git", - "url": "https://github.com/static-php/php-rar.git", - "path": "php-src/ext/rar", - "rev": "issue-php82", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "re2c": { - "type": "ghrel", - "repo": "skvadrik/re2c", - "match": "re2c.+\\.tar\\.xz", - "prefer-stable": true, - "alt": { - "type": "url", - "url": "https://dl.static-php.dev/static-php-cli/deps/re2c/re2c-4.3.tar.xz" - }, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "readline": { - "type": "filelist", - "url": "https://ftp.gnu.org/pub/gnu/readline/", - "regex": "/href=\"(?readline-(?[^\"]+)\\.tar\\.gz)\"/", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "redis": { - "type": "url", - "url": "https://pecl.php.net/get/redis", - "path": "php-src/ext/redis", - "filename": "redis.tgz", - "license": { - "type": "file", - "path": [ - "LICENSE", - "COPYING" - ] - } - }, - "snappy": { - "type": "git", - "rev": "main", - "url": "https://github.com/google/snappy", - "license": { - "type": "file", - "path": "COPYING" - } - }, - "spx": { - "type": "pie", - "repo": "noisebynorthwest/php-spx", - "path": "php-src/ext/spx", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "sqlite": { - "type": "url", - "url": "https://www.sqlite.org/2024/sqlite-autoconf-3450200.tar.gz", - "provide-pre-built": true, - "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." - } - }, - "sqlsrv": { - "type": "url", - "url": "https://pecl.php.net/get/sqlsrv", - "path": "php-src/ext/sqlsrv", - "filename": "sqlsrv.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "swoole": { - "path": "php-src/ext/swoole", - "type": "ghtar", - "repo": "swoole/swoole-src", - "match": "v6\\.+", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "swow": { - "path": "php-src/ext/swow-src", - "type": "ghtar", - "repo": "swow/swow", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "tidy": { - "type": "ghtar", - "repo": "htacg/tidy-html5", - "prefer-stable": true, - "license": { - "type": "file", - "path": "README/LICENSE.md" - } - }, - "unixodbc": { - "type": "url", - "url": "https://www.unixodbc.org/unixODBC-2.3.12.tar.gz", - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "watcher": { - "type": "ghtar", - "repo": "e-dant/watcher", - "prefer-stable": true, - "license": { - "type": "file", - "path": "license" - } - }, - "xdebug": { - "type": "pie", - "repo": "xdebug/xdebug", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "xhprof": { - "type": "url", - "url": "https://pecl.php.net/get/xhprof", - "path": "php-src/ext/xhprof-src", - "filename": "xhprof.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "xlswriter": { - "type": "url", - "url": "https://pecl.php.net/get/xlswriter", - "path": "php-src/ext/xlswriter", - "filename": "xlswriter.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "xz": { - "type": "ghrel", - "repo": "tukaani-project/xz", - "match": "xz.+\\.tar\\.xz", - "prefer-stable": true, - "provide-pre-built": true, - "license": { - "type": "file", - "path": "COPYING" - } - }, - "yac": { - "type": "url", - "url": "https://pecl.php.net/get/yac", - "path": "php-src/ext/yac", - "filename": "yac.tgz", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "yaml": { - "type": "git", - "path": "php-src/ext/yaml", - "rev": "php7", - "url": "https://github.com/php/pecl-file_formats-yaml", - "license": { - "type": "file", - "path": "LICENSE" - } - }, - "zlib": { - "type": "ghrel", - "repo": "madler/zlib", - "match": "zlib.+\\.tar\\.gz", - "prefer-stable": true, - "provide-pre-built": true, - "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" - } - }, - "zstd": { - "type": "ghrel", - "repo": "facebook/zstd", - "match": "zstd.+\\.tar\\.gz", - "prefer-stable": true, - "license": { - "type": "file", - "path": "LICENSE" - } - } -} diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php deleted file mode 100644 index 9685a1d8..00000000 --- a/src/SPC/ConsoleApplication.php +++ /dev/null @@ -1,78 +0,0 @@ -addCommands( - [ - // Craft command - new CraftCommand(), - // Common commands - new BuildPHPCommand(), - new BuildLibsCommand(), - new DoctorCommand(), - new DownloadCommand(), - new InstallPkgCommand(), - new DeleteDownloadCommand(), - new DumpLicenseCommand(), - new ExtractCommand(), - new MicroCombineCommand(), - new SwitchPhpVersionCommand(), - new SPCConfigCommand(), - new DumpExtensionsCommand(), - - // Dev commands - new AllExtCommand(), - new PhpVerCommand(), - new LibVerCommand(), - new ExtVerCommand(), - new SortConfigCommand(), - new GenerateExtDocCommand(), - new GenerateExtDepDocsCommand(), - new GenerateLibDepDocsCommand(), - new PackLibCommand(), - new EnvCommand(), - ] - ); - } -} diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php deleted file mode 100644 index fdba936d..00000000 --- a/src/SPC/builder/BuilderBase.php +++ /dev/null @@ -1,543 +0,0 @@ - libraries */ - protected array $libs = []; - - /** @var array extensions */ - protected array $exts = []; - - /** @var array extension names */ - protected array $ext_list = []; - - /** @var array library names */ - protected array $lib_list = []; - - /** @var bool compile libs only (just mark it) */ - protected bool $libs_only = false; - - /** @var array compile options */ - protected array $options = []; - - /** @var string patch point name */ - protected string $patch_point = ''; - - /** - * Convert libraries to class - * - * @param array $sorted_libraries Libraries to build (if not empty, must sort first) - * - * @internal - */ - abstract public function proveLibs(array $sorted_libraries); - - /** - * Set-Up libraries - */ - public function setupLibs(): void - { - // build all libs - foreach ($this->libs as $lib) { - $starttime = microtime(true); - $status = $lib->setup($this->getOption('rebuild', false)); - match ($status) { - LIB_STATUS_OK => logger()->info('lib [' . $lib::NAME . '] setup success, took ' . round(microtime(true) - $starttime, 2) . ' s'), - LIB_STATUS_ALREADY => logger()->notice('lib [' . $lib::NAME . '] already built'), - LIB_STATUS_INSTALL_FAILED => logger()->error('lib [' . $lib::NAME . '] install failed'), - default => logger()->warning('lib [' . $lib::NAME . '] build status unknown'), - }; - if (in_array($status, [LIB_STATUS_BUILD_FAILED, LIB_STATUS_INSTALL_FAILED])) { - throw new BuildFailureException('Library [' . $lib::NAME . '] setup failed.'); - } - } - } - - /** - * Add library to build. - * - * @param LibraryBase $library Library object - */ - public function addLib(LibraryBase $library): void - { - $this->libs[$library::NAME] = $library; - } - - /** - * Get library object by name. - */ - public function getLib(string $name): ?LibraryBase - { - return $this->libs[$name] ?? null; - } - - /** - * Get all library objects. - * - * @return LibraryBase[] - */ - public function getLibs(): array - { - return $this->libs; - } - - /** - * Add extension to build. - */ - public function addExt(Extension $extension): void - { - $this->exts[$extension->getName()] = $extension; - } - - /** - * Get extension object by name. - */ - public function getExt(string $name): ?Extension - { - return $this->exts[$name] ?? null; - } - - /** - * Get all extension objects. - * - * @return Extension[] - */ - public function getExts(bool $including_shared = true): array - { - if ($including_shared) { - return $this->exts; - } - return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic()); - } - - /** - * Set libs only mode. - * - * @internal - */ - public function setLibsOnly(bool $status = true): void - { - $this->libs_only = $status; - } - - /** - * Verify the list of "ext" extensions for validity and declare an Extension object to check the dependencies of the extensions. - * - * @internal - */ - public function proveExts(array $static_extensions, array $shared_extensions = [], bool $skip_check_deps = false, bool $skip_extract = false): void - { - // judge ext - foreach ($static_extensions as $ext) { - // if extension does not support static build, throw exception - if (!in_array('static', Config::getExtTarget($ext))) { - throw new WrongUsageException('Extension [' . $ext . '] does not support static build!'); - } - } - foreach ($shared_extensions as $ext) { - // if extension does not support shared build, throw exception - if (!in_array('shared', Config::getExtTarget($ext)) && !in_array($ext, $shared_extensions)) { - throw new WrongUsageException('Extension [' . $ext . '] does not support shared build!'); - } - } - if (!$skip_extract) { - $this->emitPatchPoint('before-php-extract'); - SourceManager::initSource(sources: ['php-src'], source_only: true); - $this->emitPatchPoint('after-php-extract'); - if ($this->getPHPVersionID() >= 80000) { - $this->emitPatchPoint('before-micro-extract'); - SourceManager::initSource(sources: ['micro'], source_only: true); - $this->emitPatchPoint('after-micro-extract'); - } - $this->emitPatchPoint('before-exts-extract'); - SourceManager::initSource(exts: [...$static_extensions, ...$shared_extensions]); - $this->emitPatchPoint('after-exts-extract'); - // patch micro - SourcePatcher::patchMicro(); - } - - foreach ([...$static_extensions, ...$shared_extensions] as $extension) { - $class = AttributeMapper::getExtensionClassByName($extension) ?? Extension::class; - /** @var Extension $ext */ - $ext = new $class($extension, $this); - if (in_array($extension, $static_extensions)) { - $ext->setBuildStatic(); - } - if (in_array($extension, $shared_extensions)) { - $ext->setBuildShared(); - } - $this->addExt($ext); - } - - if ($skip_check_deps) { - return; - } - - foreach ($this->getExts() as $ext) { - $ext->checkDependency(); - } - $this->ext_list = [...$static_extensions, ...$shared_extensions]; - } - - /** - * Start to build PHP - * - * @param int $build_target Build target, see BUILD_TARGET_* - */ - abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE); - - /** - * Test PHP - */ - abstract public function testPHP(int $build_target = BUILD_TARGET_NONE); - - /** - * Build shared extensions. - */ - public function buildSharedExts(): void - { - $lines = file(BUILD_BIN_PATH . '/php-config'); - $extension_dir_line = null; - foreach ($lines as $key => $value) { - if (str_starts_with($value, 'extension_dir=')) { - $lines[$key] = 'extension_dir="' . BUILD_MODULES_PATH . '"' . PHP_EOL; - $extension_dir_line = $value; - break; - } - } - file_put_contents(BUILD_BIN_PATH . '/php-config', implode('', $lines)); - FileSystem::replaceFileStr(BUILD_LIB_PATH . '/php/build/phpize.m4', 'test "[$]$1" = "no" && $1=yes', '# test "[$]$1" = "no" && $1=yes'); - FileSystem::createDir(BUILD_MODULES_PATH); - try { - foreach ($this->getExts() as $ext) { - if (!$ext->isBuildShared()) { - continue; - } - $ext->buildShared(); - } - } finally { - FileSystem::replaceFileLineContainsString(BUILD_BIN_PATH . '/php-config', 'extension_dir=', $extension_dir_line); - } - FileSystem::replaceFileLineContainsString(BUILD_BIN_PATH . '/php-config', 'extension_dir=', $extension_dir_line); - FileSystem::replaceFileStr(BUILD_LIB_PATH . '/php/build/phpize.m4', '# test "[$]$1" = "no" && $1=yes', 'test "[$]$1" = "no" && $1=yes'); - } - - /** - * Generate extension enable arguments for configure. - * e.g. --enable-mbstring - */ - public function makeStaticExtensionArgs(): string - { - $ret = []; - foreach ($this->getExts() as $ext) { - $arg = null; - if ($ext->isBuildShared() && !$ext->isBuildStatic()) { - if ( - (Config::getExt($ext->getName(), 'type') === 'builtin' && - !file_exists(SOURCE_PATH . '/php-src/ext/' . $ext->getName() . '/config.m4')) || - Config::getExt($ext->getName(), 'build-with-php') === true - ) { - $arg = $ext->getConfigureArg(true); - } else { - continue; - } - } - $arg ??= $ext->getConfigureArg(); - logger()->info($ext->getName() . ' is using ' . $arg); - $ret[] = trim($arg); - } - logger()->debug('Using configure: ' . implode(' ', $ret)); - return implode(' ', $ret); - } - - /** - * Get libs only mode. - */ - public function isLibsOnly(): bool - { - return $this->libs_only; - } - - /** - * Get PHP Version ID from php-src/main/php_version.h - */ - public function getPHPVersionID(): int - { - if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) { - throw new WrongUsageException('PHP source files are not available, you need to download them first'); - } - - $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); - if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0) { - return intval($match[1]); - } - - throw new WrongUsageException('PHP version file format is malformed, please remove "./source/php-src" dir and download/extract again'); - } - - public function getPHPVersion(bool $exception_on_failure = true): string - { - if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) { - if (!$exception_on_failure) { - return 'unknown'; - } - throw new WrongUsageException('PHP source files are not available, you need to download them first'); - } - $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); - if (preg_match('/PHP_VERSION "(.*)"/', $file, $match) !== 0) { - return $match[1]; - } - if (!$exception_on_failure) { - return 'unknown'; - } - throw new WrongUsageException('PHP version file format is malformed, please remove it and download again'); - } - - /** - * Get PHP version from archive file name. - * - * @param null|string $file php-*.*.*.tar.gz filename, read from lockfile if empty - */ - public function getPHPVersionFromArchive(?string $file = null): false|string - { - if ($file === null) { - $lock = LockFile::get('php-src'); - if ($lock === null) { - return false; - } - $file = LockFile::getLockFullPath($lock); - } - if (preg_match('/php-(\d+\.\d+\.\d+(?:RC\d+|alpha\d+|beta\d+)?)\.tar\.(?:gz|bz2|xz)/', $file, $match)) { - return $match[1]; - } - return false; - } - - public function getMicroVersion(): false|string - { - $file = FileSystem::convertPath(SOURCE_PATH . '/php-src/sapi/micro/php_micro.h'); - if (!file_exists($file)) { - return false; - } - - $content = file_get_contents($file); - $ver = ''; - preg_match('/#define PHP_MICRO_VER_MAJ (\d)/m', $content, $match); - $ver .= $match[1] . '.'; - preg_match('/#define PHP_MICRO_VER_MIN (\d)/m', $content, $match); - $ver .= $match[1] . '.'; - preg_match('/#define PHP_MICRO_VER_PAT (\d)/m', $content, $match); - $ver .= $match[1]; - return $ver; - } - - /** - * Get build type name string to display. - * - * @param int $type Build target type - */ - public function getBuildTypeName(int $type): string - { - $ls = []; - if (($type & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { - $ls[] = 'cli'; - } - if (($type & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) { - $ls[] = 'micro'; - } - if (($type & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) { - $ls[] = 'fpm'; - } - if (($type & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) { - $ls[] = 'embed'; - } - if (($type & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) { - $ls[] = 'frankenphp'; - } - if (($type & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) { - $ls[] = 'cgi'; - } - return implode(', ', $ls); - } - - /** - * Get builder options (maybe changed by user) - * - * @param string $key Option key - * @param mixed $default If not exists, return this value - */ - public function getOption(string $key, mixed $default = null): mixed - { - return $this->options[$key] ?? $default; - } - - /** - * Get all builder options - */ - public function getOptions(): array - { - return $this->options; - } - - /** - * Set builder options if not exists. - */ - public function setOptionIfNotExist(string $key, mixed $value): void - { - if (!isset($this->options[$key])) { - $this->options[$key] = $value; - } - } - - /** - * Set builder options. - */ - public function setOption(string $key, mixed $value): void - { - $this->options[$key] = $value; - } - - public function getEnvString(array $vars = ['cc', 'cxx', 'ar', 'ld']): string - { - $env = []; - foreach ($vars as $var) { - $var = strtoupper($var); - if (getenv($var) !== false) { - $env[] = "{$var}=" . getenv($var); - } - } - return implode(' ', $env); - } - - /** - * Get builder patch point name. - */ - public function getPatchPoint(): string - { - return $this->patch_point; - } - - /** - * Validate libs and exts can be compiled successfully in current environment - */ - public function validateLibsAndExts(): void - { - foreach ($this->libs as $lib) { - $lib->validate(); - } - foreach ($this->getExts() as $ext) { - $ext->validate(); - } - } - - public function emitPatchPoint(string $point_name): void - { - $this->patch_point = $point_name; - if (($patches = $this->getOption('with-added-patch', [])) === []) { - return; - } - - foreach ($patches as $patch) { - try { - if (!file_exists($patch)) { - throw new WrongUsageException("Additional patch script file {$patch} not found!"); - } - logger()->debug('Running additional patch script: ' . $patch); - require $patch; - } catch (InterruptException $e) { - if ($e->getCode() === 0) { - logger()->notice('Patch script ' . $patch . ' interrupted' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.')); - } else { - logger()->error('Patch script ' . $patch . ' interrupted with error code [' . $e->getCode() . ']' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.')); - } - exit($e->getCode()); - } catch (\Throwable $e) { - logger()->critical('Patch script ' . $patch . ' failed to run.'); - throw $e; - } - } - } - - public function checkBeforeBuildPHP(int $rule): void - { - if (($rule & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) { - if (!$this->getOption('enable-zts')) { - throw new WrongUsageException('FrankenPHP SAPI requires ZTS enabled PHP, build with `--enable-zts`!'); - } - // frankenphp doesn't support windows, BSD is currently not supported by static-php-cli - if (!in_array(PHP_OS_FAMILY, ['Linux', 'Darwin'])) { - throw new WrongUsageException('FrankenPHP SAPI is only available on Linux and macOS!'); - } - // frankenphp needs package go-xcaddy installed - if (!GoXcaddy::isInstalled()) { - global $argv; - throw new WrongUsageException("FrankenPHP SAPI requires the go-xcaddy package, please install it first: {$argv[0]} install-pkg go-xcaddy"); - } - // frankenphp needs libxml2 lib on macos, see: https://github.com/php/frankenphp/blob/main/frankenphp.go#L17 - if (PHP_OS_FAMILY === 'Darwin' && !$this->getLib('libxml2')) { - throw new WrongUsageException('FrankenPHP SAPI for macOS requires libxml2 library, please include the `xml` extension in your build.'); - } - } - } - - /** - * Generate micro extension test php code. - */ - protected function generateMicroExtTests(): string - { - $php = "getExts(false) as $ext) { - $ext_name = $ext->getDistName(); - if (!empty($ext_name)) { - $php .= "echo 'Running micro with {$ext_name} test' . PHP_EOL;\n"; - $php .= "assert(extension_loaded('{$ext_name}'));\n\n"; - } - } - $php .= "echo '[micro-test-end]';\n"; - return $php; - } - - protected function getMicroTestTasks(): array - { - return [ - 'micro_ext_test' => [ - 'content' => ($this->getOption('without-micro-ext-test') ? 'generateMicroExtTests()), - 'conditions' => [ - // program success - function ($ret) { return $ret === 0; }, - // program returns expected output - function ($ret, $out) { - $raw_out = trim(implode('', $out)); - return str_starts_with($raw_out, '[micro-test-start]') && str_ends_with($raw_out, '[micro-test-end]'); - }, - ], - ], - 'micro_zend_bug_test' => [ - 'content' => ($this->getOption('without-micro-ext-test') ? ' [ - // program success - function ($ret) { return $ret === 0; }, - ], - ], - ]; - } -} diff --git a/src/SPC/builder/BuilderProvider.php b/src/SPC/builder/BuilderProvider.php deleted file mode 100644 index ec6141e6..00000000 --- a/src/SPC/builder/BuilderProvider.php +++ /dev/null @@ -1,47 +0,0 @@ - new WindowsBuilder($input->getOptions()), - 'Darwin' => new MacOSBuilder($input->getOptions()), - 'Linux' => new LinuxBuilder($input->getOptions()), - 'BSD' => new BSDBuilder($input->getOptions()), - default => throw new WrongUsageException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'), - }; - - // bind the builder to ExceptionHandler - ExceptionHandler::bindBuilder(self::$builder); - - return self::$builder; - } - - public static function getBuilder(): BuilderBase - { - if (self::$builder === null) { - throw new WrongUsageException('Builder has not been initialized'); - } - return self::$builder; - } -} diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php deleted file mode 100644 index 9077269e..00000000 --- a/src/SPC/builder/Extension.php +++ /dev/null @@ -1,617 +0,0 @@ -name, 'type'); - $unix_only = Config::getExt($this->name, 'unix-only', false); - $windows_only = Config::getExt($this->name, 'windows-only', false); - if (PHP_OS_FAMILY !== 'Windows' && $windows_only) { - throw new EnvironmentException("{$ext_type} extension {$name} is not supported on Linux and macOS platform"); - } - if (PHP_OS_FAMILY === 'Windows' && $unix_only) { - throw new EnvironmentException("{$ext_type} extension {$name} is not supported on Windows platform"); - } - // set source_dir for builtin - if ($ext_type === 'builtin') { - $this->source_dir = SOURCE_PATH . '/php-src/ext/' . $this->name; - } elseif ($ext_type === 'external') { - $source = Config::getExt($this->name, 'source'); - if ($source === null) { - throw new ValidationException("{$ext_type} extension {$name} source not found", validation_module: "Extension [{$name}] loader"); - } - $source_path = Config::getSource($source)['path'] ?? null; - $source_path = $source_path === null ? SOURCE_PATH . '/' . $source : SOURCE_PATH . '/' . $source_path; - $this->source_dir = $source_path; - } else { - $this->source_dir = SOURCE_PATH . '/php-src'; - } - } - - public function getFrameworks(): array - { - return Config::getExt($this->getName(), 'frameworks', []); - } - - /** - * 获取开启该扩展的 PHP 编译添加的参数 - */ - public function getConfigureArg(bool $shared = false): string - { - return match (PHP_OS_FAMILY) { - 'Windows' => $this->getWindowsConfigureArg($shared), - 'Darwin', - 'Linux', - 'BSD' => $this->getUnixConfigureArg($shared), - default => throw new WrongUsageException(PHP_OS_FAMILY . ' build is not supported yet'), - }; - } - - /** - * 根据 ext 的 arg-type 获取对应开启的参数,一般都是 --enable-xxx 和 --with-xxx - */ - public function getEnableArg(bool $shared = false): string - { - $escapedPath = str_replace("'", '', escapeshellarg(BUILD_ROOT_PATH)) !== BUILD_ROOT_PATH || str_contains(BUILD_ROOT_PATH, ' ') ? escapeshellarg(BUILD_ROOT_PATH) : BUILD_ROOT_PATH; - $_name = str_replace('_', '-', $this->name); - return match ($arg_type = Config::getExt($this->name, 'arg-type', 'enable')) { - 'enable' => '--enable-' . $_name . ($shared ? '=shared' : '') . ' ', - 'enable-path' => '--enable-' . $_name . '=' . ($shared ? 'shared,' : '') . $escapedPath . ' ', - 'with' => '--with-' . $_name . ($shared ? '=shared' : '') . ' ', - 'with-path' => '--with-' . $_name . '=' . ($shared ? 'shared,' : '') . $escapedPath . ' ', - 'none', 'custom' => '', - default => throw new WrongUsageException("argType does not accept {$arg_type}, use [enable/with/with-path] ."), - }; - } - - /** - * 导出当前扩展依赖的所有 lib 库生成的 .a 静态编译库文件,以字符串形式导出,用空格分割 - */ - public function getLibFilesString(): string - { - $ret = array_map( - fn ($x) => $x->getStaticLibFiles(), - $this->getLibraryDependencies(recursive: true) - ); - $libs = implode(' ', $ret); - return deduplicate_flags($libs); - } - - /** - * 检查下依赖就行了,作用是导入依赖给 Extension 对象,今后可以对库依赖进行选择性处理 - */ - public function checkDependency(): static - { - foreach (Config::getExt($this->name, 'lib-depends', []) as $name) { - $this->addLibraryDependency($name); - } - foreach (Config::getExt($this->name, 'lib-suggests', []) as $name) { - $this->addLibraryDependency($name, true); - } - foreach (Config::getExt($this->name, 'ext-depends', []) as $name) { - $this->addExtensionDependency($name); - } - foreach (Config::getExt($this->name, 'ext-suggests', []) as $name) { - $this->addExtensionDependency($name, true); - } - return $this; - } - - public function getExtensionDependency(): array - { - return array_filter($this->dependencies, fn ($x) => $x instanceof Extension); - } - - public function getName(): string - { - return $this->name; - } - - /** - * returns extension dist name - */ - public function getDistName(): string - { - return $this->name; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - return $this->getEnableArg(); - // Windows is not supported yet - } - - public function getUnixConfigureArg(bool $shared = false): string - { - return $this->getEnableArg($shared); - } - - /** - * Patch code before ./buildconf - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeBuildconf(): bool - { - return false; - } - - /** - * Patch code before ./configure - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeConfigure(): bool - { - return false; - } - - /** - * Patch code before ./configure.bat for Windows - */ - public function patchBeforeWindowsConfigure(): bool - { - return false; - } - - /** - * Patch code before make - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeMake(): bool - { - if (SPCTarget::getTargetOS() === 'Linux' && $this->isBuildShared() && ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS'))) { - FileSystem::replaceFileRegex( - SOURCE_PATH . '/php-src/Makefile', - "/^(shared_objects_{$this->getName()}\\s*=.*)$/m", - "$1 {$objs}", - ); - return true; - } - return false; - } - - /** - * Patch code before shared extension phpize - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeSharedPhpize(): bool - { - return false; - } - - /** - * Patch code before shared extension ./configure - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeSharedConfigure(): bool - { - return false; - } - - /** - * Patch code before shared extension make - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeSharedMake(): bool - { - $config = (new SPCConfigUtil($this->builder))->getExtensionConfig($this); - [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); - $lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null; - $lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : ''; - - $makefileContent = file_get_contents($this->source_dir . '/Makefile'); - if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) { - $prefix = $matches[1]; - $currentLibs = trim($matches[2]); - $newLibs = trim("{$currentLibs} {$staticLibs} {$lstdcpp}"); - $deduplicatedLibs = deduplicate_flags($newLibs); - - FileSystem::replaceFileRegex( - $this->source_dir . '/Makefile', - '/^(.*_SHARED_LIBADD\s*=.*)$/m', - $prefix . $deduplicatedLibs - ); - } - - if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) { - FileSystem::replaceFileRegex( - $this->source_dir . '/Makefile', - "/^(shared_objects_{$this->getName()}\\s*=.*)$/m", - "$1 {$objs}", - ); - } - return true; - } - - /** - * @return string - * returns a command line string with all required shared extensions to load - * i.e.; pdo_pgsql would return: - * - * `-d "extension=pgsql" -d "extension=pdo_pgsql"` - */ - public function getSharedExtensionLoadString(): string - { - $loaded = []; - $order = []; - - $resolve = function ($extension) use (&$resolve, &$loaded, &$order) { - if (!$extension instanceof Extension) { - return; - } - if (isset($loaded[$extension->getName()])) { - return; - } - $loaded[$extension->getName()] = true; - - foreach ($extension->dependencies as $dependency) { - $resolve($dependency); - } - - $order[] = $extension; - }; - - $resolve($this); - - $ret = ''; - foreach ($order as $ext) { - if ($ext instanceof self && $ext->isBuildShared()) { - if (Config::getExt($ext->getName(), 'type', false) === 'addon') { - continue; - } - if (Config::getExt($ext->getName(), 'zend-extension', false) === true) { - $ret .= " -d \"zend_extension={$ext->getName()}\""; - } else { - $ret .= " -d \"extension={$ext->getName()}\""; - } - } - } - - if ($ret !== '') { - $ret = ' -d "extension_dir=' . BUILD_MODULES_PATH . '"' . $ret; - } - - return $ret; - } - - public function runCliCheckUnix(): void - { - // Run compile check if build target is cli - // If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php - $sharedExtensions = $this->getSharedExtensionLoadString(); - [$ret] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"'); - if ($ret !== 0) { - throw new ValidationException( - "extension {$this->getName()} failed compile check: php-cli returned {$ret}", - validation_module: 'Extension ' . $this->getName() . ' sanity check' - ); - } - - if (file_exists(ROOT_DIR . '/src/globals/ext-tests/' . $this->getName() . '.php')) { - // Trim additional content & escape special characters to allow inline usage - $test = str_replace( - ['getName() . '.php') - ); - - [$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' -r "' . trim($test) . '"'); - if ($ret !== 0) { - throw new ValidationException( - "extension {$this->getName()} failed sanity check. Code: {$ret}, output: " . implode("\n", $out), - validation_module: 'Extension ' . $this->getName() . ' function check' - ); - } - } - } - - public function runCliCheckWindows(): void - { - // Run compile check if build target is cli - // If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php - [$ret] = cmd()->execWithResult(BUILD_BIN_PATH . '/php.exe -n --ri "' . $this->getDistName() . '"', false); - if ($ret !== 0) { - throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check"); - } - - if (file_exists(FileSystem::convertPath(ROOT_DIR . '/src/globals/ext-tests/' . $this->getName() . '.php'))) { - // Trim additional content & escape special characters to allow inline usage - $test = str_replace( - ['getName() . '.php')) - ); - - [$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n -r "' . trim($test) . '"'); - if ($ret !== 0) { - throw new ValidationException( - "extension {$this->getName()} failed function check", - validation_module: "Extension {$this->getName()} function check" - ); - } - } - } - - public function validate(): void - { - // do nothing, just throw wrong usage exception if not valid - } - - /** - * Build shared extension - */ - public function buildShared(array $visited = []): void - { - try { - if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) { - if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) { - logger()->info('Shared extension [' . $this->getName() . '] was already built by php-src/configure (' . $this->getName() . '.so)'); - return; - } - if (Config::getExt($this->getName(), 'build-with-php') === true) { - logger()->warning('Shared extension [' . $this->getName() . '] did not build with php-src/configure (' . $this->getName() . '.so)'); - logger()->warning('Try deleting your build and source folders and running `spc build`` again.'); - return; - } - } - if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) { - 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) { - continue; - } - if (!$dependency->isBuildStatic() && !in_array($dependency->getName(), $visited)) { - logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName()); - $dependency->buildShared([...$visited, $this->getName()]); - } - } - $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; - } - } - - /** - * Build shared extension for Unix - */ - public function buildUnixShared(): void - { - $env = $this->getSharedExtensionEnv(); - if ($this->patchBeforeSharedPhpize()) { - logger()->info("Extension [{$this->getName()}] patched before shared phpize"); - } - - // prepare configure args - shell()->cd($this->source_dir) - ->setEnv($env) - ->appendEnv($this->getExtraEnv()) - ->exec(BUILD_BIN_PATH . '/phpize'); - - if ($this->patchBeforeSharedConfigure()) { - logger()->info("Extension [{$this->getName()}] patched before shared configure"); - } - - $phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: ''; - - shell()->cd($this->source_dir) - ->setEnv($env) - ->appendEnv($this->getExtraEnv()) - ->exec( - './configure ' . $this->getUnixConfigureArg(true) . - ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . - "--enable-shared --disable-static {$phpvars}" - ); - - if ($this->patchBeforeSharedMake()) { - logger()->info("Extension [{$this->getName()}] patched before shared make"); - } - - shell()->cd($this->source_dir) - ->setEnv($env) - ->appendEnv($this->getExtraEnv()) - ->exec('make clean') - ->exec('make -j' . $this->builder->concurrency) - ->exec('make install'); - - // 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, $soDest, false); - } - - /** - * Get current extension version - * - * @return null|string Version string or null - */ - public function getExtVersion(): ?string - { - return null; - } - - public function setBuildStatic(): void - { - if (!in_array('static', Config::getExtTarget($this->name))) { - throw new WrongUsageException("Extension [{$this->name}] does not support static build!"); - } - $this->build_static = true; - } - - public function setBuildShared(): void - { - if (!in_array('shared', Config::getExtTarget($this->name))) { - throw new WrongUsageException("Extension [{$this->name}] does not support shared build!"); - } - $this->build_shared = true; - } - - public function isBuildShared(): bool - { - return $this->build_shared; - } - - public function isBuildStatic(): bool - { - return $this->build_static; - } - - /** - * Get the library dependencies that current extension depends on. - * - * @param bool $recursive Whether it includes dependencies recursively - */ - public function getLibraryDependencies(bool $recursive = false): array - { - $ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase); - if (!$recursive) { - return $ret; - } - - $deps = []; - - $added = 1; - while ($added !== 0) { - $added = 0; - foreach ($ret as $depName => $dep) { - foreach ($dep->getDependencies(true) as $depdepName => $depdep) { - if (!array_key_exists($depdepName, $deps)) { - $deps[$depdepName] = $depdep; - ++$added; - } - } - if (!array_key_exists($depName, $deps)) { - $deps[$depName] = $dep; - } - } - } - - return $deps; - } - - /** - * Returns the environment variables a shared extension needs to be built. - * CFLAGS, CXXFLAGS, LDFLAGS and so on. - */ - protected function getSharedExtensionEnv(): array - { - $config = (new SPCConfigUtil($this->builder, ['no_php' => true]))->getExtensionConfig($this); - [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); - $preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group '; - $postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group '; - return [ - '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, - ]; - } - - protected function addLibraryDependency(string $name, bool $optional = false): void - { - $depLib = $this->builder->getLib($name); - if (!$depLib) { - if (!$optional) { - throw new WrongUsageException("extension {$this->name} requires library {$name}"); - } - logger()->info("enabling {$this->name} without library {$name}"); - } else { - $this->dependencies[$name] = $depLib; - } - } - - protected function addExtensionDependency(string $name, bool $optional = false): void - { - $depExt = $this->builder->getExt($name); - if (!$depExt) { - if (!$optional) { - throw new WrongUsageException("{$this->name} requires extension {$name} which is not included"); - } - logger()->info("enabling {$this->name} without extension {$name}"); - } else { - $this->dependencies[$name] = $depExt; - } - } - - protected function getExtraEnv(): array - { - return []; - } - - /** - * Splits a given string of library flags into static and shared libraries. - * - * @param string $allLibs A space-separated string of library flags (e.g., -lxyz). - * @return array an array containing two elements: the first is a space-separated string - * of static library flags, and the second is a space-separated string - * of shared library flags - */ - protected function splitLibsIntoStaticAndShared(string $allLibs): array - { - $staticLibString = ''; - $sharedLibString = ''; - $libs = explode(' ', $allLibs); - foreach ($libs as $lib) { - $staticLib = BUILD_LIB_PATH . '/lib' . str_replace('-l', '', $lib) . '.a'; - if (str_starts_with($lib, BUILD_LIB_PATH . '/lib') && str_ends_with($lib, '.a')) { - $staticLib = $lib; - } - if ($lib === '-lphp' || !file_exists($staticLib)) { - $sharedLibString .= " {$lib}"; - } else { - $staticLibString .= " {$lib}"; - } - } - return [trim($staticLibString), trim($sharedLibString)]; - } -} diff --git a/src/SPC/builder/LibraryBase.php b/src/SPC/builder/LibraryBase.php deleted file mode 100644 index 73b1f9ed..00000000 --- a/src/SPC/builder/LibraryBase.php +++ /dev/null @@ -1,420 +0,0 @@ -source_dir = $source_dir ?? (SOURCE_PATH . DIRECTORY_SEPARATOR . Config::getLib(static::NAME, 'source')); - } - - /** - * Try to install or build this library. - * @param bool $force If true, force install or build - */ - public function setup(bool $force = false): int - { - $source = Config::getLib(static::NAME, 'source'); - // if source is locked as pre-built, we just tryInstall it - $pre_built_name = Downloader::getPreBuiltLockName($source); - if (($lock = LockFile::get($pre_built_name)) && $lock['lock_as'] === SPC_DOWNLOAD_PRE_BUILT) { - return $this->tryInstall($lock, $force); - } - return $this->tryBuild($force); - } - - /** - * Get library name. - */ - public function getName(): string - { - return static::NAME; - } - - /** - * Get current lib source root dir. - */ - public function getSourceDir(): string - { - return $this->source_dir; - } - - /** - * Get current lib dependencies. - * - * @return array - */ - public function getDependencies(bool $recursive = false): array - { - // 非递归情况下直接返回通过 addLibraryDependency 方法添加的依赖 - if (!$recursive) { - return $this->dependencies; - } - - $deps = []; - - $added = 1; - while ($added !== 0) { - $added = 0; - foreach ($this->dependencies as $depName => $dep) { - foreach ($dep->getDependencies(true) as $depdepName => $depdep) { - if (!in_array($depdepName, array_keys($deps), true)) { - $deps[$depdepName] = $depdep; - ++$added; - } - } - if (!in_array($depName, array_keys($deps), true)) { - $deps[$depName] = $dep; - } - } - } - - return $deps; - } - - /** - * Calculate dependencies for current library. - */ - public function calcDependency(): void - { - // Add dependencies from the configuration file. Here, choose different metadata based on the operating system. - /* - Rules: - If it is a Windows system, try the following dependencies in order: lib-depends-windows, lib-depends-win, lib-depends. - If it is a macOS system, try the following dependencies in order: lib-depends-macos, lib-depends-unix, lib-depends. - If it is a Linux system, try the following dependencies in order: lib-depends-linux, lib-depends-unix, lib-depends. - */ - foreach (Config::getLib(static::NAME, 'lib-depends', []) as $dep_name) { - $this->addLibraryDependency($dep_name); - } - foreach (Config::getLib(static::NAME, 'lib-suggests', []) as $dep_name) { - $this->addLibraryDependency($dep_name, true); - } - } - - /** - * Get config static libs. - */ - public function getStaticLibs(): array - { - return Config::getLib(static::NAME, 'static-libs', []); - } - - /** - * Get config headers. - */ - public function getHeaders(): array - { - return Config::getLib(static::NAME, 'headers', []); - } - - /** - * Get binary files. - */ - public function getBinaryFiles(): array - { - return Config::getLib(static::NAME, 'bin', []); - } - - public function tryInstall(array $lock, bool $force_install = false): int - { - $install_file = $lock['filename']; - if ($force_install) { - logger()->info('Installing required library [' . static::NAME . '] from pre-built binaries'); - - // Extract files - try { - FileSystem::extractPackage($install_file, $lock['source_type'], DOWNLOAD_PATH . '/' . $install_file, BUILD_ROOT_PATH); - $this->install(); - return LIB_STATUS_OK; - } catch (SPCException $e) { - logger()->error('Failed to extract pre-built library [' . static::NAME . ']: ' . $e->getMessage()); - return LIB_STATUS_INSTALL_FAILED; - } - } - if (!$this->isLibraryInstalled()) { - return $this->tryInstall($lock, true); - } - return LIB_STATUS_ALREADY; - } - - /** - * Try to build this library, before build, we check first. - * - * BUILD_STATUS_OK if build success - * BUILD_STATUS_ALREADY if already built - * BUILD_STATUS_FAILED if build failed - */ - public function tryBuild(bool $force_build = false): int - { - if (file_exists($this->source_dir . '/.spc.patched')) { - $this->patched = true; - } - // force means just build - if ($force_build) { - $type = Config::getLib(static::NAME, 'type', 'lib'); - logger()->info('Building required ' . $type . ' [' . static::NAME . ']'); - - // extract first if not exists - if (!is_dir($this->source_dir)) { - $this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-extract'); - SourceManager::initSource(libs: [static::NAME], source_only: true); - $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->build(); - $this->installLicense(); - $this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-build'); - return LIB_STATUS_OK; - } - - if (!$this->isLibraryInstalled()) { - return $this->tryBuild(true); - } - // if all the files exist at this point, skip the compilation process - return LIB_STATUS_ALREADY; - } - - public function validate(): void - { - // do nothing, just throw wrong usage exception if not valid - } - - /** - * Get current lib version - * - * @return null|string Version string or null - */ - public function getLibVersion(): ?string - { - return null; - } - - /** - * Get current builder object. - */ - abstract public function getBuilder(): BuilderBase; - - public function beforePack(): void - { - // do something before pack, default do nothing. overwrite this method to do something (e.g. modify pkg-config file) - } - - /** - * Patch code before build - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeBuild(): bool - { - return false; - } - - /** - * Patch code before ./buildconf - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeBuildconf(): bool - { - return false; - } - - /** - * Patch code before ./configure - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeConfigure(): bool - { - return false; - } - - /** - * Patch code before windows configure.bat - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeWindowsConfigure(): bool - { - return false; - } - - /** - * Patch code before make - * If you need to patch some code, overwrite this - * return true if you patched something, false if not - */ - public function patchBeforeMake(): bool - { - return false; - } - - /** - * Patch php-config after embed was built - * Example: imap requires -lcrypt - */ - public function patchPhpConfig(): bool - { - return false; - } - - /** - * Build this library. - */ - abstract protected function build(); - - protected function install(): void - { - // replace placeholders if BUILD_ROOT_PATH/.spc-extract-placeholder.json exists - $replace_item_file = BUILD_ROOT_PATH . '/.spc-extract-placeholder.json'; - if (!file_exists($replace_item_file)) { - return; - } - $replace_items = json_decode(file_get_contents($replace_item_file), true); - if (!is_array($replace_items)) { - throw new SPCInternalException("Invalid placeholder file: {$replace_item_file}"); - } - $placeholders = get_pack_replace(); - // replace placeholders in BUILD_ROOT_PATH - foreach ($replace_items as $item) { - $filepath = BUILD_ROOT_PATH . "/{$item}"; - FileSystem::replaceFileStr( - $filepath, - array_values($placeholders), - array_keys($placeholders), - ); - } - // remove placeholder file - unlink($replace_item_file); - } - - /** - * Add lib dependency - */ - protected function addLibraryDependency(string $name, bool $optional = false): void - { - $dep_lib = $this->getBuilder()->getLib($name); - if ($dep_lib) { - $this->dependencies[$name] = $dep_lib; - return; - } - if (!$optional) { - throw new WrongUsageException(static::NAME . " requires library {$name} but it is not included"); - } - logger()->debug('enabling ' . static::NAME . " without {$name}"); - } - - protected function getSnakeCaseName(): string - { - return str_replace('-', '_', static::NAME); - } - - /** - * Install license files in buildroot directory - */ - protected function installLicense(): void - { - $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/{$source}/{$index}.txt", $license['text']); - continue; - } - if ($license['type'] === 'file') { - copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt"); - } - } - } - - protected function isLibraryInstalled(): bool - { - if ($pkg_configs = Config::getLib(static::NAME, 'pkg-configs', [])) { - $pkg_config_path = getenv('PKG_CONFIG_PATH') ?: ''; - $search_paths = array_unique(array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path))); - - foreach ($pkg_configs as $name) { - $found = false; - foreach ($search_paths as $path) { - if (file_exists($path . "/{$name}.pc")) { - $found = true; - break; - } - } - if (!$found) { - return false; - } - } - // allow using system dependencies if pkg_config_path is explicitly defined - if (count($search_paths) > 1) { - return true; - } - } - foreach (Config::getLib(static::NAME, 'static-libs', []) as $name) { - if (!file_exists(BUILD_LIB_PATH . "/{$name}")) { - return false; - } - } - foreach (Config::getLib(static::NAME, 'headers', []) as $name) { - if (!file_exists(BUILD_INCLUDE_PATH . "/{$name}")) { - 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) { - $found = false; - foreach ($search_paths as $path) { - if (file_exists($path . "/{$name}.pc")) { - $found = true; - break; - } - } - if (!$found) { - return false; - } - } - foreach (Config::getLib(static::NAME, 'bin', []) as $name) { - if (!file_exists(BUILD_BIN_PATH . "/{$name}")) { - return false; - } - } - return true; - } -} diff --git a/src/SPC/builder/LibraryInterface.php b/src/SPC/builder/LibraryInterface.php deleted file mode 100644 index 5368555e..00000000 --- a/src/SPC/builder/LibraryInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : ''; - FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lbz2/', $this->getLibFilesString() . $frameworks); - return true; - } -} diff --git a/src/SPC/builder/extension/com_dotnet.php b/src/SPC/builder/extension/com_dotnet.php deleted file mode 100644 index 7a8f6a4e..00000000 --- a/src/SPC/builder/extension/com_dotnet.php +++ /dev/null @@ -1,17 +0,0 @@ -info('patching before-configure for curl checks'); - $file1 = "AC_DEFUN([PHP_CHECK_LIBRARY], [\n $3\n])"; - $files = FileSystem::readFile($this->source_dir . '/config.m4'); - $file2 = 'AC_DEFUN([PHP_CHECK_LIBRARY], [ - save_old_LDFLAGS=$LDFLAGS - ac_stuff="$5" - - save_ext_shared=$ext_shared - ext_shared=yes - PHP_EVAL_LIBLINE([$]ac_stuff, LDFLAGS) - AC_CHECK_LIB([$1],[$2],[ - LDFLAGS=$save_old_LDFLAGS - ext_shared=$save_ext_shared - $3 - ],[ - LDFLAGS=$save_old_LDFLAGS - ext_shared=$save_ext_shared - unset ac_cv_lib_$1[]_$2 - $4 - ])dnl -])'; - file_put_contents($this->source_dir . '/config.m4', $file1 . "\n" . $files . "\n" . $file2); - return true; - } - - public function patchBeforeConfigure(): bool - { - $frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : ''; - FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lcurl/', $this->getLibFilesString() . $frameworks); - $this->patchBeforeSharedConfigure(); - return true; - } - - public function patchBeforeMake(): bool - { - $patched = parent::patchBeforeMake(); - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - if ($this->builder instanceof WindowsBuilder && !str_contains($extra_libs, 'secur32.lib')) { - $extra_libs .= ' secur32.lib'; - putenv('SPC_EXTRA_LIBS=' . trim($extra_libs)); - return true; - } - return $patched; - } - - public function patchBeforeSharedConfigure(): bool - { - $file = $this->source_dir . '/config.m4'; - $content = FileSystem::readFile($file); - - // Inject patch before it - $patch = ' save_LIBS="$LIBS" - LIBS="$LIBS $CURL_LIBS" -'; - // Check if already patched - if (str_contains($content, $patch)) { - return false; // Already patched - } - - // Match the line containing PHP_CHECK_LIBRARY for curl - $pattern = '/(PHP_CHECK_LIBRARY\(\[curl],\s*\[curl_easy_perform],)/'; - - // Restore LIBS after the check — append this just after the macro block - $restore = ' - LIBS="$save_LIBS"'; - - // Apply patch - $patched = preg_replace_callback($pattern, function ($matches) use ($patch) { - return $patch . $matches[1]; - }, $content, 1); - - // Inject restore after the matching PHP_CHECK_LIBRARY block - $patched = preg_replace( - '/(PHP_CHECK_LIBRARY\(\[curl],\s*\[curl_easy_perform],.*?\)\n)/s', - "$1{$restore}\n", - $patched, - 1 - ); - - if ($patched === null) { - throw new PatchException('shared extension curl patcher', 'Failed to patch config.m4 due to a regex error'); - } - - FileSystem::writeFile($file, $patched); - return true; - } - - public function buildUnixShared(): void - { - if (!$this->builder instanceof LinuxBuilder) { - parent::buildUnixShared(); - return; - } - - FileSystem::replaceFileStr( - $this->source_dir . '/config.m4', - ['$ext_dir/phar.1', '$ext_dir/phar.phar.1'], - ['${ext_dir}phar.1', '${ext_dir}phar.phar.1'] - ); - try { - parent::buildUnixShared(); - } finally { - FileSystem::replaceFileStr( - $this->source_dir . '/config.m4', - ['${ext_dir}phar.1', '${ext_dir}phar.phar.1'], - ['$ext_dir/phar.1', '$ext_dir/phar.phar.1'] - ); - } - } -} diff --git a/src/SPC/builder/extension/dba.php b/src/SPC/builder/extension/dba.php deleted file mode 100644 index d1f8cda3..00000000 --- a/src/SPC/builder/extension/dba.php +++ /dev/null @@ -1,24 +0,0 @@ -builder->getLib('qdbm') ? (' --with-qdbm=' . BUILD_ROOT_PATH) : ''; - return '--enable-dba' . ($shared ? '=shared' : '') . $qdbm; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - $qdbm = $this->builder->getLib('qdbm') ? ' --with-qdbm' : ''; - return '--with-dba' . $qdbm; - } -} diff --git a/src/SPC/builder/extension/dio.php b/src/SPC/builder/extension/dio.php deleted file mode 100644 index 55d08480..00000000 --- a/src/SPC/builder/extension/dio.php +++ /dev/null @@ -1,22 +0,0 @@ -getLibFilesString() . '"'; - $arg .= ' GLIB_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '"'; - $arg .= ' GLIB_LIBS="' . implode(' ', $glibs) . '"'; - return $arg; - } -} diff --git a/src/SPC/builder/extension/ev.php b/src/SPC/builder/extension/ev.php deleted file mode 100644 index 8e391244..00000000 --- a/src/SPC/builder/extension/ev.php +++ /dev/null @@ -1,27 +0,0 @@ -source_dir . '/config.w32', - 'EXTENSION(\'ev\'', - " EXTENSION('ev', php_ev_sources, PHP_EV_SHARED, ' /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');" - ); - return true; - } -} diff --git a/src/SPC/builder/extension/event.php b/src/SPC/builder/extension/event.php deleted file mode 100644 index 0a981f91..00000000 --- a/src/SPC/builder/extension/event.php +++ /dev/null @@ -1,45 +0,0 @@ -builder->getLib('openssl')) { - $arg .= ' --with-event-openssl=' . BUILD_ROOT_PATH; - } - if ($this->builder->getExt('sockets')) { - $arg .= ' --enable-event-sockets'; - } else { - $arg .= ' --disable-event-sockets'; - } - return $arg; - } - - public function patchBeforeConfigure(): bool - { - FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-levent_openssl/', $this->getLibFilesString()); - return true; - } - - public function patchBeforeMake(): bool - { - $patched = parent::patchBeforeMake(); - // Prevent event extension compile error on macOS - if ($this->builder instanceof MacOSBuilder) { - FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_OPENPTY 1$/m', ''); - return true; - } - return $patched; - } -} diff --git a/src/SPC/builder/extension/ffi.php b/src/SPC/builder/extension/ffi.php deleted file mode 100644 index 8e192bea..00000000 --- a/src/SPC/builder/extension/ffi.php +++ /dev/null @@ -1,32 +0,0 @@ -builder->getLib('freetype') ? ' --with-freetype' : ''; - $arg .= $this->builder->getLib('libjpeg') ? ' --with-jpeg' : ''; - $arg .= $this->builder->getLib('libwebp') ? ' --with-webp' : ''; - $arg .= $this->builder->getLib('libavif') ? ' --with-avif' : ''; - return $arg; - } -} diff --git a/src/SPC/builder/extension/gettext.php b/src/SPC/builder/extension/gettext.php deleted file mode 100644 index 303cc389..00000000 --- a/src/SPC/builder/extension/gettext.php +++ /dev/null @@ -1,35 +0,0 @@ -builder instanceof MacOSBuilder) { - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/gettext/config.m4', - ['AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB([$GETTEXT_CHECK_IN_LIB'], - ['AC_CHECK_LIB(intl', 'AC_CHECK_LIB([intl'] // new php versions use a bracket - ); - } - return true; - } - - public function patchBeforeConfigure(): bool - { - if ($this->builder instanceof MacOSBuilder) { - $frameworks = ' ' . $this->builder->getFrameworks(true) . ' '; - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lintl', $this->getLibFilesString() . $frameworks); - } - return true; - } -} diff --git a/src/SPC/builder/extension/glfw.php b/src/SPC/builder/extension/glfw.php deleted file mode 100644 index 7cfdaaaf..00000000 --- a/src/SPC/builder/extension/glfw.php +++ /dev/null @@ -1,38 +0,0 @@ -builder instanceof WindowsBuilder) { - throw new ValidationException('grpc extension does not support windows yet'); - } - - // Fix deprecated PHP API usage in call.c - FileSystem::replaceFileStr( - "{$this->source_dir}/src/php/ext/grpc/call.c", - 'zend_exception_get_default(TSRMLS_C),', - 'zend_ce_exception,', - ); - - // Fix include path conflict with pdo_sqlsrv: grpc's PHP ext dir is added to the global include path via - $grpc_php_dir = "{$this->source_dir}/src/php/ext/grpc"; - if (file_exists("{$grpc_php_dir}/version.h")) { - copy("{$grpc_php_dir}/version.h", "{$grpc_php_dir}/php_grpc_version.h"); - unlink("{$grpc_php_dir}/version.h"); - FileSystem::replaceFileStr("{$grpc_php_dir}/php_grpc.h", '#include "version.h"', '#include "php_grpc_version.h"'); - FileSystem::replaceFileStr("{$grpc_php_dir}/php_grpc.c", '#include "version.h"', '#include "php_grpc_version.h"'); - } - - $config_m4 = <<<'M4' -PHP_ARG_ENABLE(grpc, [whether to enable grpc support], [AS_HELP_STRING([--enable-grpc], [Enable grpc support])]) - -if test "$PHP_GRPC" != "no"; then - PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) - PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) - GRPC_LIBDIR=@@build_lib_path@@ - PHP_ADD_LIBPATH($GRPC_LIBDIR) - PHP_ADD_LIBRARY(grpc,,GRPC_SHARED_LIBADD) - LIBS="-lpthread $LIBS" - PHP_ADD_LIBRARY(pthread) - - case $host in - *darwin*) - PHP_ADD_LIBRARY(c++,1,GRPC_SHARED_LIBADD) - ;; - *) - PHP_ADD_LIBRARY(stdc++,1,GRPC_SHARED_LIBADD) - PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD) - PHP_ADD_LIBRARY(rt) - ;; - esac - - PHP_NEW_EXTENSION(grpc, @grpc_c_files@, $ext_shared, , -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1) - PHP_SUBST(GRPC_SHARED_LIBADD) - PHP_INSTALL_HEADERS([ext/grpc], [php_grpc.h]) -fi -M4; - $replace = get_pack_replace(); - // load grpc c files from src/php/ext/grpc - $c_files = glob($this->source_dir . '/src/php/ext/grpc/*.c'); - $replace['@grpc_c_files@'] = implode(" \\\n ", array_map(fn ($f) => 'src/php/ext/grpc/' . basename($f), $c_files)); - $config_m4 = str_replace(array_keys($replace), array_values($replace), $config_m4); - file_put_contents($this->source_dir . '/config.m4', $config_m4); - - copy($this->source_dir . '/src/php/ext/grpc/php_grpc.h', $this->source_dir . '/php_grpc.h'); - return true; - } - - public function patchBeforeConfigure(): bool - { - $util = new SPCConfigUtil($this->builder, ['libs_only_deps' => true]); - $config = $util->getExtensionConfig($this); - $libs = $config['libs']; - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lgrpc', $libs); - return true; - } - - public function patchBeforeMake(): bool - { - parent::patchBeforeMake(); - GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes'); - return true; - } - - protected function getSharedExtensionEnv(): array - { - $env = parent::getSharedExtensionEnv(); - $env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes'; - return $env; - } -} diff --git a/src/SPC/builder/extension/iconv.php b/src/SPC/builder/extension/iconv.php deleted file mode 100644 index e3178144..00000000 --- a/src/SPC/builder/extension/iconv.php +++ /dev/null @@ -1,27 +0,0 @@ -builder instanceof MacOSBuilder) { - return false; - } - $extra_libs = $this->builder->getOption('extra-libs', ''); - if (!str_contains($extra_libs, '-liconv')) { - $extra_libs .= ' -liconv'; - } - $this->builder->setOption('extra-libs', $extra_libs); - return true; - } -} diff --git a/src/SPC/builder/extension/imagick.php b/src/SPC/builder/extension/imagick.php deleted file mode 100644 index a548a8a3..00000000 --- a/src/SPC/builder/extension/imagick.php +++ /dev/null @@ -1,32 +0,0 @@ -builder->getLib('openssl')) { - // sometimes imap with openssl does not contain zlib (required by openssl) - // we need to add it manually - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/imap/config.m4', 'TST_LIBS="$DLIBS $IMAP_SHARED_LIBADD"', 'TST_LIBS="$DLIBS $IMAP_SHARED_LIBADD -lz"'); - return true; - } - return false; - } - - public function validate(): void - { - if ($this->builder->getOption('enable-zts')) { - throw new WrongUsageException('ext-imap is not thread safe, do not build it with ZTS builds'); - } - } - - public function getUnixConfigureArg(bool $shared = false): string - { - $arg = '--with-imap=' . BUILD_ROOT_PATH; - if ($this->builder->getLib('openssl') !== null) { - $arg .= ' --with-imap-ssl=' . BUILD_ROOT_PATH; - } - return $arg; - } - - public function patchBeforeMake(): bool - { - $patched = parent::patchBeforeMake(); - if (PHP_OS_FAMILY !== 'Linux' || SystemUtil::isMuslDist()) { - return $patched; - } - $extra_libs = trim((getenv('SPC_EXTRA_LIBS') ?: '') . ' -lcrypt'); - f_putenv('SPC_EXTRA_LIBS=' . $extra_libs); - return true; - } -} diff --git a/src/SPC/builder/extension/intl.php b/src/SPC/builder/extension/intl.php deleted file mode 100644 index 0c1e323d..00000000 --- a/src/SPC/builder/extension/intl.php +++ /dev/null @@ -1,32 +0,0 @@ -builder instanceof WindowsBuilder) { - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/intl/config.w32', - 'EXTENSION("intl", "php_intl.c intl_convert.c intl_convertcpp.cpp intl_error.c ", true,', - 'EXTENSION("intl", "php_intl.c intl_convert.c intl_convertcpp.cpp intl_error.c ", PHP_INTL_SHARED,' - ); - return true; - } - return false; - } - - public function patchBeforeSharedPhpize(): bool - { - return $this->patchBeforeBuildconf(); - } -} diff --git a/src/SPC/builder/extension/ldap.php b/src/SPC/builder/extension/ldap.php deleted file mode 100644 index 4616bea8..00000000 --- a/src/SPC/builder/extension/ldap.php +++ /dev/null @@ -1,23 +0,0 @@ -execWithResult('$PKG_CONFIG --libs-only-l --static ldap'); - if (!empty($output[1][0])) { - $libs = $output[1][0]; - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lldap ', $libs . ' '); - } - return true; - } -} diff --git a/src/SPC/builder/extension/lz4.php b/src/SPC/builder/extension/lz4.php deleted file mode 100644 index 5727a97d..00000000 --- a/src/SPC/builder/extension/lz4.php +++ /dev/null @@ -1,22 +0,0 @@ -source_dir; - FileSystem::copyDir($original . '/ext', SOURCE_PATH . '/php-src/ext/maxminddb'); - $this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb'; - return true; - } - $this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb'; - return false; - } -} diff --git a/src/SPC/builder/extension/mbregex.php b/src/SPC/builder/extension/mbregex.php deleted file mode 100644 index 1132eeb2..00000000 --- a/src/SPC/builder/extension/mbregex.php +++ /dev/null @@ -1,42 +0,0 @@ -builder->getExt('mbstring')->isBuildShared() ? '-d "extension_dir=' . BUILD_MODULES_PATH . '" -d "extension=mbstring"' : ''; - [$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $sharedext . ' --ri "mbstring" | grep regex', false); - if ($ret !== 0) { - throw new ValidationException("Extension {$this->getName()} failed compile check: compiled php-cli mbstring extension does not contain regex !"); - } - } - - public function runCliCheckWindows(): void - { - [$ret, $out] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "mbstring"', false); - if ($ret !== 0) { - throw new ValidationException("extension {$this->getName()} failed compile check: compiled php-cli does not contain mbstring !"); - } - $out = implode("\n", $out); - if (!str_contains($out, 'regex')) { - throw new ValidationException("extension {$this->getName()} failed compile check: compiled php-cli mbstring extension does not contain regex !"); - } - } -} diff --git a/src/SPC/builder/extension/mbstring.php b/src/SPC/builder/extension/mbstring.php deleted file mode 100644 index 3576877f..00000000 --- a/src/SPC/builder/extension/mbstring.php +++ /dev/null @@ -1,34 +0,0 @@ -builder->getExt('mbregex') === null) { - $arg .= ' --disable-mbregex'; - } else { - $arg .= ' --enable-mbregex'; - } - return $arg; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - $arg = '--enable-mbstring' . ($shared ? '=shared' : ''); - if ($this->builder->getExt('mbregex') === null) { - $arg .= ' --disable-mbregex'; - } else { - $arg .= ' --enable-mbregex'; - } - return $arg; - } -} diff --git a/src/SPC/builder/extension/memcache.php b/src/SPC/builder/extension/memcache.php deleted file mode 100644 index 32cb301c..00000000 --- a/src/SPC/builder/extension/memcache.php +++ /dev/null @@ -1,72 +0,0 @@ -isBuildStatic()) { - return false; - } - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/memcache/config9.m4', - 'if test -d $abs_srcdir/src ; then', - 'if test -d $abs_srcdir/main ; then' - ); - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/memcache/config9.m4', - 'export CPPFLAGS="$CPPFLAGS $INCLUDES"', - 'export CPPFLAGS="$CPPFLAGS $INCLUDES -I$abs_srcdir/main"' - ); - // add for in-tree building - file_put_contents( - SOURCE_PATH . '/php-src/ext/memcache/php_memcache.h', - <<<'EOF' -#ifndef PHP_MEMCACHE_H -#define PHP_MEMCACHE_H - -extern zend_module_entry memcache_module_entry; -#define phpext_memcache_ptr &memcache_module_entry - -#endif -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/memcached.php b/src/SPC/builder/extension/memcached.php deleted file mode 100644 index 983b5b64..00000000 --- a/src/SPC/builder/extension/memcached.php +++ /dev/null @@ -1,26 +0,0 @@ -builder->getLib('zstd') ? '--with-zstd ' : '') . - ($this->builder->getExt('igbinary') ? '--enable-memcached-igbinary ' : '') . - ($this->builder->getExt('session') ? '--enable-memcached-session ' : '') . - ($this->builder->getExt('msgpack') ? '--enable-memcached-msgpack ' : '') . - '--with-system-fastlz'; - } -} diff --git a/src/SPC/builder/extension/mongodb.php b/src/SPC/builder/extension/mongodb.php deleted file mode 100644 index 08861e4e..00000000 --- a/src/SPC/builder/extension/mongodb.php +++ /dev/null @@ -1,32 +0,0 @@ -builder->getLib('openssl')) { - $arg .= '--with-mongodb-ssl=openssl'; - } - $arg .= $this->builder->getLib('icu') ? ' --with-mongodb-icu=yes ' : ' --with-mongodb-icu=no '; - $arg .= $this->builder->getLib('zstd') ? ' --with-mongodb-zstd=yes ' : ' --with-mongodb-zstd=no '; - // $arg .= $this->builder->getLib('snappy') ? ' --with-mongodb-snappy=yes ' : ' --with-mongodb-snappy=no '; - $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 deleted file mode 100644 index 7b2b4abc..00000000 --- a/src/SPC/builder/extension/mysqlnd_ed25519.php +++ /dev/null @@ -1,22 +0,0 @@ -getConfigureArg(); - } -} diff --git a/src/SPC/builder/extension/mysqlnd_parsec.php b/src/SPC/builder/extension/mysqlnd_parsec.php deleted file mode 100644 index d044b1c5..00000000 --- a/src/SPC/builder/extension/mysqlnd_parsec.php +++ /dev/null @@ -1,22 +0,0 @@ -getConfigureArg(); - } -} diff --git a/src/SPC/builder/extension/odbc.php b/src/SPC/builder/extension/odbc.php deleted file mode 100644 index 278b5865..00000000 --- a/src/SPC/builder/extension/odbc.php +++ /dev/null @@ -1,17 +0,0 @@ -builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') { - throw new WrongUsageException('Statically compiled PHP with Zend Opcache only available for PHP >= 8.0 !'); - } - } - - public function patchBeforeBuildconf(): bool - { - $version = $this->builder->getPHPVersion(); - if (file_exists(SOURCE_PATH . '/php-src/.opcache_patched')) { - return false; - } - // if 8.2.0 <= PHP_VERSION < 8.2.23, we need to patch from legacy patch file - if (version_compare($version, '8.2.0', '>=') && version_compare($version, '8.2.23', '<')) { - SourcePatcher::patchFile('spc_fix_static_opcache_before_80222.patch', SOURCE_PATH . '/php-src'); - } - // if 8.3.0 <= PHP_VERSION < 8.3.11, we need to patch from legacy patch file - elseif (version_compare($version, '8.3.0', '>=') && version_compare($version, '8.3.11', '<')) { - SourcePatcher::patchFile('spc_fix_static_opcache_before_80310.patch', SOURCE_PATH . '/php-src'); - } - // if 8.3.12 <= PHP_VERSION < 8.5.0-dev, we need to patch from legacy patch file - elseif (version_compare($version, '8.5.0-dev', '<')) { - SourcePatcher::patchMicro(items: ['static_opcache']); - } - // PHP 8.5.0-dev and later supports static opcache without patching - else { - return false; - } - return file_put_contents(SOURCE_PATH . '/php-src/.opcache_patched', '1') !== false; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - $phpVersionID = $this->builder->getPHPVersionID(); - $opcache_jit = ' --enable-opcache-jit'; - if ((SPCTarget::getTargetOS() === 'Linux' && - SPCTarget::getLibc() === 'musl' && - $this->builder->getOption('enable-zts') && - arch2gnu(php_uname('m')) === 'x86_64' && - $phpVersionID < 80500) || - $this->builder->getOption('disable-opcache-jit') - ) { - $opcache_jit = ' --disable-opcache-jit'; - } - return '--enable-opcache' . ($shared ? '=shared' : '') . $opcache_jit; - } - - public function getDistName(): string - { - return 'Zend Opcache'; - } -} diff --git a/src/SPC/builder/extension/openssl.php b/src/SPC/builder/extension/openssl.php deleted file mode 100644 index bf61fa37..00000000 --- a/src/SPC/builder/extension/openssl.php +++ /dev/null @@ -1,45 +0,0 @@ -builder->getPHPVersionID() < 80100) { - $openssl_c = file_get_contents(SOURCE_PATH . '/php-src/ext/openssl/openssl.c'); - $openssl_c = preg_replace('/REGISTER_LONG_CONSTANT\s*\(\s*"OPENSSL_SSLV23_PADDING"\s*.+;/', '', $openssl_c); - file_put_contents(SOURCE_PATH . '/php-src/ext/openssl/openssl.c', $openssl_c); - return true; - } - - return $patched; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - $openssl_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : ' --with-openssl-dir=' . BUILD_ROOT_PATH; - $args = '--with-openssl=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $openssl_dir; - if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) { - $args .= ' --with-openssl-argon2 OPENSSL_LIBS="-lz"'; - } - return $args; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - $args = '--with-openssl'; - if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) { - $args .= ' --with-openssl-argon2'; - } - return $args; - } -} diff --git a/src/SPC/builder/extension/opentelemetry.php b/src/SPC/builder/extension/opentelemetry.php deleted file mode 100644 index 924c9ea2..00000000 --- a/src/SPC/builder/extension/opentelemetry.php +++ /dev/null @@ -1,43 +0,0 @@ -builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') { - throw new ValidationException('The opentelemetry extension requires PHP 8.0 or later'); - } - } - - public function patchBeforeBuildconf(): bool - { - if (PHP_OS_FAMILY === 'Windows') { - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/opentelemetry/config.w32', - "EXTENSION('opentelemetry', 'opentelemetry.c otel_observer.c', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');", - "EXTENSION('opentelemetry', 'opentelemetry.c otel_observer.c', PHP_OPENTELEMETRY_SHARED, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');" - ); - return true; - } - return false; - } - - public function patchBeforeMake(): bool - { - parent::patchBeforeMake(); - // add -Wno-strict-prototypes - GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes'); - return true; - } -} diff --git a/src/SPC/builder/extension/parallel.php b/src/SPC/builder/extension/parallel.php deleted file mode 100644 index de4e5d88..00000000 --- a/src/SPC/builder/extension/parallel.php +++ /dev/null @@ -1,27 +0,0 @@ -builder->getOption('enable-zts')) { - throw new WrongUsageException('ext-parallel must be built with ZTS builds. Use "--enable-zts" option!'); - } - } - - public function patchBeforeBuildconf(): bool - { - FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/parallel/config.m4', '/PHP_VERSION=.*/m', ''); - return true; - } -} diff --git a/src/SPC/builder/extension/password_argon2.php b/src/SPC/builder/extension/password_argon2.php deleted file mode 100644 index d42fe4e3..00000000 --- a/src/SPC/builder/extension/password_argon2.php +++ /dev/null @@ -1,36 +0,0 @@ -execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "assert(defined(\'PASSWORD_ARGON2I\'));"'); - if ($ret !== 0) { - throw new ValidationException('extension ' . $this->getName() . ' failed sanity check', validation_module: 'password_argon2 function check'); - } - } - - public function getConfigureArg(bool $shared = false): string - { - if ($this->builder->getLib('openssl') !== null) { - if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) { - return '--without-password-argon2'; // use --with-openssl-argon2 in openssl extension instead - } - } - return '--with-password-argon2'; - } -} diff --git a/src/SPC/builder/extension/pdo_odbc.php b/src/SPC/builder/extension/pdo_odbc.php deleted file mode 100644 index c47144fe..00000000 --- a/src/SPC/builder/extension/pdo_odbc.php +++ /dev/null @@ -1,29 +0,0 @@ -getLibFilesString() - ); - return true; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - if ($this->builder->getPHPVersionID() >= 80400) { - $libfiles = $this->getLibFilesString(); - $libfiles = str_replace(BUILD_LIB_PATH . '/lib', '-l', $libfiles); - $libfiles = str_replace('.a', '', $libfiles); - return '--with-pgsql' . ($shared ? '=shared' : '') . - ' PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH . - ' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' ' . $libfiles . '"'; - } - return '--with-pgsql=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - if ($this->builder->getPHPVersionID() >= 80400) { - return '--with-pgsql'; - } - return '--with-pgsql=' . BUILD_ROOT_PATH; - } - - protected function getExtraEnv(): array - { - return [ - 'CFLAGS' => '-std=c17 -Wno-int-conversion', - ]; - } -} diff --git a/src/SPC/builder/extension/phar.php b/src/SPC/builder/extension/phar.php deleted file mode 100644 index 7396ba83..00000000 --- a/src/SPC/builder/extension/phar.php +++ /dev/null @@ -1,37 +0,0 @@ -builder instanceof LinuxBuilder) { - parent::buildUnixShared(); - return; - } - - FileSystem::replaceFileStr( - $this->source_dir . '/config.m4', - ['$ext_dir/phar.1', '$ext_dir/phar.phar.1'], - ['${ext_dir}phar.1', '${ext_dir}phar.phar.1'] - ); - try { - parent::buildUnixShared(); - } finally { - FileSystem::replaceFileStr( - $this->source_dir . '/config.m4', - ['${ext_dir}phar.1', '${ext_dir}phar.phar.1'], - ['$ext_dir/phar.1', '$ext_dir/phar.phar.1'] - ); - } - } -} diff --git a/src/SPC/builder/extension/protobuf.php b/src/SPC/builder/extension/protobuf.php deleted file mode 100644 index fd84dfec..00000000 --- a/src/SPC/builder/extension/protobuf.php +++ /dev/null @@ -1,25 +0,0 @@ -builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') { - throw new ValidationException('The latest protobuf extension requires PHP 8.0 or later'); - } - $grpc = $this->builder->getExt('grpc'); - // protobuf conflicts with grpc - if ($grpc?->isBuildStatic()) { - throw new ValidationException('protobuf conflicts with grpc, please remove grpc or protobuf extension'); - } - } -} diff --git a/src/SPC/builder/extension/rar.php b/src/SPC/builder/extension/rar.php deleted file mode 100644 index 6db8c03c..00000000 --- a/src/SPC/builder/extension/rar.php +++ /dev/null @@ -1,24 +0,0 @@ -= 15.0) - if ($this->builder instanceof MacOSBuilder) { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/rar/config.m4', '-Wall -fvisibility=hidden', '-Wall -Wno-incompatible-function-pointer-types -fvisibility=hidden'); - return true; - } - return false; - } -} diff --git a/src/SPC/builder/extension/rdkafka.php b/src/SPC/builder/extension/rdkafka.php deleted file mode 100644 index 58af50ff..00000000 --- a/src/SPC/builder/extension/rdkafka.php +++ /dev/null @@ -1,45 +0,0 @@ -source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\n", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm \$RDKAFKA_LIBS\n"); - FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\"\n", '-L$RDKAFKA_DIR/$PHP_LIBDIR -lm $RDKAFKA_LIBS"'); - FileSystem::replaceFileStr("{$this->source_dir}/config.m4", 'PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,', 'AC_CHECK_LIB([$LIBNAME], [$LIBSYMBOL],'); - return true; - } - - public function patchBeforeMake(): bool - { - parent::patchBeforeMake(); - // when compiling rdkafka with inline builds, it shows some errors, I don't know why. - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/rdkafka/rdkafka.c', - "#ifdef HAS_RD_KAFKA_TRANSACTIONS\n#include \"kafka_error_exception.h\"\n#endif", - '#include "kafka_error_exception.h"' - ); - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/rdkafka/kafka_error_exception.h', - ['#ifdef HAS_RD_KAFKA_TRANSACTIONS', '#endif'], - '' - ); - return true; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - $pkgconf_libs = (new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]))->getExtensionConfig($this); - return '--with-rdkafka=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . " RDKAFKA_LIBS=\"{$pkgconf_libs['libs']}\""; - } -} diff --git a/src/SPC/builder/extension/readline.php b/src/SPC/builder/extension/readline.php deleted file mode 100644 index 035d7b43..00000000 --- a/src/SPC/builder/extension/readline.php +++ /dev/null @@ -1,47 +0,0 @@ -getLibFilesString() - ); - return true; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - return '--with-libedit --without-readline'; - } - - public function buildUnixShared(): void - { - if (!file_exists(BUILD_BIN_PATH . '/php') || !file_exists(BUILD_INCLUDE_PATH . '/php/sapi/cli/cli.h')) { - logger()->warning('CLI mode is not enabled, skipping readline build'); - return; - } - parent::buildUnixShared(); - } - - public function runCliCheckUnix(): void - { - parent::runCliCheckUnix(); - [$ret, $out] = shell()->execWithResult('printf "exit\n" | ' . BUILD_BIN_PATH . '/php -a'); - if ($ret !== 0 || !str_contains(implode("\n", $out), 'Interactive shell')) { - throw new ValidationException("readline extension failed sanity check. Code: {$ret}, output: " . implode("\n", $out)); - } - } -} diff --git a/src/SPC/builder/extension/redis.php b/src/SPC/builder/extension/redis.php deleted file mode 100644 index 4dd59565..00000000 --- a/src/SPC/builder/extension/redis.php +++ /dev/null @@ -1,41 +0,0 @@ -isBuildStatic()) { - $arg .= $this->builder->getExt('session')?->isBuildStatic() ? ' --enable-redis-session' : ' --disable-redis-session'; - $arg .= $this->builder->getExt('igbinary')?->isBuildStatic() ? ' --enable-redis-igbinary' : ' --disable-redis-igbinary'; - $arg .= $this->builder->getExt('msgpack')?->isBuildStatic() ? ' --enable-redis-msgpack' : ' --disable-redis-msgpack'; - } else { - $arg .= $this->builder->getExt('session') ? ' --enable-redis-session' : ' --disable-redis-session'; - $arg .= $this->builder->getExt('igbinary') ? ' --enable-redis-igbinary' : ' --disable-redis-igbinary'; - $arg .= $this->builder->getExt('msgpack') ? ' --enable-redis-msgpack' : ' --disable-redis-msgpack'; - } - if ($this->builder->getLib('zstd')) { - $arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '"'; - } - if ($this->builder->getLib('liblz4')) { - $arg .= ' --enable-redis-lz4 --with-liblz4="' . BUILD_ROOT_PATH . '"'; - } - return $arg; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - $arg = '--enable-redis'; - $arg .= $this->builder->getExt('session') ? ' --enable-redis-session' : ' --disable-redis-session'; - $arg .= $this->builder->getExt('igbinary') ? ' --enable-redis-igbinary' : ' --disable-redis-igbinary'; - return $arg; - } -} diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php deleted file mode 100644 index 914fd674..00000000 --- a/src/SPC/builder/extension/simdjson.php +++ /dev/null @@ -1,50 +0,0 @@ -builder->getPHPVersionID(); - FileSystem::replaceFileRegex( - SOURCE_PATH . '/php-src/ext/simdjson/config.m4', - '/php_version=(`.*`)$/m', - 'php_version=' . $php_ver - ); - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/simdjson/config.m4', - 'if test -z "$PHP_CONFIG"; then', - 'if false; then' - ); - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/simdjson/config.w32', - "'yes',", - 'PHP_SIMDJSON_SHARED,' - ); - return true; - } - - public function getSharedExtensionEnv(): array - { - $env = parent::getSharedExtensionEnv(); - if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $extra = getenv('SPC_COMPILER_EXTRA'); - if (!str_contains((string) $extra, '-lstdc++')) { - f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++')); - } - $env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; - $env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; - } - return $env; - } -} diff --git a/src/SPC/builder/extension/snappy.php b/src/SPC/builder/extension/snappy.php deleted file mode 100644 index 13644edf..00000000 --- a/src/SPC/builder/extension/snappy.php +++ /dev/null @@ -1,29 +0,0 @@ -getLibFilesString() . ($this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++') - ); - return true; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - return '--enable-snappy --with-snappy-includedir="' . BUILD_ROOT_PATH . '"'; - } -} diff --git a/src/SPC/builder/extension/snmp.php b/src/SPC/builder/extension/snmp.php deleted file mode 100644 index 488fc81e..00000000 --- a/src/SPC/builder/extension/snmp.php +++ /dev/null @@ -1,29 +0,0 @@ -builder->getPHPVersionID() < 80400) { - FileSystem::copy(ROOT_DIR . '/src/globals/extra/snmp-ext-config-old.m4', "{$this->source_dir}/config.m4"); - } - $libs = implode(' ', PkgConfigUtil::getLibsArray('netsnmp')); - FileSystem::replaceFileStr( - "{$this->source_dir}/config.m4", - 'PHP_EVAL_LIBLINE([$SNMP_LIBS], [SNMP_SHARED_LIBADD])', - "SNMP_LIBS=\"{$libs}\"\nPHP_EVAL_LIBLINE([\$SNMP_LIBS], [SNMP_SHARED_LIBADD])" - ); - return true; - } -} diff --git a/src/SPC/builder/extension/spx.php b/src/SPC/builder/extension/spx.php deleted file mode 100644 index e7723293..00000000 --- a/src/SPC/builder/extension/spx.php +++ /dev/null @@ -1,55 +0,0 @@ -builder->getLib('zlib') !== null) { - $arg .= ' --with-zlib-dir=' . BUILD_ROOT_PATH; - } - return $arg; - } - - public function patchBeforeConfigure(): bool - { - FileSystem::replaceFileStr( - $this->source_dir . '/Makefile.frag', - '@cp -r assets/web-ui/*', - '@cp -r ' . $this->source_dir . '/assets/web-ui/*', - ); - return true; - } - - public function patchBeforeBuildconf(): bool - { - FileSystem::replaceFileStr( - $this->source_dir . '/config.m4', - 'CFLAGS="$CFLAGS -Werror -Wall -O3 -pthread -std=gnu90"', - 'CFLAGS="$CFLAGS -pthread"' - ); - FileSystem::replaceFileStr( - $this->source_dir . '/src/php_spx.h', - "extern zend_module_entry spx_module_entry;\n", - "extern zend_module_entry spx_module_entry;;\n#define phpext_spx_ptr &spx_module_entry\n" - ); - FileSystem::copy($this->source_dir . '/src/php_spx.h', $this->source_dir . '/php_spx.h'); - return true; - } - - public function getSharedExtensionEnv(): array - { - $env = parent::getSharedExtensionEnv(); - $env['SPX_SHARED_LIBADD'] = $env['LIBS']; - return $env; - } -} diff --git a/src/SPC/builder/extension/sqlsrv.php b/src/SPC/builder/extension/sqlsrv.php deleted file mode 100644 index fa55b932..00000000 --- a/src/SPC/builder/extension/sqlsrv.php +++ /dev/null @@ -1,46 +0,0 @@ -builder->getExt('pdo_sqlsrv') === null) { - // support sqlsrv without pdo_sqlsrv - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/sqlsrv/config.w32', 'PHP_PDO_SQLSRV', '"no"'); - $this->pdo_sqlsrv_patched = true; - return true; - } - return false; - } - - public function patchBeforeWindowsConfigure(): bool - { - if ($this->pdo_sqlsrv_patched) { - // revert pdo_sqlsrv patch - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/sqlsrv/config.w32', '"no" == "no"', 'PHP_PDO_SQLSRV == "no"'); - return true; - } - return false; - } - - public function patchBeforeMake(): bool - { - $makefile = SOURCE_PATH . '/php-src/Makefile'; - $makeContent = file_get_contents($makefile); - $makeContent = preg_replace('/^(CFLAGS_(?:PDO_)?SQLSRV=.*?)\s+\/W4\b/m', '$1', $makeContent); - $makeContent = preg_replace('/^(CFLAGS_(?:PDO_)?SQLSRV=.*?)\s+\/WX\b/m', '$1', $makeContent); - file_put_contents($makefile, $makeContent); - return true; - } -} diff --git a/src/SPC/builder/extension/ssh2.php b/src/SPC/builder/extension/ssh2.php deleted file mode 100644 index aa6a439d..00000000 --- a/src/SPC/builder/extension/ssh2.php +++ /dev/null @@ -1,23 +0,0 @@ -getLibFilesString() - ); - return true; - } -} diff --git a/src/SPC/builder/extension/swoole.php b/src/SPC/builder/extension/swoole.php deleted file mode 100644 index 7da30ba6..00000000 --- a/src/SPC/builder/extension/swoole.php +++ /dev/null @@ -1,86 +0,0 @@ -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'; - FileSystem::replaceFileStr( - "{$this->source_dir}/thirdparty/php/standard/proc_open.cc", - 'include ', - 'include "' . $util_path . '"', - ); - return true; - } - return $patched; - } - - public function getExtVersion(): ?string - { - // Get version from source directory - $file = SOURCE_PATH . '/php-src/ext/swoole/include/swoole_version.h'; - // Match #define SWOOLE_VERSION "5.1.3" - $pattern = '/#define SWOOLE_VERSION "(.+)"/'; - if (preg_match($pattern, file_get_contents($file), $matches)) { - return $matches[1]; - } - return null; - } - - public function getUnixConfigureArg(bool $shared = false): string - { - // enable swoole - $arg = '--enable-swoole' . ($shared ? '=shared' : ''); - - // commonly used feature: coroutine-time - $arg .= ' --enable-swoole-coro-time --with-pic'; - $arg .= ' --enable-swoole-ssh --enable-swoole-curl'; - - $arg .= $this->builder->getOption('enable-zts') ? ' --enable-swoole-thread --disable-thread-context' : ' --disable-swoole-thread --enable-thread-context'; - - // additional features that only require libraries - $arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : ''; - $arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : ''; - $arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : ''; - $arg .= $this->builder->getLib('zstd') ? ' --enable-zstd' : ''; - $arg .= $this->builder->getLib('liburing') && getenv('SPC_LIBC') !== 'glibc' ? ' --enable-iouring --enable-uring-socket' : '--disable-iouring'; - $arg .= $this->builder->getExt('sockets') ? ' --enable-sockets' : ''; - - // enable additional features that require the pdo extension, but conflict with pdo_* extensions - // to make sure everything works as it should, this is done in fake addon extensions - $arg .= $this->builder->getExt('swoole-hook-pgsql') ? ' --enable-swoole-pgsql' : ' --disable-swoole-pgsql'; - $arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd'; - $arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite'; - if ($this->builder->getExt('swoole-hook-odbc')) { - $config = (new SPCConfigUtil($this->builder))->getLibraryConfig($this->builder->getLib('unixodbc')); - $arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"'; - } - $arg .= $this->builder->getExt('ftp')?->isBuildStatic() ? ' --disable-swoole-ftp' : ' --enable-swoole-ftp'; - - if ($this->getExtVersion() >= '6.1.0') { - $arg .= ' --enable-swoole-stdext'; - } - - if (SPCTarget::getTargetOS() === 'Darwin') { - $arg .= ' ac_cv_lib_pthread_pthread_barrier_init=no'; - } - - return $arg; - } -} diff --git a/src/SPC/builder/extension/swoole_hook_mysql.php b/src/SPC/builder/extension/swoole_hook_mysql.php deleted file mode 100644 index f60f4f8e..00000000 --- a/src/SPC/builder/extension/swoole_hook_mysql.php +++ /dev/null @@ -1,30 +0,0 @@ -execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false); - $out = implode('', $out); - if ($ret !== 0) { - throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: 'extension swoole_hook_mysql sanity check'); - } - if (!str_contains($out, 'mysqlnd')) { - throw new ValidationException('swoole mysql hook is not enabled correctly.', validation_module: 'Extension swoole mysql hook availability check'); - } - } -} diff --git a/src/SPC/builder/extension/swoole_hook_odbc.php b/src/SPC/builder/extension/swoole_hook_odbc.php deleted file mode 100644 index 8586dc51..00000000 --- a/src/SPC/builder/extension/swoole_hook_odbc.php +++ /dev/null @@ -1,40 +0,0 @@ -builder->getExt('pdo_odbc')?->isBuildStatic()) { - throw new WrongUsageException('swoole-hook-odbc provides pdo_odbc, if you enable odbc hook for swoole, you must remove pdo_odbc extension.'); - } - } - - public function runCliCheckUnix(): void - { - $sharedExtensions = $this->getSharedExtensionLoadString(); - [$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false); - $out = implode('', $out); - if ($ret !== 0) { - throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check"); - } - if (!str_contains($out, 'coroutine_odbc')) { - throw new ValidationException('swoole odbc hook is not enabled correctly.', validation_module: 'Extension swoole odbc hook availability check'); - } - } -} diff --git a/src/SPC/builder/extension/swoole_hook_pgsql.php b/src/SPC/builder/extension/swoole_hook_pgsql.php deleted file mode 100644 index bb2b4cfd..00000000 --- a/src/SPC/builder/extension/swoole_hook_pgsql.php +++ /dev/null @@ -1,46 +0,0 @@ -builder->getExt('pdo_pgsql')?->isBuildStatic()) { - throw new WrongUsageException('swoole-hook-pgsql provides pdo_pgsql, if you enable pgsql hook for swoole, you must remove pdo_pgsql extension.'); - } - } - - public function runCliCheckUnix(): void - { - $sharedExtensions = $this->getSharedExtensionLoadString(); - [$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false); - $out = implode('', $out); - if ($ret !== 0) { - throw new ValidationException( - "extension {$this->getName()} failed sanity check: php-cli returned {$ret}", - validation_module: 'Extension swoole-hook-pgsql sanity check' - ); - } - if (!str_contains($out, 'coroutine_pgsql')) { - throw new ValidationException( - 'swoole pgsql hook is not enabled correctly.', - validation_module: 'Extension swoole pgsql hook availability check' - ); - } - } -} diff --git a/src/SPC/builder/extension/swoole_hook_sqlite.php b/src/SPC/builder/extension/swoole_hook_sqlite.php deleted file mode 100644 index d87342ba..00000000 --- a/src/SPC/builder/extension/swoole_hook_sqlite.php +++ /dev/null @@ -1,40 +0,0 @@ -builder->getExt('pdo_sqlite')?->isBuildStatic()) { - throw new WrongUsageException('swoole-hook-sqlite provides pdo_sqlite, if you enable sqlite hook for swoole, you must remove pdo_sqlite extension.'); - } - } - - public function runCliCheckUnix(): void - { - $sharedExtensions = $this->getSharedExtensionLoadString(); - [$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false); - $out = implode('', $out); - if ($ret !== 0) { - throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check"); - } - if (!str_contains($out, 'coroutine_sqlite')) { - throw new ValidationException('swoole sqlite hook is not enabled correctly.', validation_module: 'Extension swoole sqlite hook availability check'); - } - } -} diff --git a/src/SPC/builder/extension/swow.php b/src/SPC/builder/extension/swow.php deleted file mode 100644 index e2a5cbad..00000000 --- a/src/SPC/builder/extension/swow.php +++ /dev/null @@ -1,41 +0,0 @@ -builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') { - throw new ValidationException('The latest swow extension requires PHP 8.0 or later'); - } - } - - public function getConfigureArg(bool $shared = false): string - { - $arg = '--enable-swow'; - $arg .= $this->builder->getLib('openssl') ? ' --enable-swow-ssl' : ' --disable-swow-ssl'; - $arg .= $this->builder->getLib('curl') ? ' --enable-swow-curl' : ' --disable-swow-curl'; - return $arg; - } - - public function patchBeforeBuildconf(): bool - { - if ($this->builder->getPHPVersionID() >= 80000 && !is_link(SOURCE_PATH . '/php-src/ext/swow')) { - if (PHP_OS_FAMILY === 'Windows') { - f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && mklink /D swow swow-src\ext'); - } else { - f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && ln -s swow-src/ext swow'); - } - return true; - } - return false; - } -} diff --git a/src/SPC/builder/extension/trader.php b/src/SPC/builder/extension/trader.php deleted file mode 100644 index 03021529..00000000 --- a/src/SPC/builder/extension/trader.php +++ /dev/null @@ -1,19 +0,0 @@ -builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') { - throw new ValidationException('The latest uv extension requires PHP 8.0 or later'); - } - } - - public function patchBeforeSharedMake(): bool - { - parent::patchBeforeSharedMake(); - if (PHP_OS_FAMILY !== 'Linux' || arch2gnu(php_uname('m')) !== 'aarch64') { - return false; - } - FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/^(LDFLAGS =.*)$/m', '$1 -luv -ldl -lrt -pthread'); - return true; - } -} diff --git a/src/SPC/builder/extension/xhprof.php b/src/SPC/builder/extension/xhprof.php deleted file mode 100644 index c3d98aac..00000000 --- a/src/SPC/builder/extension/xhprof.php +++ /dev/null @@ -1,33 +0,0 @@ -builder->getLib('openssl')) { - $arg .= ' --with-openssl=' . BUILD_ROOT_PATH; - } - return $arg; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - return '--with-xlswriter'; - } - - public function patchBeforeMake(): bool - { - $patched = parent::patchBeforeMake(); - - // Remove when https://github.com/viest/php-ext-xlswriter/pull/560 is merged - if (PHP_OS_FAMILY !== 'Windows') { - GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -std=gnu17'); - $patched = true; - } - - if (PHP_OS_FAMILY === 'Windows') { - // fix windows build with openssl extension duplicate symbol bug - SourcePatcher::patchFile('spc_fix_xlswriter_win32.patch', $this->source_dir); - $content = file_get_contents($this->source_dir . '/library/libxlsxwriter/src/theme.c'); - $bom = pack('CCC', 0xEF, 0xBB, 0xBF); - if (!str_starts_with($content, $bom)) { - file_put_contents($this->source_dir . '/library/libxlsxwriter/src/theme.c', $bom . $content); - } - return true; - } - return $patched; - } - - // Remove when https://github.com/viest/php-ext-xlswriter/pull/560 is merged - protected function getExtraEnv(): array - { - return ['CFLAGS' => '-std=gnu17']; - } -} diff --git a/src/SPC/builder/extension/xml.php b/src/SPC/builder/extension/xml.php deleted file mode 100644 index a111ed39..00000000 --- a/src/SPC/builder/extension/xml.php +++ /dev/null @@ -1,52 +0,0 @@ -name) { - 'xml' => '--enable-xml', - 'soap' => '--enable-soap', - 'xmlreader' => '--enable-xmlreader', - 'xmlwriter' => '--enable-xmlwriter', - 'simplexml' => '--enable-simplexml', - default => throw new SPCInternalException('Not accept non-xml extension'), - }; - $arg .= ($shared ? '=shared' : '') . ' --with-libxml="' . BUILD_ROOT_PATH . '"'; - return $arg; - } - - public function patchBeforeBuildconf(): bool - { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/win32/build/config.w32', 'dllmain.c ', ''); - return true; - } - - public function getWindowsConfigureArg(bool $shared = false): string - { - $arg = match ($this->name) { - 'xml' => '--with-xml', - 'soap' => '--enable-soap', - 'xmlreader' => '--enable-xmlreader', - 'xmlwriter' => '--enable-xmlwriter', - 'simplexml' => '--with-simplexml', - default => throw new SPCInternalException('Not accept non-xml extension'), - }; - $arg .= ' --with-libxml'; - return $arg; - } -} diff --git a/src/SPC/builder/extension/yac.php b/src/SPC/builder/extension/yac.php deleted file mode 100644 index 335aafa1..00000000 --- a/src/SPC/builder/extension/yac.php +++ /dev/null @@ -1,26 +0,0 @@ -builder->getPHPVersionID() >= 80400 ? '' : ' --with-zlib-dir=' . BUILD_ROOT_PATH; - return '--with-zlib' . $zlib_dir; - } -} diff --git a/src/SPC/builder/extension/zstd.php b/src/SPC/builder/extension/zstd.php deleted file mode 100644 index 3a6df602..00000000 --- a/src/SPC/builder/extension/zstd.php +++ /dev/null @@ -1,17 +0,0 @@ -options = $options; - - // ---------- set necessary options ---------- - // set C Compiler (default: clang) - f_putenv('CC=' . $this->getOption('cc', 'clang')); - // set C++ Compiler (default: clang++) - f_putenv('CXX=' . $this->getOption('cxx', 'clang++')); - // set PATH - f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH')); - - // set arch (default: current) - $this->setOptionIfNotExist('arch', php_uname('m')); - $this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch'))); - - // ---------- set necessary compile environments ---------- - // concurrency - $this->concurrency = SystemUtil::getCpuCount(); - // cflags - $this->arch_c_flags = SystemUtil::getArchCFlags($this->getOption('arch')); - $this->arch_cxx_flags = SystemUtil::getArchCFlags($this->getOption('arch')); - - // create pkgconfig and include dir (some libs cannot create them automatically) - f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true); - f_mkdir(BUILD_INCLUDE_PATH, recursive: true); - } - - /** - * Just start to build statically linked php binary - * - * @param int $build_target build target - */ - public function buildPHP(int $build_target = BUILD_TARGET_NONE): void - { - $this->emitPatchPoint('before-php-buildconf'); - SourcePatcher::patchBeforeBuildconf($this); - - shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force'); - - $this->emitPatchPoint('before-php-configure'); - SourcePatcher::patchBeforeConfigure($this); - - $json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : ''; - $zts_enable = $this->getPHPVersionID() < 80000 ? '--enable-maintainer-zts --disable-zend-signals' : '--enable-zts --disable-zend-signals'; - $zts = $this->getOption('enable-zts', false) ? $zts_enable : ''; - - $config_file_path = $this->getOption('with-config-file-path', false) ? - ('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : ''; - $config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ? - ('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : ''; - - $enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI; - $enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; - $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; - $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; - $enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP; - - shell()->cd(SOURCE_PATH . '/php-src') - ->exec( - './configure ' . - '--prefix= ' . - '--with-valgrind=no ' . // Not detect memory leak - '--enable-shared=no ' . - '--enable-static=yes ' . - "CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " . - '--disable-all ' . - '--disable-cgi ' . - '--disable-phpdbg ' . - ($enableCli ? '--enable-cli ' : '--disable-cli ') . - ($enableFpm ? '--enable-fpm ' : '--disable-fpm ') . - ($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') . - ($enableMicro ? '--enable-micro ' : '--disable-micro ') . - $config_file_path . - $config_file_scan_dir . - $json_74 . - $zts . - $this->makeStaticExtensionArgs() - ); - - $this->emitPatchPoint('before-php-make'); - SourcePatcher::patchBeforeMake($this); - - $this->cleanMake(); - - if ($enableCli) { - logger()->info('building cli'); - $this->buildCli(); - } - if ($enableFpm) { - logger()->info('building fpm'); - $this->buildFpm(); - } - if ($enableMicro) { - logger()->info('building micro'); - $this->buildMicro(); - } - if ($enableEmbed) { - logger()->info('building embed'); - if ($enableMicro) { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la'); - } - $this->buildEmbed(); - } - $shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared')))); - if (!empty($shared_extensions)) { - logger()->info('Building shared extensions ...'); - $this->buildSharedExts(); - } - if ($enableFrankenphp) { - logger()->info('building frankenphp'); - $this->buildFrankenphp(); - } - } - - public function testPHP(int $build_target = BUILD_TARGET_NONE) - { - if (php_uname('m') === $this->getOption('arch')) { - $this->emitPatchPoint('before-sanity-check'); - $this->sanityCheck($build_target); - } - } - - /** - * Build cli sapi - */ - protected function buildCli(): void - { - $vars = SystemUtil::makeEnvVarString([ - 'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a", - ]); - - $shell = shell()->cd(SOURCE_PATH . '/php-src'); - $shell->exec('sed -ie "s|//lib|/lib|g" Makefile'); - $shell->exec("make -j{$this->concurrency} {$vars} cli"); - if (!$this->getOption('no-strip', false)) { - $shell->exec('strip sapi/cli/php'); - } - $this->deploySAPIBinary(BUILD_TARGET_CLI); - } - - /** - * Build phpmicro sapi - */ - protected function buildMicro(): void - { - if ($this->getPHPVersionID() < 80000) { - throw new WrongUsageException('phpmicro only support PHP >= 8.0!'); - } - if ($this->getExt('phar')) { - $this->phar_patched = true; - SourcePatcher::patchMicroPhar($this->getPHPVersionID()); - } - - $enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : ''; - $vars = [ - // with debug information, optimize for size, remove identifiers, patch fake cli for micro - 'EXTRA_CFLAGS' => '-g -Os' . $enable_fake_cli, - // link resolv library (macOS needs it) - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a", - ]; - $vars = SystemUtil::makeEnvVarString($vars); - - shell()->cd(SOURCE_PATH . '/php-src') - ->exec("make -j{$this->concurrency} {$vars} micro"); - - if (!$this->getOption('no-strip', false)) { - shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-unneeded micro.sfx'); - } - $this->deploySAPIBinary(BUILD_TARGET_MICRO); - - if ($this->phar_patched) { - SourcePatcher::unpatchMicroPhar(); - } - } - - /** - * Build fpm sapi - */ - protected function buildFpm(): void - { - $vars = SystemUtil::makeEnvVarString([ - 'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a", // link resolv library (macOS needs it) - ]); - - $shell = shell()->cd(SOURCE_PATH . '/php-src'); - $shell->exec("make -j{$this->concurrency} {$vars} fpm"); - if (!$this->getOption('no-strip', false)) { - $shell->exec('strip sapi/fpm/php-fpm'); - } - $this->deploySAPIBinary(BUILD_TARGET_FPM); - } - - /** - * Build embed sapi - */ - protected function buildEmbed(): void - { - $vars = SystemUtil::makeEnvVarString([ - 'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a", // link resolv library (macOS needs it) - ]); - - shell() - ->cd(SOURCE_PATH . '/php-src') - ->exec('make INSTALL_ROOT=' . BUILD_ROOT_PATH . " -j{$this->concurrency} {$vars} install") - // Workaround for https://github.com/php/php-src/issues/12082 - ->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o') - ->exec('mkdir ' . BUILD_ROOT_PATH . '/lib/php-o') - ->cd(BUILD_ROOT_PATH . '/lib/php-o') - ->exec('ar x ' . BUILD_ROOT_PATH . '/lib/libphp.a') - ->exec('rm ' . BUILD_ROOT_PATH . '/lib/libphp.a') - ->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o') - ->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o'); - } -} diff --git a/src/SPC/builder/freebsd/SystemUtil.php b/src/SPC/builder/freebsd/SystemUtil.php deleted file mode 100644 index cbc206b9..00000000 --- a/src/SPC/builder/freebsd/SystemUtil.php +++ /dev/null @@ -1,46 +0,0 @@ -execWithResult('sysctl -n hw.ncpu'); - if ($ret !== 0) { - throw new EnvironmentException( - 'Failed to get cpu count from FreeBSD sysctl', - 'Please ensure you are running this command on a FreeBSD system and have the sysctl command available.' - ); - } - - return (int) $output[0]; - } - - /** - * Get Target Arch CFlags - * - * @param string $arch Arch Name - * @return string return Arch CFlags string - */ - public static function getArchCFlags(string $arch): string - { - return match ($arch) { - 'amd64', 'x86_64' => '--target=x86_64-unknown-freebsd', - 'arm64','aarch64' => '--target=aarch-unknown-freebsd', - default => throw new WrongUsageException('unsupported arch: ' . $arch), - }; - } -} diff --git a/src/SPC/builder/freebsd/library/BSDLibraryBase.php b/src/SPC/builder/freebsd/library/BSDLibraryBase.php deleted file mode 100644 index 6267fbbe..00000000 --- a/src/SPC/builder/freebsd/library/BSDLibraryBase.php +++ /dev/null @@ -1,27 +0,0 @@ -builder; - } -} diff --git a/src/SPC/builder/freebsd/library/bzip2.php b/src/SPC/builder/freebsd/library/bzip2.php deleted file mode 100644 index 8695adac..00000000 --- a/src/SPC/builder/freebsd/library/bzip2.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\freebsd\library; - -use SPC\builder\macos\library\MacOSLibraryBase; - -class openssl extends BSDLibraryBase -{ - public const NAME = 'openssl'; - - protected function build(): void - { - [$lib,,$destdir] = SEPARATED_PATH; - - // lib:zlib - $extra = ''; - $ex_lib = ''; - $zlib = $this->builder->getLib('zlib'); - if ($zlib instanceof MacOSLibraryBase) { - $extra = 'zlib'; - $ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib); - } - - shell()->cd($this->source_dir)->initializeEnv($this) - ->exec( - "./Configure no-shared {$extra} " . - '--prefix=/ ' . // use prefix=/ - "--libdir={$lib} " . - '--openssldir=/etc/ssl ' . - 'BSD-' . arch2gnu($this->builder->getOption('arch')) - ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"") - ->exec("make install_sw DESTDIR={$destdir}"); - $this->patchPkgconfPrefix(['libssl.pc', 'openssl.pc', 'libcrypto.pc']); - } -} diff --git a/src/SPC/builder/freebsd/library/pkgconfig.php b/src/SPC/builder/freebsd/library/pkgconfig.php deleted file mode 100644 index 62bd8ace..00000000 --- a/src/SPC/builder/freebsd/library/pkgconfig.php +++ /dev/null @@ -1,15 +0,0 @@ -options = $options; - - GlobalEnvManager::init(); - GlobalEnvManager::afterInit(); - - // concurrency - $this->concurrency = (int) getenv('SPC_CONCURRENCY'); - // cflags - $this->arch_c_flags = getenv('SPC_DEFAULT_C_FLAGS'); - $this->arch_cxx_flags = getenv('SPC_DEFAULT_CXX_FLAGS'); - $this->arch_ld_flags = getenv('SPC_DEFAULT_LD_FLAGS'); - - // create pkgconfig and include dir (some libs cannot create them automatically) - f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true); - f_mkdir(BUILD_INCLUDE_PATH, recursive: true); - } - - /** - * Build PHP from source. - * - * @param int $build_target Build target, use `BUILD_TARGET_*` constants - */ - public function buildPHP(int $build_target = BUILD_TARGET_NONE): void - { - $cflags = $this->arch_c_flags; - f_putenv('CFLAGS=' . $cflags); - - $this->emitPatchPoint('before-php-buildconf'); - SourcePatcher::patchBeforeBuildconf($this); - - shell()->cd(SOURCE_PATH . '/php-src')->exec(getenv('SPC_CMD_PREFIX_PHP_BUILDCONF')); - - $this->emitPatchPoint('before-php-configure'); - SourcePatcher::patchBeforeConfigure($this); - - $phpVersionID = $this->getPHPVersionID(); - $json_74 = $phpVersionID < 80000 ? '--enable-json ' : ''; - - $opcache_jit = !$this->getOption('disable-opcache-jit', false); - if ($opcache_jit && ($phpVersionID >= 80500 || $this->getExt('opcache'))) { - // php 8.5 contains opcache extension by default, - // if opcache_jit is enabled for 8.5 or opcache enabled, - // we need to disable undefined behavior sanitizer. - f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined'); - } - - if ($this->getOption('enable-zts', false)) { - $maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : ''; - $zts = '--enable-zts --disable-zend-signals '; - } else { - $maxExecutionTimers = ''; - $zts = ''; - } - - $config_file_path = $this->getOption('with-config-file-path', false) ? - ('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : ''; - $config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ? - ('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : ''; - - $enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI; - $enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; - $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; - $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; - $enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP; - $enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI; - - // prepare build php envs - // $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__'; - $php_configure_env = SystemUtil::makeEnvVarString([ - 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag, - 'LDFLAGS' => '-L' . BUILD_LIB_PATH, - // 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions! - ]); - - $phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: ''; - - $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; - if ($embed_type !== 'static' && SPCTarget::isStatic()) { - throw new WrongUsageException( - 'Linux does not support loading shared libraries when linking libc statically. ' . - 'Change SPC_CMD_VAR_PHP_EMBED_TYPE to static.' - ); - } - - $this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec( - $php_configure_env . ' ' . - getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . - ($enableCli ? '--enable-cli ' : '--disable-cli ') . - ($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') . - ($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') . - ($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') . - ($enableCgi ? '--enable-cgi ' : '--disable-cgi ') . - $config_file_path . - $config_file_scan_dir . - $json_74 . - $zts . - $maxExecutionTimers . - $phpvars . ' ' . - $this->makeStaticExtensionArgs() . ' ' - )); - - $this->emitPatchPoint('before-php-make'); - SourcePatcher::patchBeforeMake($this); - - $this->cleanMake(); - - if ($enableCli) { - logger()->info('building cli'); - $this->buildCli(); - } - if ($enableFpm) { - logger()->info('building fpm'); - $this->buildFpm(); - } - if ($enableCgi) { - logger()->info('building cgi'); - $this->buildCgi(); - } - if ($enableMicro) { - logger()->info('building micro'); - $this->buildMicro(); - } - if ($enableEmbed) { - logger()->info('building embed'); - if ($enableMicro) { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la'); - } - $this->buildEmbed(); - } - if ($enableFrankenphp) { - logger()->info('building frankenphp'); - $this->buildFrankenphp(); - } - $shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared')))); - if (!empty($shared_extensions)) { - if (SPCTarget::isStatic()) { - throw new WrongUsageException( - "You're building against musl libc statically (the default on Linux), but you're trying to build shared extensions.\n" . - 'Static musl libc does not implement `dlopen`, so your php binary is not able to load shared extensions.' . "\n" . - 'Either use SPC_LIBC=glibc to link against glibc on a glibc OS, use SPC_TARGET="native-native-musl -dynamic" to link against musl libc dynamically using `zig cc` or use SPC_MUSL_DYNAMIC=true on alpine.' - ); - } - logger()->info('Building shared extensions...'); - $this->buildSharedExts(); - } - } - - public function testPHP(int $build_target = BUILD_TARGET_NONE) - { - $this->emitPatchPoint('before-sanity-check'); - $this->sanityCheck($build_target); - } - - /** - * Build cli sapi - */ - protected function buildCli(): void - { - if ($this->getExt('readline') && SPCTarget::isStatic()) { - SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src'); - } - - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - shell()->cd(SOURCE_PATH . '/php-src') - ->exec('sed -i "s|//lib|/lib|g" Makefile') - ->exec("make {$concurrency} {$vars} cli"); - - if ($this->getExt('readline') && SPCTarget::isStatic()) { - SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src', true); - } - - $this->deploySAPIBinary(BUILD_TARGET_CLI); - } - - protected function buildCgi(): void - { - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - shell()->cd(SOURCE_PATH . '/php-src') - ->exec('sed -i "s|//lib|/lib|g" Makefile') - ->exec("make {$concurrency} {$vars} cgi"); - - $this->deploySAPIBinary(BUILD_TARGET_CGI); - } - - /** - * Build phpmicro sapi - */ - protected function buildMicro(): void - { - if ($this->getPHPVersionID() < 80000) { - throw new WrongUsageException('phpmicro only support PHP >= 8.0!'); - } - try { - if ($this->getExt('phar')) { - $this->phar_patched = true; - SourcePatcher::patchMicroPhar($this->getPHPVersionID()); - } - - $enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : ''; - $vars = $this->getMakeExtraVars(); - - // patch fake cli for micro - $vars['EXTRA_CFLAGS'] .= $enable_fake_cli; - $vars = SystemUtil::makeEnvVarString($vars); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - - shell()->cd(SOURCE_PATH . '/php-src') - ->exec('sed -i "s|//lib|/lib|g" Makefile') - ->exec("make {$concurrency} {$vars} micro"); - - // deploy micro.sfx - $dst = $this->deploySAPIBinary(BUILD_TARGET_MICRO); - - // patch after UPX-ed micro.sfx - $this->processUpxedMicroSfx($dst); - } finally { - if ($this->phar_patched) { - SourcePatcher::unpatchMicroPhar(); - } - } - } - - /** - * Build fpm sapi - */ - protected function buildFpm(): void - { - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - shell()->cd(SOURCE_PATH . '/php-src') - ->exec('sed -i "s|//lib|/lib|g" Makefile') - ->exec("make {$concurrency} {$vars} fpm"); - - $this->deploySAPIBinary(BUILD_TARGET_FPM); - } - - /** - * Build embed sapi - */ - protected function buildEmbed(): void - { - $sharedExts = array_filter($this->exts, static fn ($ext) => $ext->isBuildShared()); - $sharedExts = array_filter($sharedExts, static function ($ext) { - return Config::getExt($ext->getName(), 'build-with-php') === true; - }); - $install_modules = $sharedExts ? 'install-modules' : ''; - - // detect changes in module path - $diff = new DirDiff(BUILD_MODULES_PATH, true); - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - shell()->cd(SOURCE_PATH . '/php-src') - ->exec('sed -i "s|//lib|/lib|g" Makefile') - ->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile') - ->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs"); - - // process libphp.so for shared embed - $libphpSo = BUILD_LIB_PATH . '/libphp.so'; - $libphpSoDest = BUILD_LIB_PATH . '/libphp.so'; - if (file_exists($libphpSo)) { - // deploy libphp.so - 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 - $increment_files = $diff->getChangedFiles(); - foreach ($increment_files as $increment_file) { - $this->deployBinary($increment_file, $increment_file, false); - } - - // process libphp.a for static embed - if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') { - $AR = getenv('AR') ?: 'ar'; - f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a'); - // export dynamic symbols - SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a'); - } - - // patch embed php scripts - $this->patchPhpScripts(); - } - - /** - * Return extra variables for php make command. - */ - private function getMakeExtraVars(): array - { - $config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); - $static = SPCTarget::isStatic() ? '-all-static' : ''; - $lib = BUILD_LIB_PATH; - return array_filter([ - 'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'EXTRA_LIBS' => $config['libs'], - 'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), - 'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie", - ]); - } - - /** - * Patch micro.sfx after UPX compression. - * micro needs special section handling in LinuxBuilder. - * The micro.sfx does not support UPX directly, but we can remove UPX - * info segment to adapt. - * This will also make micro.sfx with upx-packed more like a malware fore antivirus - */ - private function processUpxedMicroSfx(string $dst): void - { - if ($this->getOption('with-upx-pack') && version_compare($this->getMicroVersion(), '0.2.0') >= 0) { - // strip first - // cut binary with readelf - [$ret, $out] = shell()->execWithResult("readelf -l {$dst} | awk '/LOAD|GNU_STACK/ {getline; print \$1, \$2, \$3, \$4, \$6, \$7}'"); - $out[1] = explode(' ', $out[1]); - $offset = $out[1][0]; - if ($ret !== 0 || !str_starts_with($offset, '0x')) { - throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output'); - } - $offset = hexdec($offset); - // remove upx extra wastes - file_put_contents($dst, substr(file_get_contents($dst), 0, $offset)); - } - } -} diff --git a/src/SPC/builder/linux/SystemUtil.php b/src/SPC/builder/linux/SystemUtil.php deleted file mode 100644 index 30b36b88..00000000 --- a/src/SPC/builder/linux/SystemUtil.php +++ /dev/null @@ -1,198 +0,0 @@ - 'unknown', - 'ver' => '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]; - } - } - 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('/^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'; - } - break; - } - return $ret; - } - - public static function isMuslDist(): bool - { - return static::getOSRelease()['dist'] === 'alpine'; - } - - public static function getCpuCount(): int - { - $ncpu = 1; - - if (is_file('/proc/cpuinfo')) { - $cpuinfo = file_get_contents('/proc/cpuinfo'); - preg_match_all('/^processor/m', $cpuinfo, $matches); - $ncpu = count($matches[0]); - } - - return $ncpu; - } - - public static function findStaticLib(string $name): ?array - { - $paths = getenv('LIBPATH'); - if (!$paths) { - $paths = '/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:'; - } - foreach (explode(':', $paths) as $path) { - if (file_exists("{$path}/{$name}")) { - return ["{$path}", "{$name}"]; - } - } - return null; - } - - /** @noinspection PhpUnused */ - public static function findStaticLibs(array $names): ?array - { - $ret = []; - foreach ($names as $name) { - $path = static::findStaticLib($name); - if (!$path) { - logger()->warning("static library {$name} not found"); - return null; - } - $ret[] = $path; - } - return $ret; - } - - public static function findHeader(string $name): ?array - { - $paths = getenv('INCLUDEPATH'); - if (!$paths) { - $paths = '/include:/usr/include:/usr/local/include'; - } - foreach (explode(':', $paths) as $path) { - if (file_exists("{$path}/{$name}") || is_dir("{$path}/{$name}")) { - return ["{$path}", "{$name}"]; - } - } - return null; - } - - /** @noinspection PhpUnused */ - public static function findHeaders(array $names): ?array - { - $ret = []; - foreach ($names as $name) { - $path = static::findHeader($name); - if (!$path) { - logger()->warning("header {$name} not found"); - return null; - } - $ret[] = $path; - } - return $ret; - } - - /** - * Get fully-supported linux distros. - * - * @return string[] List of supported Linux distro name for doctor - */ - public static function getSupportedDistros(): array - { - return [ - // debian-like - 'debian', 'ubuntu', 'Deepin', 'neon', - // rhel-like - 'redhat', - // centos - 'centos', - // alpine - 'alpine', - // arch - 'arch', 'manjaro', - ]; - } - - /** - * Get libc version string from ldd - */ - public static function getLibcVersionIfExists(?string $libc = null): ?string - { - if (self::$libc_version !== null) { - return self::$libc_version; - } - if ($libc === 'glibc') { - $result = shell()->execWithResult('ldd --version', false); - if ($result[0] !== 0) { - return null; - } - // get first line - $first_line = $result[1][0]; - // match ldd version: "ldd (some useless text) 2.17" match 2.17 - $pattern = '/ldd\s+\(.*?\)\s+(\d+\.\d+)/'; - if (preg_match($pattern, $first_line, $matches)) { - self::$libc_version = $matches[1]; - return self::$libc_version; - } - return null; - } - if ($libc === 'musl') { - if (self::isMuslDist()) { - $result = shell()->execWithResult('ldd 2>&1', false); - } elseif (is_file('/usr/local/musl/lib/libc.so')) { - $result = shell()->execWithResult('/usr/local/musl/lib/libc.so 2>&1', false); - } else { - $arch = php_uname('m'); - $result = shell()->execWithResult("/lib/ld-musl-{$arch}.so.1 2>&1", false); - } - // Match Version * line - // match ldd version: "Version 1.2.3" match 1.2.3 - $pattern = '/Version\s+(\d+\.\d+\.\d+)/'; - if (preg_match($pattern, $result[1][1] ?? '', $matches)) { - self::$libc_version = $matches[1]; - return self::$libc_version; - } - } - return null; - } -} diff --git a/src/SPC/builder/linux/library/LinuxLibraryBase.php b/src/SPC/builder/linux/library/LinuxLibraryBase.php deleted file mode 100644 index 2a496590..00000000 --- a/src/SPC/builder/linux/library/LinuxLibraryBase.php +++ /dev/null @@ -1,36 +0,0 @@ - true,代表依赖 curl 但可选 - */ - protected array $dep_names; - - public function __construct(protected LinuxBuilder $builder) - { - parent::__construct(); - } - - public function getBuilder(): BuilderBase - { - return $this->builder; - } -} diff --git a/src/SPC/builder/linux/library/attr.php b/src/SPC/builder/linux/library/attr.php deleted file mode 100644 index da29d48f..00000000 --- a/src/SPC/builder/linux/library/attr.php +++ /dev/null @@ -1,12 +0,0 @@ -cd($this->source_dir . '/source')->initializeEnv($this) - ->exec( - "{$cppflags} {$cxxflags} {$ldflags} " . - './runConfigureICU Linux ' . - '--enable-static ' . - '--disable-shared ' . - '--with-data-packaging=static ' . - '--enable-release=yes ' . - '--enable-extras=no ' . - '--enable-icuio=yes ' . - '--enable-dyload=no ' . - '--enable-tools=yes ' . - '--enable-tests=no ' . - '--enable-samples=no ' . - '--prefix=' . BUILD_ROOT_PATH - ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install'); - - $this->patchPkgconfPrefix(patch_option: PKGCONF_PATCH_PREFIX); - FileSystem::removeDir(BUILD_LIB_PATH . '/icu'); - } -} diff --git a/src/SPC/builder/linux/library/idn2.php b/src/SPC/builder/linux/library/idn2.php deleted file mode 100644 index a271760d..00000000 --- a/src/SPC/builder/linux/library/idn2.php +++ /dev/null @@ -1,12 +0,0 @@ -source_dir . '/Makefile', '-DMAC_OSX_KLUDGE=1', ''); - FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', 'CC=cc', "CC={$cc}"); - /* FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', '-lcrypto -lz', '-lcrypto'); - FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', '-lcrypto', '-lcrypto -lz'); - FileSystem::replaceFileStr( - $this->source_dir . '/src/osdep/unix/ssl_unix.c', - "#include \n#include ", - "#include \n#include " - ); - // SourcePatcher::patchFile('1006_openssl1.1_autoverify.patch', $this->source_dir); - SourcePatcher::patchFile('2014_openssl1.1.1_sni.patch', $this->source_dir); */ - FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'SSLINCLUDE=/usr/include/openssl', 'SSLINCLUDE=' . BUILD_INCLUDE_PATH); - FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'SSLLIB=/usr/lib', 'SSLLIB=' . BUILD_LIB_PATH); - return true; - } - - public function patchPhpConfig(): bool - { - if (SPCTarget::getLibc() === 'glibc') { - FileSystem::replaceFileRegex(BUILD_BIN_PATH . '/php-config', '/^libs="(.*)"$/m', 'libs="$1 -lcrypt"'); - return true; - } - return false; - } - - protected function build(): void - { - if ($this->builder->getLib('openssl')) { - $ssl_options = 'SPECIALAUTHENTICATORS=ssl SSLTYPE=unix.nopwd SSLINCLUDE=' . BUILD_INCLUDE_PATH . ' SSLLIB=' . BUILD_LIB_PATH; - } else { - $ssl_options = 'SSLTYPE=none'; - } - $libcVer = SPCTarget::getLibcVersion(); - $extraLibs = $libcVer && version_compare($libcVer, '2.17', '<=') ? 'EXTRALDFLAGS="-ldl -lrt -lpthread"' : ''; - shell()->cd($this->source_dir) - ->exec('make clean') - ->exec('touch ip6') - ->exec('chmod +x tools/an') - ->exec('chmod +x tools/ua') - ->exec('chmod +x src/osdep/unix/drivers') - ->exec('chmod +x src/osdep/unix/mkauths') - ->exec("yes | make slx {$ssl_options} EXTRACFLAGS='-fPIC -fpermissive' {$extraLibs}"); - try { - shell() - ->exec("cp -rf {$this->source_dir}/c-client/c-client.a " . BUILD_LIB_PATH . '/libc-client.a') - ->exec("cp -rf {$this->source_dir}/c-client/*.c " . BUILD_LIB_PATH . '/') - ->exec("cp -rf {$this->source_dir}/c-client/*.h " . BUILD_INCLUDE_PATH . '/') - ->exec("cp -rf {$this->source_dir}/src/osdep/unix/*.h " . BUILD_INCLUDE_PATH . '/'); - } catch (\Throwable) { - // last command throws an exception, no idea why since it works - } - } -} diff --git a/src/SPC/builder/linux/library/jbig.php b/src/SPC/builder/linux/library/jbig.php deleted file mode 100644 index e47e21f4..00000000 --- a/src/SPC/builder/linux/library/jbig.php +++ /dev/null @@ -1,12 +0,0 @@ -source_dir . '/Makefile', 'LIBRARY_REL ?= lib/x86_64-linux-gnu', 'LIBRARY_REL ?= lib'); - return true; - } -} diff --git a/src/SPC/builder/linux/library/libavif.php b/src/SPC/builder/linux/library/libavif.php deleted file mode 100644 index 410d549d..00000000 --- a/src/SPC/builder/linux/library/libavif.php +++ /dev/null @@ -1,12 +0,0 @@ -configure()->make(); - - if (is_file(BUILD_ROOT_PATH . '/lib64/libffi.a')) { - copy(BUILD_ROOT_PATH . '/lib64/libffi.a', BUILD_ROOT_PATH . '/lib/libffi.a'); - unlink(BUILD_ROOT_PATH . '/lib64/libffi.a'); - } - $this->patchPkgconfPrefix(['libffi.pc']); - } -} diff --git a/src/SPC/builder/linux/library/libheif.php b/src/SPC/builder/linux/library/libheif.php deleted file mode 100644 index d2cc5163..00000000 --- a/src/SPC/builder/linux/library/libheif.php +++ /dev/null @@ -1,12 +0,0 @@ -addConfigureArgs('-DCMAKE_INSTALL_RPATH=""') - ->build(); - } -} diff --git a/src/SPC/builder/linux/library/libpng.php b/src/SPC/builder/linux/library/libpng.php deleted file mode 100644 index 30d5a7f3..00000000 --- a/src/SPC/builder/linux/library/libpng.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\linux\library; - -use SPC\util\executor\UnixAutoconfExecutor; - -class libpng extends LinuxLibraryBase -{ - public const NAME = 'libpng'; - - public function build(): void - { - UnixAutoconfExecutor::create($this) - ->exec('chmod +x ./configure') - ->exec('chmod +x ./install-sh') - ->appendEnv(['LDFLAGS' => "-L{$this->getLibDir()}"]) - ->configure( - '--enable-hardware-optimizations', - "--with-zlib-prefix={$this->getBuildRootPath()}", - match (getenv('SPC_ARCH')) { - 'x86_64' => '--enable-intel-sse', - 'aarch64' => '--enable-arm-neon', - default => '', - } - ) - ->make('libpng16.la', 'install-libLTLIBRARIES install-data-am', after_env_vars: ['DEFAULT_INCLUDES' => "-I{$this->source_dir} -I{$this->getIncludeDir()}"]); - - $this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/linux/library/librabbitmq.php b/src/SPC/builder/linux/library/librabbitmq.php deleted file mode 100644 index 657aece8..00000000 --- a/src/SPC/builder/linux/library/librabbitmq.php +++ /dev/null @@ -1,12 +0,0 @@ -source_dir . '/configure', 'realpath -s', 'realpath'); - return true; - } - return false; - } - - protected function build(): void - { - $use_libc = ToolchainManager::getToolchainClass() !== GccNativeToolchain::class || version_compare(SPCTarget::getLibcVersion(), '2.30', '>='); - $make = UnixAutoconfExecutor::create($this); - - if ($use_libc) { - $make->appendEnv([ - 'CFLAGS' => '-D_GNU_SOURCE', - ]); - } - - $make - ->removeConfigureArgs( - '--disable-shared', - '--enable-static', - '--with-pic', - '--enable-pic', - ) - ->addConfigureArgs( - $use_libc ? '--use-libc' : '', - ) - ->configure() - ->make('library ENABLE_SHARED=0', 'install ENABLE_SHARED=0', with_clean: false); - - $this->patchPkgconfPrefix(); - } -} diff --git a/src/SPC/builder/linux/library/libuuid.php b/src/SPC/builder/linux/library/libuuid.php deleted file mode 100644 index 85f0d215..00000000 --- a/src/SPC/builder/linux/library/libuuid.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\linux\library; - -class libwebp extends LinuxLibraryBase -{ - use \SPC\builder\unix\library\libwebp; - - public const NAME = 'libwebp'; -} diff --git a/src/SPC/builder/linux/library/libxml2.php b/src/SPC/builder/linux/library/libxml2.php deleted file mode 100644 index 102f60b7..00000000 --- a/src/SPC/builder/linux/library/libxml2.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\linux\library; - -use SPC\builder\linux\SystemUtil; -use SPC\store\FileSystem; - -class openssl extends LinuxLibraryBase -{ - use \SPC\builder\traits\openssl; - - public const NAME = 'openssl'; - - public function build(): void - { - $extra = ''; - $ex_lib = '-ldl -pthread'; - $arch = getenv('SPC_ARCH'); - - $env = "CC='" . getenv('CC') . ' -idirafter ' . BUILD_INCLUDE_PATH . - ' -idirafter /usr/include/ ' . - ' -idirafter /usr/include/' . getenv('SPC_ARCH') . '-linux-gnu/ ' . - "' "; - // lib:zlib - $zlib = $this->builder->getLib('zlib'); - if ($zlib instanceof LinuxLibraryBase) { - $extra = 'zlib'; - $ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib); - $zlib_extra = - '--with-zlib-include=' . BUILD_INCLUDE_PATH . ' ' . - '--with-zlib-lib=' . BUILD_LIB_PATH . ' '; - } else { - $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) - ->exec( - "{$env} ./Configure no-shared {$extra} " . - '--prefix=' . BUILD_ROOT_PATH . ' ' . - '--libdir=' . BUILD_LIB_PATH . ' ' . - "--openssldir={$openssl_dir} " . - "{$zlib_extra}" . - 'enable-pie ' . - 'no-legacy ' . - 'no-tests ' . - "linux-{$arch}" - ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"") - ->exec('make install_sw'); - $this->patchPkgconfPrefix(['libssl.pc', 'openssl.pc', 'libcrypto.pc']); - // patch for openssl 3.3.0+ - if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/libssl.pc'), 'prefix=')) { - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/libssl.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file); - } - if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/openssl.pc'), 'prefix=')) { - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/openssl.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file); - } - if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc'), 'prefix=')) { - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file); - } - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', '/Libs.private:.*/m', 'Requires.private: zlib'); - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/cmake/OpenSSL/OpenSSLConfig.cmake', '/set\(OPENSSL_LIBCRYPTO_DEPENDENCIES .*\)/m', 'set(OPENSSL_LIBCRYPTO_DEPENDENCIES "${OPENSSL_LIBRARY_DIR}/libz.a")'); - } -} diff --git a/src/SPC/builder/linux/library/pkgconfig.php b/src/SPC/builder/linux/library/pkgconfig.php deleted file mode 100644 index eacca36d..00000000 --- a/src/SPC/builder/linux/library/pkgconfig.php +++ /dev/null @@ -1,15 +0,0 @@ -options = $options; - - // apply global environment variables - GlobalEnvManager::init(); - GlobalEnvManager::afterInit(); - - // ---------- set necessary compile vars ---------- - // concurrency - $this->concurrency = intval(getenv('SPC_CONCURRENCY')); - // cflags - $this->arch_c_flags = getenv('SPC_DEFAULT_C_FLAGS'); - $this->arch_cxx_flags = getenv('SPC_DEFAULT_CXX_FLAGS'); - $this->arch_ld_flags = getenv('SPC_DEFAULT_LD_FLAGS'); - - // create pkgconfig and include dir (some libs cannot create them automatically) - f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true); - f_mkdir(BUILD_INCLUDE_PATH, recursive: true); - } - - /** - * Get dynamically linked macOS frameworks - * - * @param bool $asString If true, return as string - */ - public function getFrameworks(bool $asString = false): array|string - { - $libs = []; - - // reorder libs - foreach ($this->libs as $lib) { - foreach ($lib->getDependencies() as $dep) { - $libs[] = $dep; - } - $libs[] = $lib; - } - - $frameworks = []; - /** @var MacOSLibraryBase $lib */ - foreach ($libs as $lib) { - array_push($frameworks, ...$lib->getFrameworks()); - } - - foreach ($this->exts as $ext) { - array_push($frameworks, ...$ext->getFrameworks()); - } - - if ($asString) { - return implode(' ', array_map(fn ($x) => "-framework {$x}", $frameworks)); - } - return $frameworks; - } - - /** - * Just start to build statically linked php binary - * - * @param int $build_target build target - */ - public function buildPHP(int $build_target = BUILD_TARGET_NONE): void - { - $this->emitPatchPoint('before-php-buildconf'); - SourcePatcher::patchBeforeBuildconf($this); - - shell()->cd(SOURCE_PATH . '/php-src')->exec(getenv('SPC_CMD_PREFIX_PHP_BUILDCONF')); - - $this->emitPatchPoint('before-php-configure'); - SourcePatcher::patchBeforeConfigure($this); - - $phpVersionID = $this->getPHPVersionID(); - $json_74 = $phpVersionID < 80000 ? '--enable-json ' : ''; - $zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : ''; - - $config_file_path = $this->getOption('with-config-file-path', false) ? - ('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : ''; - $config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ? - ('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : ''; - - $enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI; - $enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; - $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; - $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; - $enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP; - $enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI; - - // prepare build php envs - $envs_build_php = SystemUtil::makeEnvVarString([ - 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, - 'LDFLAGS' => '-L' . BUILD_LIB_PATH, - ]); - - if ($this->getLib('postgresql')) { - shell() - ->cd(SOURCE_PATH . '/php-src') - ->exec( - 'sed -i.backup "s/ac_cv_func_explicit_bzero\" = xyes/ac_cv_func_explicit_bzero\" = x_fake_yes/" ./configure' - ); - } - - $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; - $this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec( - getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . - ($enableCli ? '--enable-cli ' : '--disable-cli ') . - ($enableFpm ? '--enable-fpm ' : '--disable-fpm ') . - ($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') . - ($enableMicro ? '--enable-micro ' : '--disable-micro ') . - ($enableCgi ? '--enable-cgi ' : '--disable-cgi ') . - $config_file_path . - $config_file_scan_dir . - $json_74 . - $zts . - $this->makeStaticExtensionArgs() . ' ' . - $envs_build_php - )); - - $this->emitPatchPoint('before-php-make'); - SourcePatcher::patchBeforeMake($this); - - $this->cleanMake(); - - if ($enableCli) { - logger()->info('building cli'); - $this->buildCli(); - } - if ($enableFpm) { - logger()->info('building fpm'); - $this->buildFpm(); - } - if ($enableCgi) { - logger()->info('building cgi'); - $this->buildCgi(); - } - if ($enableMicro) { - logger()->info('building micro'); - $this->buildMicro(); - } - if ($enableEmbed) { - logger()->info('building embed'); - if ($enableMicro) { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la'); - } - $this->buildEmbed(); - } - if ($enableFrankenphp) { - logger()->info('building frankenphp'); - $this->buildFrankenphp(); - } - $shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared')))); - if (!empty($shared_extensions)) { - logger()->info('Building shared extensions ...'); - $this->buildSharedExts(); - } - } - - public function testPHP(int $build_target = BUILD_TARGET_NONE) - { - $this->emitPatchPoint('before-sanity-check'); - $this->sanityCheck($build_target); - } - - /** - * Build cli sapi - */ - protected function buildCli(): void - { - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - - $shell = shell()->cd(SOURCE_PATH . '/php-src'); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - $shell->exec("make {$concurrency} {$vars} cli"); - $this->deploySAPIBinary(BUILD_TARGET_CLI); - } - - protected function buildCgi(): void - { - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - - $shell = shell()->cd(SOURCE_PATH . '/php-src'); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - $shell->exec("make {$concurrency} {$vars} cgi"); - $this->deploySAPIBinary(BUILD_TARGET_CGI); - } - - /** - * Build phpmicro sapi - */ - protected function buildMicro(): void - { - if ($this->getPHPVersionID() < 80000) { - throw new WrongUsageException('phpmicro only support PHP >= 8.0!'); - } - - try { - if ($this->getExt('phar')) { - $this->phar_patched = true; - SourcePatcher::patchMicroPhar($this->getPHPVersionID()); - } - - $enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : ''; - $vars = $this->getMakeExtraVars(); - - // patch fake cli for micro - $vars['EXTRA_CFLAGS'] .= $enable_fake_cli; - $vars = SystemUtil::makeEnvVarString($vars); - - $shell = shell()->cd(SOURCE_PATH . '/php-src'); - // build - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - $shell->exec("make {$concurrency} {$vars} micro"); - - $this->deploySAPIBinary(BUILD_TARGET_MICRO); - } finally { - if ($this->phar_patched) { - SourcePatcher::unpatchMicroPhar(); - } - } - } - - /** - * Build fpm sapi - */ - protected function buildFpm(): void - { - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - - $shell = shell()->cd(SOURCE_PATH . '/php-src'); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - $shell->exec("make {$concurrency} {$vars} fpm"); - $this->deploySAPIBinary(BUILD_TARGET_FPM); - } - - /** - * Build embed sapi - */ - protected function buildEmbed(): void - { - $sharedExts = array_filter($this->exts, static fn ($ext) => $ext->isBuildShared()); - $sharedExts = array_filter($sharedExts, static function ($ext) { - return Config::getExt($ext->getName(), 'build-with-php') === true; - }); - $install_modules = $sharedExts ? 'install-modules' : ''; - $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); - $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; - - $diff = new DirDiff(BUILD_MODULES_PATH, true); - - shell()->cd(SOURCE_PATH . '/php-src') - ->exec('sed -i "" "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile') - ->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs"); - - $libphp = BUILD_LIB_PATH . '/libphp.dylib'; - if (file_exists($libphp)) { - $this->deployBinary($libphp, $libphp, false); - // macOS currently have no -release option for dylib, so we just rename it here - } - - // process shared extensions build-with-php - $increment_files = $diff->getChangedFiles(); - foreach ($increment_files as $increment_file) { - $this->deployBinary($increment_file, $increment_file, false); - } - - if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') { - $AR = getenv('AR') ?: 'ar'; - f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a'); - // export dynamic symbols - SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a'); - } - $this->patchPhpScripts(); - } - - private function getMakeExtraVars(): array - { - $config = (new SPCConfigUtil($this, ['libs_only_deps' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); - return array_filter([ - 'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'EXTRA_LDFLAGS_PROGRAM' => '-L' . BUILD_LIB_PATH, - 'EXTRA_LIBS' => $config['libs'], - ]); - } -} diff --git a/src/SPC/builder/macos/SystemUtil.php b/src/SPC/builder/macos/SystemUtil.php deleted file mode 100644 index a75a78a1..00000000 --- a/src/SPC/builder/macos/SystemUtil.php +++ /dev/null @@ -1,46 +0,0 @@ - '--target=x86_64-apple-darwin', - 'arm64','aarch64' => '--target=arm64-apple-darwin', - default => throw new WrongUsageException('unsupported arch: ' . $arch), - }; - } -} diff --git a/src/SPC/builder/macos/library/MacOSLibraryBase.php b/src/SPC/builder/macos/library/MacOSLibraryBase.php deleted file mode 100644 index 21bb4a33..00000000 --- a/src/SPC/builder/macos/library/MacOSLibraryBase.php +++ /dev/null @@ -1,33 +0,0 @@ -builder; - } - - public function getFrameworks(): array - { - return Config::getLib(static::NAME, 'frameworks', []); - } -} diff --git a/src/SPC/builder/macos/library/brotli.php b/src/SPC/builder/macos/library/brotli.php deleted file mode 100644 index 1061d913..00000000 --- a/src/SPC/builder/macos/library/brotli.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class brotli extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\brotli; - - public const NAME = 'brotli'; -} diff --git a/src/SPC/builder/macos/library/bzip2.php b/src/SPC/builder/macos/library/bzip2.php deleted file mode 100644 index 7719770c..00000000 --- a/src/SPC/builder/macos/library/bzip2.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class bzip2 extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\bzip2; - - public const NAME = 'bzip2'; -} diff --git a/src/SPC/builder/macos/library/curl.php b/src/SPC/builder/macos/library/curl.php deleted file mode 100644 index 2de97f32..00000000 --- a/src/SPC/builder/macos/library/curl.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -use SPC\store\FileSystem; - -class curl extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\curl; - - public const NAME = 'curl'; - - public function patchBeforeBuild(): bool - { - FileSystem::replaceFileRegex( - SOURCE_PATH . '/curl/CMakeLists.txt', - '/NOT COREFOUNDATION_FRAMEWORK/m', - 'FALSE' - ); - FileSystem::replaceFileRegex( - SOURCE_PATH . '/curl/CMakeLists.txt', - '/NOT SYSTEMCONFIGURATION_FRAMEWORK/m', - 'FALSE' - ); - FileSystem::replaceFileRegex( - SOURCE_PATH . '/curl/CMakeLists.txt', - '/NOT CORESERVICES_FRAMEWORK/m', - 'FALSE' - ); - return true; - } -} diff --git a/src/SPC/builder/macos/library/fastlz.php b/src/SPC/builder/macos/library/fastlz.php deleted file mode 100644 index db0f517a..00000000 --- a/src/SPC/builder/macos/library/fastlz.php +++ /dev/null @@ -1,12 +0,0 @@ -setBuildDir("{$this->source_dir}/vendor/glfw") - ->setReset(false) - ->addConfigureArgs( - '-DGLFW_BUILD_EXAMPLES=OFF', - '-DGLFW_BUILD_TESTS=OFF', - ) - ->build('.'); - // patch pkgconf - $this->patchPkgconfPrefix(['glfw3.pc']); - } -} diff --git a/src/SPC/builder/macos/library/gmp.php b/src/SPC/builder/macos/library/gmp.php deleted file mode 100644 index f75d0bbd..00000000 --- a/src/SPC/builder/macos/library/gmp.php +++ /dev/null @@ -1,15 +0,0 @@ -cd($this->source_dir . '/source') - ->exec("./runConfigureICU MacOSX --enable-static --disable-shared --disable-extras --disable-samples --disable-tests --prefix={$root}") - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install'); - - $this->patchPkgconfPrefix(patch_option: PKGCONF_PATCH_PREFIX); - FileSystem::removeDir(BUILD_LIB_PATH . '/icu'); - } -} diff --git a/src/SPC/builder/macos/library/idn2.php b/src/SPC/builder/macos/library/idn2.php deleted file mode 100644 index a41eeeb1..00000000 --- a/src/SPC/builder/macos/library/idn2.php +++ /dev/null @@ -1,12 +0,0 @@ -source_dir); - // FileSystem::replaceFileStr($this->source_dir . '/Makefile', '-DMAC_OSX_KLUDGE=1', ''); - FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', 'CC=cc', "CC={$cc}"); - /* FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', '-lcrypto -lz', '-lcrypto'); - FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', '-lcrypto', '-lcrypto -lz'); - FileSystem::replaceFileStr( - $this->source_dir . '/src/osdep/unix/ssl_unix.c', - "#include \n#include ", - "#include \n#include " - ); - // SourcePatcher::patchFile('1006_openssl1.1_autoverify.patch', $this->source_dir); - SourcePatcher::patchFile('2014_openssl1.1.1_sni.patch', $this->source_dir); */ - FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'SSLINCLUDE=/usr/include/openssl', 'SSLINCLUDE=' . BUILD_INCLUDE_PATH); - FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'SSLLIB=/usr/lib', 'SSLLIB=' . BUILD_LIB_PATH); - return true; - } - - protected function build(): void - { - if ($this->builder->getLib('openssl')) { - $ssl_options = 'SPECIALAUTHENTICATORS=ssl SSLTYPE=unix.nopwd SSLINCLUDE=' . BUILD_INCLUDE_PATH . ' SSLLIB=' . BUILD_LIB_PATH; - } else { - $ssl_options = 'SSLTYPE=none'; - } - $out = shell()->execWithResult('echo "-include $(xcrun --show-sdk-path)/usr/include/poll.h -include $(xcrun --show-sdk-path)/usr/include/time.h -include $(xcrun --show-sdk-path)/usr/include/utime.h"')[1][0]; - shell()->cd($this->source_dir) - ->exec('make clean') - ->exec('touch ip6') - ->exec('chmod +x tools/an') - ->exec('chmod +x tools/ua') - ->exec('chmod +x src/osdep/unix/drivers') - ->exec('chmod +x src/osdep/unix/mkauths') - ->exec( - "echo y | make osx {$ssl_options} EXTRACFLAGS='-Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types {$out}'" - ); - try { - shell() - ->exec("cp -rf {$this->source_dir}/c-client/c-client.a " . BUILD_LIB_PATH . '/libc-client.a') - ->exec("cp -rf {$this->source_dir}/c-client/*.c " . BUILD_LIB_PATH . '/') - ->exec("cp -rf {$this->source_dir}/c-client/*.h " . BUILD_INCLUDE_PATH . '/') - ->exec("cp -rf {$this->source_dir}/src/osdep/unix/*.h " . BUILD_INCLUDE_PATH . '/'); - } catch (\Throwable) { - // last command throws an exception, no idea why since it works - } - } -} diff --git a/src/SPC/builder/macos/library/jbig.php b/src/SPC/builder/macos/library/jbig.php deleted file mode 100644 index 10b64974..00000000 --- a/src/SPC/builder/macos/library/jbig.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class libavif extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\libavif; - - public const NAME = 'libavif'; -} diff --git a/src/SPC/builder/macos/library/libcares.php b/src/SPC/builder/macos/library/libcares.php deleted file mode 100644 index 6eb92ec0..00000000 --- a/src/SPC/builder/macos/library/libcares.php +++ /dev/null @@ -1,12 +0,0 @@ -configure( - "--host={$arch}-apple-darwin", - "--target={$arch}-apple-darwin", - ) - ->make(); - $this->patchPkgconfPrefix(['libffi.pc']); - } -} diff --git a/src/SPC/builder/macos/library/libheif.php b/src/SPC/builder/macos/library/libheif.php deleted file mode 100644 index af99740b..00000000 --- a/src/SPC/builder/macos/library/libheif.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class libiconv extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\libiconv; - - public const NAME = 'libiconv'; -} diff --git a/src/SPC/builder/macos/library/libjpeg.php b/src/SPC/builder/macos/library/libjpeg.php deleted file mode 100644 index 6b86baae..00000000 --- a/src/SPC/builder/macos/library/libjpeg.php +++ /dev/null @@ -1,12 +0,0 @@ -build(); - } -} diff --git a/src/SPC/builder/macos/library/libpng.php b/src/SPC/builder/macos/library/libpng.php deleted file mode 100644 index 91873bd4..00000000 --- a/src/SPC/builder/macos/library/libpng.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -use SPC\util\executor\UnixAutoconfExecutor; - -class libpng extends MacOSLibraryBase -{ - public const NAME = 'libpng'; - - protected function build(): void - { - $arch = arch2gnu(php_uname('m')); - UnixAutoconfExecutor::create($this) - ->exec('chmod +x ./configure') - ->exec('chmod +x ./install-sh') - ->appendEnv(['LDFLAGS' => "-L{$this->getLibDir()}"]) - ->configure( - "--host={$arch}-apple-darwin", - '--enable-hardware-optimizations', - "--with-zlib-prefix={$this->getBuildRootPath()}", - match (getenv('SPC_ARCH')) { - 'x86_64' => '--enable-intel-sse', - 'aarch64' => '--enable-arm-neon', - default => '', - } - ) - ->make('libpng16.la', 'install-libLTLIBRARIES install-data-am', after_env_vars: ['DEFAULT_INCLUDES' => "-I{$this->source_dir} -I{$this->getIncludeDir()}"]); - - shell()->cd(BUILD_LIB_PATH)->exec('ln -sf libpng16.a libpng.a'); - $this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/macos/library/librabbitmq.php b/src/SPC/builder/macos/library/librabbitmq.php deleted file mode 100644 index aba46aa5..00000000 --- a/src/SPC/builder/macos/library/librabbitmq.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class libwebp extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\libwebp; - - public const NAME = 'libwebp'; -} diff --git a/src/SPC/builder/macos/library/libxml2.php b/src/SPC/builder/macos/library/libxml2.php deleted file mode 100644 index 51fd031e..00000000 --- a/src/SPC/builder/macos/library/libxml2.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class nghttp2 extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\nghttp2; - - public const NAME = 'nghttp2'; -} diff --git a/src/SPC/builder/macos/library/nghttp3.php b/src/SPC/builder/macos/library/nghttp3.php deleted file mode 100644 index 9feebb01..00000000 --- a/src/SPC/builder/macos/library/nghttp3.php +++ /dev/null @@ -1,12 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -use SPC\store\FileSystem; - -class openssl extends MacOSLibraryBase -{ - use \SPC\builder\traits\openssl; - - public const NAME = 'openssl'; - - protected function build(): void - { - // lib:zlib - $extra = ''; - $ex_lib = ''; - $zlib = $this->builder->getLib('zlib'); - if ($zlib instanceof MacOSLibraryBase) { - $extra = 'zlib'; - $ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib); - } - $arch = getenv('SPC_ARCH'); - - shell()->cd($this->source_dir)->initializeEnv($this) - ->exec( - "./Configure no-shared {$extra} " . - '--prefix=' . BUILD_ROOT_PATH . ' ' . // use prefix=/ - '--libdir=lib ' . - '--openssldir=/etc/ssl ' . - "darwin64-{$arch}-cc" - ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"") - ->exec('make install_sw'); - $this->patchPkgconfPrefix(['libssl.pc', 'openssl.pc', 'libcrypto.pc']); - // patch for openssl 3.3.0+ - if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/libssl.pc'), 'prefix=')) { - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/libssl.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file); - } - if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/openssl.pc'), 'prefix=')) { - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/openssl.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file); - } - if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc'), 'prefix=')) { - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file); - } - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', '/Libs.private:.*/m', 'Requires.private: zlib'); - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/cmake/OpenSSL/OpenSSLConfig.cmake', '/set\(OPENSSL_LIBCRYPTO_DEPENDENCIES .*\)/m', 'set(OPENSSL_LIBCRYPTO_DEPENDENCIES "${OPENSSL_LIBRARY_DIR}/libz.a")'); - } -} diff --git a/src/SPC/builder/macos/library/pkgconfig.php b/src/SPC/builder/macos/library/pkgconfig.php deleted file mode 100644 index bb74dfaa..00000000 --- a/src/SPC/builder/macos/library/pkgconfig.php +++ /dev/null @@ -1,15 +0,0 @@ - - * - * lwmbs is licensed under Mulan PSL v2. You can use this - * software according to the terms and conditions of the - * Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - */ - -declare(strict_types=1); - -namespace SPC\builder\macos\library; - -class zlib extends MacOSLibraryBase -{ - use \SPC\builder\unix\library\zlib; - - public const NAME = 'zlib'; -} diff --git a/src/SPC/builder/macos/library/zstd.php b/src/SPC/builder/macos/library/zstd.php deleted file mode 100644 index 251d6e4f..00000000 --- a/src/SPC/builder/macos/library/zstd.php +++ /dev/null @@ -1,12 +0,0 @@ -getDependencies(recursive: true))); - $config = new SPCConfigUtil($this->builder, options: ['libs_only_deps' => true, 'absolute_libs' => true]); - $res = $config->config(libraries: array_map(fn ($x) => $x->getName(), $libs)); - return $res['libs']; - } - - /** - * Patch pkgconfig file prefix, exec_prefix, libdir, includedir for correct build. - * - * @param array $files File list to patch, if empty, will use pkg-configs from config (e.g. ['zlib.pc', 'openssl.pc']) - * @param int $patch_option Patch options - * @param null|array $custom_replace Custom replace rules, if provided, will be used to replace in the format [regex, replacement] - */ - public function patchPkgconfPrefix(array $files = [], int $patch_option = PKGCONF_PATCH_ALL, ?array $custom_replace = null): void - { - logger()->info('Patching library [' . static::NAME . '] pkgconfig'); - if ($files === [] && ($conf_pc = Config::getLib(static::NAME, 'pkg-configs', [])) !== []) { - $files = array_map(fn ($x) => "{$x}.pc", $conf_pc); - } - foreach ($files as $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/ !'); - } - logger()->debug('Patching ' . $realpath); - // replace prefix - $file = FileSystem::readFile($realpath); - $file = ($patch_option & PKGCONF_PATCH_PREFIX) === PKGCONF_PATCH_PREFIX ? preg_replace('/^prefix\s*=.*$/m', 'prefix=' . BUILD_ROOT_PATH, $file) : $file; - $file = ($patch_option & PKGCONF_PATCH_EXEC_PREFIX) === PKGCONF_PATCH_EXEC_PREFIX ? preg_replace('/^exec_prefix\s*=.*$/m', 'exec_prefix=${prefix}', $file) : $file; - $file = ($patch_option & PKGCONF_PATCH_LIBDIR) === PKGCONF_PATCH_LIBDIR ? preg_replace('/^libdir\s*=.*$/m', 'libdir=${prefix}/lib', $file) : $file; - $file = ($patch_option & PKGCONF_PATCH_INCLUDEDIR) === PKGCONF_PATCH_INCLUDEDIR ? preg_replace('/^includedir\s*=.*$/m', 'includedir=${prefix}/include', $file) : $file; - $file = ($patch_option & PKGCONF_PATCH_CUSTOM) === PKGCONF_PATCH_CUSTOM && $custom_replace !== null ? preg_replace($custom_replace[0], $custom_replace[1], $file) : $file; - FileSystem::writeFile($realpath, $file); - } - } - - public function patchLaDependencyPrefix(?array $files = null): void - { - logger()->info('Patching library [' . static::NAME . '] la files'); - $throwOnMissing = true; - if ($files === null) { - $files = $this->getStaticLibs(); - $files = array_map(fn ($name) => str_replace('.a', '.la', $name), $files); - $throwOnMissing = false; - } - foreach ($files as $name) { - $realpath = realpath(BUILD_LIB_PATH . '/' . $name); - if ($realpath === false) { - if ($throwOnMissing) { - throw new PatchException('la dependency patcher', 'Cannot find library [' . static::NAME . '] la file [' . $name . '] !'); - } - logger()->warning('Cannot find library [' . static::NAME . '] la file [' . $name . '] !'); - continue; - } - logger()->debug('Patching ' . $realpath); - // replace prefix - $file = FileSystem::readFile($realpath); - $file = str_replace( - ' /lib/', - ' ' . BUILD_LIB_PATH . '/', - $file - ); - $file = preg_replace('/^libdir=.*$/m', "libdir='" . BUILD_LIB_PATH . "'", $file); - FileSystem::writeFile($realpath, $file); - } - } - - public function getLibExtraCFlags(): string - { - $env = getenv($this->getSnakeCaseName() . '_CFLAGS') ?: ''; - if (!str_contains($env, $this->builder->arch_c_flags)) { - $env .= ' ' . $this->builder->arch_c_flags; - } - return trim($env); - } - - public function getLibExtraCXXFlags(): string - { - $env = getenv($this->getSnakeCaseName() . '_CXXFLAGS') ?: ''; - if (!str_contains($env, $this->builder->arch_cxx_flags)) { - $env .= ' ' . $this->builder->arch_cxx_flags; - } - return trim($env); - } - - public function getLibExtraLdFlags(): string - { - $env = getenv($this->getSnakeCaseName() . '_LDFLAGS') ?: ''; - if (!str_contains($env, $this->builder->arch_ld_flags)) { - $env .= ' ' . $this->builder->arch_ld_flags; - } - return trim($env); - } - - public function getLibExtraLibs(): string - { - return getenv($this->getSnakeCaseName() . '_LIBS') ?: ''; - } -} diff --git a/src/SPC/builder/traits/UnixSystemUtilTrait.php b/src/SPC/builder/traits/UnixSystemUtilTrait.php deleted file mode 100644 index 33f824f3..00000000 --- a/src/SPC/builder/traits/UnixSystemUtilTrait.php +++ /dev/null @@ -1,127 +0,0 @@ -execWithResult($cmd); - if ($result[0] !== 0) { - throw new ExecutionException($cmd, 'Failed to get defined symbols from ' . $lib_file); - } - // parse shell output and filter - $defined = []; - foreach ($result[1] as $line) { - $line = trim($line); - if ($line === '' || str_ends_with($line, '.o:') || str_ends_with($line, '.o]:')) { - continue; - } - $name = strtok($line, " \t"); - if (!$name) { - continue; - } - $name = preg_replace('/@.*$/', '', $name); - if ($name !== '' && $name !== false) { - $defined[] = $name; - } - } - $defined = array_unique($defined); - sort($defined); - // export - if (SPCTarget::getTargetOS() === 'Linux') { - file_put_contents("{$lib_file}.dynsym", "{\n" . implode("\n", array_map(fn ($x) => " {$x};", $defined)) . "};\n"); - } else { - file_put_contents("{$lib_file}.dynsym", implode("\n", $defined) . "\n"); - } - } - - /** - * Get linker flag to export dynamic symbols from a static library. - * - * @param string $lib_file Static library file path (e.g. /path/to/libxxx.a) - * @return null|string Linker flag to export dynamic symbols, null if no .dynsym file found - */ - public static function getDynamicExportedSymbols(string $lib_file): ?string - { - $symbol_file = "{$lib_file}.dynsym"; - if (!is_file($symbol_file)) { - self::exportDynamicSymbols($lib_file); - } - 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'; // needs release 0.16, can be removed then - } - // macOS/zig - if (SPCTarget::getTargetOS() !== 'Linux' || ToolchainManager::getToolchainClass() === ZigToolchain::class) { - return "-Wl,-exported_symbols_list,{$symbol_file}"; - } - return "-Wl,--dynamic-list={$symbol_file}"; - } - - /** - * Find a command in given paths or system PATH. - * If $name is an absolute path, check if it exists. - * - * @param string $name Command name or absolute path - * @param array $paths Paths to search, if empty, use system PATH - * @return null|string Absolute path of the command if found, null otherwise - */ - public static function findCommand(string $name, array $paths = []): ?string - { - if (!$paths) { - $paths = explode(PATH_SEPARATOR, getenv('PATH')); - } - if (str_starts_with($name, '/')) { - return file_exists($name) ? $name : null; - } - foreach ($paths as $path) { - if (file_exists($path . DIRECTORY_SEPARATOR . $name)) { - return $path . DIRECTORY_SEPARATOR . $name; - } - } - return null; - } - - /** - * Make environment variable string for shell command. - * - * @param array $vars Variables, like: ["CFLAGS" => "-Ixxx"] - * @return string like: CFLAGS="-Ixxx" - */ - public static function makeEnvVarString(array $vars): string - { - $str = ''; - foreach ($vars as $key => $value) { - if ($str !== '') { - $str .= ' '; - } - $str .= $key . '=' . escapeshellarg($value); - } - return $str; - } -} diff --git a/src/SPC/builder/traits/openssl.php b/src/SPC/builder/traits/openssl.php deleted file mode 100644 index 6ffef33a..00000000 --- a/src/SPC/builder/traits/openssl.php +++ /dev/null @@ -1,38 +0,0 @@ -source_dir}/VERSION.dat")) { - // parse as INI - $version = parse_ini_file("{$this->source_dir}/VERSION.dat"); - if ($version !== false) { - return "{$version['MAJOR']}.{$version['MINOR']}.{$version['PATCH']}"; - } - } - // get openssl version from pkg-config - if (PHP_OS_FAMILY !== 'Windows') { - try { - return PkgConfigUtil::getModuleVersion('openssl'); - } catch (SPCException) { - } - } - // get openssl version from header openssl/opensslv.h - if (file_exists(BUILD_INCLUDE_PATH . '/openssl/opensslv.h')) { - if (preg_match('/OPENSSL_VERSION_STR "(.*)"/', FileSystem::readFile(BUILD_INCLUDE_PATH . '/openssl/opensslv.h'), $match)) { - return $match[1]; - } - } - return null; - } -} diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php deleted file mode 100644 index fd16656c..00000000 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ /dev/null @@ -1,488 +0,0 @@ -isLibsOnly()) { - $libraries = array_keys($support_lib_list); - $sorted_libraries = DependencyUtil::getLibs($libraries); - } - - // add lib object for builder - foreach ($sorted_libraries as $library) { - if (!in_array(Config::getLib($library, 'type', 'lib'), ['lib', 'package'])) { - continue; - } - // if some libs are not supported (but in config "lib.json", throw exception) - if (!isset($support_lib_list[$library])) { - $os = match (PHP_OS_FAMILY) { - 'Linux' => 'Linux', - 'Darwin' => 'macOS', - 'Windows' => 'Windows', - 'BSD' => 'FreeBSD', - default => PHP_OS_FAMILY, - }; - throw new WrongUsageException("library [{$library}] is in the lib.json list but not supported to build on {$os}."); - } - $lib = new ($support_lib_list[$library])($this); - $this->addLib($lib); - } - - // calculate and check dependencies - foreach ($this->libs as $lib) { - $lib->calcDependency(); - } - $this->lib_list = $sorted_libraries; - } - - /** - * Strip unneeded symbols from binary file. - */ - public function stripBinary(string $binary_path): void - { - shell()->exec(match (PHP_OS_FAMILY) { - 'Darwin' => "strip -S {$binary_path}", - 'Linux' => "strip --strip-unneeded {$binary_path}", - default => throw new SPCInternalException('stripBinary is only supported on Linux and macOS'), - }); - } - - /** - * Extract debug information from binary file. - * - * @param string $binary_path the path to the binary file, including executables, shared libraries, etc - */ - public function extractDebugInfo(string $binary_path): string - { - $target_dir = BUILD_ROOT_PATH . '/debug'; - FileSystem::createDir($target_dir); - $basename = basename($binary_path); - $debug_file = "{$target_dir}/{$basename}" . (PHP_OS_FAMILY === 'Darwin' ? '.dwarf' : '.debug'); - if (PHP_OS_FAMILY === 'Darwin') { - shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}"); - } elseif (PHP_OS_FAMILY === 'Linux') { - if ($eu_strip = SystemUtil::findCommand('eu-strip')) { - shell() - ->exec("{$eu_strip} -f {$debug_file} {$binary_path}") - ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); - } else { - shell() - ->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}") - ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); - } - } else { - throw new SPCInternalException('extractDebugInfo is only supported on Linux and macOS'); - } - return $debug_file; - } - - /** - * Deploy the binary file from src to dst. - */ - public function deployBinary(string $src, string $dst, bool $executable = true): string - { - logger()->debug('Deploying binary from ' . $src . ' to ' . $dst); - - // file must exists - if (!file_exists($src)) { - throw new SPCInternalException("Deploy failed. Cannot find file: {$src}"); - } - // dst dir must exists - FileSystem::createDir(dirname($dst)); - - // ignore copy to self - if (realpath($src) !== realpath($dst)) { - shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg($dst)); - } - - // file exist - if (!file_exists($dst)) { - throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}"); - } - - if (!$this->getOption('no-strip')) { - // extract debug info - $this->extractDebugInfo($dst); - // extra strip - $this->stripBinary($dst); - } - - // UPX for linux - $upx_option = $this->getOption('with-upx-pack'); - if ($upx_option && PHP_OS_FAMILY === 'Linux' && $executable) { - if ($this->getOption('no-strip')) { - logger()->warning('UPX compression is not recommended when --no-strip is enabled.'); - } - logger()->info("Compressing {$dst} with UPX"); - shell()->exec(getenv('UPX_EXEC') . " --best {$dst}"); - } - - return $dst; - } - - /** - * Sanity check after build complete. - */ - protected function sanityCheck(int $build_target): void - { - // sanity check for php-cli - if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { - logger()->info('running cli sanity check'); - [$ret, $output] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -r "echo \"hello\";"'); - $raw_output = implode('', $output); - if ($ret !== 0 || trim($raw_output) !== 'hello') { - throw new ValidationException("cli failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cli sanity check'); - } - - foreach ($this->getExts() as $ext) { - logger()->debug('testing ext: ' . $ext->getName()); - $ext->runCliCheckUnix(); - } - } - - // sanity check for phpmicro - if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) { - $test_task = $this->getMicroTestTasks(); - foreach ($test_task as $task_name => $task) { - $test_file = SOURCE_PATH . '/' . $task_name . '.exe'; - if (file_exists($test_file)) { - @unlink($test_file); - } - file_put_contents($test_file, file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx') . $task['content']); - chmod($test_file, 0755); - [$ret, $out] = shell()->execWithResult($test_file); - foreach ($task['conditions'] as $condition => $closure) { - if (!$closure($ret, $out)) { - $raw_out = trim(implode('', $out)); - throw new ValidationException( - "failure info: {$condition}, code: {$ret}, output: {$raw_out}", - validation_module: "phpmicro sanity check item [{$task_name}]" - ); - } - } - } - } - - // sanity check for php-cgi - if (($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) { - logger()->info('running cgi sanity check'); - [$ret, $output] = shell()->execWithResult("echo 'Hello, World!\";' | " . BUILD_BIN_PATH . '/php-cgi -n'); - $raw_output = implode('', $output); - if ($ret !== 0 || !str_contains($raw_output, 'Hello, World!') || !str_contains($raw_output, 'text/html')) { - throw new ValidationException("cgi failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cgi sanity check'); - } - } - - // sanity check for embed - if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) { - logger()->info('running embed sanity check'); - $sample_file_path = SOURCE_PATH . '/embed-test'; - if (!is_dir($sample_file_path)) { - @mkdir($sample_file_path); - } - // copy embed test files - copy(ROOT_DIR . '/src/globals/common-tests/embed.c', $sample_file_path . '/embed.c'); - copy(ROOT_DIR . '/src/globals/common-tests/embed.php', $sample_file_path . '/embed.php'); - $util = new SPCConfigUtil($this); - $config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); - $lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}"; - if (SPCTarget::isStatic()) { - $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 { - $ext_path = 'LD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$LD_LIBRARY_PATH '; - } - FileSystem::removeFileIfExists(BUILD_LIB_PATH . '/libphp.a'); - } else { - $ext_path = ''; - $suffix = PHP_OS_FAMILY === 'Darwin' ? 'dylib' : 'so'; - foreach (glob(BUILD_LIB_PATH . "/libphp*.{$suffix}") as $file) { - unlink($file); - } - // calling linux system util in other unix OS is okay - if ($dynamic_exports = LinuxSystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a')) { - $dynamic_exports = ' ' . $dynamic_exports; - } - } - $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 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 to run. Error message: ' . implode("\n", $output), - validation_module: $embedType . ' libphp embed run sanity check' - ); - } - } - - // sanity check for frankenphp - if (($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) { - logger()->info('running frankenphp sanity check'); - $frankenphp = BUILD_BIN_PATH . '/frankenphp'; - if (!file_exists($frankenphp)) { - throw new ValidationException( - "FrankenPHP binary not found: {$frankenphp}", - validation_module: 'FrankenPHP sanity check' - ); - } - $prefix = PHP_OS_FAMILY === 'Darwin' ? 'DYLD_' : 'LD_'; - [$ret, $output] = shell() - ->setEnv(["{$prefix}LIBRARY_PATH" => BUILD_LIB_PATH]) - ->execWithResult("{$frankenphp} version"); - if ($ret !== 0 || !str_contains(implode('', $output), 'FrankenPHP')) { - throw new ValidationException( - 'FrankenPHP failed sanity check: ret[' . $ret . ']. out[' . implode('', $output) . ']', - validation_module: 'FrankenPHP sanity check' - ); - } - } - } - - /** - * Deploy binaries that produces executable SAPI - */ - protected function deploySAPIBinary(int $type): string - { - $src = match ($type) { - BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php', - BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', - BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm', - BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi', - BUILD_TARGET_FRANKENPHP => BUILD_BIN_PATH . '/frankenphp', - default => throw new SPCInternalException("Deployment does not accept type {$type}"), - }; - $dst = BUILD_BIN_PATH . '/' . basename($src); - return $this->deployBinary($src, $dst); - } - - /** - * Run php clean - */ - protected function cleanMake(): void - { - logger()->info('cleaning up php-src build files'); - shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean'); - } - - /** - * Patch phpize and php-config if needed - */ - protected function patchPhpScripts(): void - { - // patch phpize - if (file_exists(BUILD_BIN_PATH . '/phpize')) { - logger()->debug('Patching phpize prefix'); - FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'"); - FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#'); - } - // patch php-config - if (file_exists(BUILD_BIN_PATH . '/php-config')) { - logger()->debug('Patching php-config prefix and libs order'); - $php_config_str = FileSystem::readFile(BUILD_BIN_PATH . '/php-config'); - $php_config_str = str_replace('prefix=""', 'prefix="' . BUILD_ROOT_PATH . '"', $php_config_str); - // move mimalloc to the beginning of libs - $php_config_str = preg_replace('/(libs=")(.*?)\s*(' . preg_quote(BUILD_LIB_PATH, '/') . '\/mimalloc\.o)\s*(.*?)"/', '$1$3 $2 $4"', $php_config_str); - // move lstdc++ to the end of libs - $php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str); - FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str); - } - foreach ($this->getLibs() as $lib) { - if ($lib->patchPhpConfig()) { - logger()->debug("Library {$lib->getName()} patched php-config"); - } - } - } - - /** - * Process the --with-frankenphp-app option - * Creates app.tar and app.checksum in source/frankenphp directory - */ - protected function processFrankenphpApp(): void - { - $frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; - if (!is_dir($frankenphpSourceDir)) { - SourceManager::initSource(['frankenphp'], ['frankenphp']); - } - $frankenphpAppPath = $this->getOption('with-frankenphp-app'); - - if ($frankenphpAppPath) { - $frankenphpAppPath = trim($frankenphpAppPath, "\"'"); - if (!is_dir($frankenphpAppPath)) { - throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}"); - } - $appTarPath = $frankenphpSourceDir . '/app.tar'; - logger()->info("Creating app.tar from {$frankenphpAppPath}"); - - shell()->exec('tar -cf ' . escapeshellarg($appTarPath) . ' -C ' . escapeshellarg($frankenphpAppPath) . ' .'); - - $checksum = hash_file('md5', $appTarPath); - file_put_contents($frankenphpSourceDir . '/app_checksum.txt', $checksum); - } else { - FileSystem::removeFileIfExists($frankenphpSourceDir . '/app.tar'); - FileSystem::removeFileIfExists($frankenphpSourceDir . '/app_checksum.txt'); - file_put_contents($frankenphpSourceDir . '/app.tar', ''); - file_put_contents($frankenphpSourceDir . '/app_checksum.txt', ''); - } - } - - protected function getFrankenPHPVersion(): string - { - if ($version = getenv('FRANKENPHP_VERSION')) { - return $version; - } - $frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; - $goModPath = $frankenphpSourceDir . '/caddy/go.mod'; - - if (!file_exists($goModPath)) { - throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?"); - } - - $content = file_get_contents($goModPath); - if (preg_match('/github\.com\/dunglas\/frankenphp\s+v?(\d+\.\d+\.\d+)/', $content, $matches)) { - return $matches[1]; - } - - throw new SPCInternalException('Could not find FrankenPHP version in caddy/go.mod'); - } - - protected function buildFrankenphp(): void - { - GlobalEnvManager::addPathIfNotExists(GoXcaddy::getPath()); - $this->processFrankenphpApp(); - $nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : ''; - $nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : ''; - $xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES'); - $frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; - - $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp\S*#', '', $xcaddyModules); - $xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " . - "--with github.com/dunglas/frankenphp/caddy={$frankenphpSourceDir}/caddy {$xcaddyModules}"; - if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) { - logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.'); - $xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules); - } - - $frankenPhpVersion = $this->getFrankenPHPVersion(); - $libphpVersion = $this->getPHPVersion(); - $dynamic_exports = ''; - if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { - $libphpVersion = preg_replace('/\.\d+$/', '', $libphpVersion); - } else { - if ($dynamicSymbolsArgument = LinuxSystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a')) { - $dynamic_exports = ' ' . $dynamicSymbolsArgument; - } - } - $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'"; - $muslTags = ''; - $staticFlags = ''; - if (SPCTarget::isStatic()) { - $extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports} {$this->arch_ld_flags}'"; - $muslTags = 'static_build,'; - $staticFlags = '-static-pie'; - } - - $config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list); - $cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -DFRANKENPHP_VERSION=' . $frankenPhpVersion; - $libs = $config['libs']; - // Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix. - if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') || - str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) && - ToolchainManager::getToolchainClass() === GccNativeToolchain::class) { - $cflags .= ' -Wno-error=missing-profile'; - $libs .= ' -lgcov'; - } - $env = [...[ - 'CGO_ENABLED' => '1', - 'CGO_CFLAGS' => clean_spaces($cflags), - 'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}", - 'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' . - '-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . - '-X \'github.com/caddyserver/caddy/v2/modules/caddyhttp.ServerHeader=FrankenPHP Caddy\' ' . - '-X \'github.com/caddyserver/caddy/v2.CustomBinaryName=frankenphp\' ' . - '-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' . - "v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " . - "-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}", - 'LD_LIBRARY_PATH' => BUILD_LIB_PATH, - ], ...GoXcaddy::getEnvironment()]; - shell()->cd(BUILD_BIN_PATH) - ->setEnv($env) - ->exec("xcaddy build --output frankenphp {$xcaddyModules}"); - - $this->deploySAPIBinary(BUILD_TARGET_FRANKENPHP); - } - - /** - * Seek php-src/config.log when building PHP, add it to exception. - */ - protected function seekPhpSrcLogFileOnException(callable $callback): void - { - try { - $callback(); - } catch (SPCException $e) { - if (file_exists(SOURCE_PATH . '/php-src/config.log')) { - $e->addExtraLogFile('php-src config.log', 'php-src.config.log'); - copy(SOURCE_PATH . '/php-src/config.log', SPC_LOGS_DIR . '/php-src.config.log'); - } - throw $e; - } - } -} diff --git a/src/SPC/builder/unix/library/attr.php b/src/SPC/builder/unix/library/attr.php deleted file mode 100644 index 67ac5feb..00000000 --- a/src/SPC/builder/unix/library/attr.php +++ /dev/null @@ -1,23 +0,0 @@ -appendEnv([ - 'CFLAGS' => '-Wno-int-conversion -Wno-implicit-function-declaration', - ]) - ->exec('libtoolize --force --copy') - ->exec('./autogen.sh || autoreconf -if') - ->configure('--disable-nls') - ->make('install-attributes_h install-data install-libattr_h install-libLTLIBRARIES install-pkgincludeHEADERS install-pkgconfDATA', with_install: false); - $this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX); - } -} diff --git a/src/SPC/builder/unix/library/brotli.php b/src/SPC/builder/unix/library/brotli.php deleted file mode 100644 index 64331a56..00000000 --- a/src/SPC/builder/unix/library/brotli.php +++ /dev/null @@ -1,33 +0,0 @@ -setBuildDir("{$this->getSourceDir()}/build-dir") - ->addConfigureArgs("-DSHARE_INSTALL_PREFIX={$this->getBuildRootPath()}") - ->build(); - - $this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']); - FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlidec.pc', 'Libs: -L${libdir} -lbrotlidec', 'Libs: -L${libdir} -lbrotlidec -lbrotlicommon'); - FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlienc.pc', 'Libs: -L${libdir} -lbrotlienc', 'Libs: -L${libdir} -lbrotlienc -lbrotlicommon'); - shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a'); - foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { - if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) { - unlink(BUILD_ROOT_PATH . '/lib/' . $filename); - } - } - - if (file_exists(BUILD_BIN_PATH . '/brotli')) { - unlink(BUILD_BIN_PATH . '/brotli'); - } - } -} diff --git a/src/SPC/builder/unix/library/bzip2.php b/src/SPC/builder/unix/library/bzip2.php deleted file mode 100644 index 32d87270..00000000 --- a/src/SPC/builder/unix/library/bzip2.php +++ /dev/null @@ -1,25 +0,0 @@ -source_dir . '/Makefile', 'CFLAGS=-Wall', 'CFLAGS=-fPIC -Wall'); - return true; - } - - protected function build(): void - { - shell()->cd($this->source_dir)->initializeEnv($this) - ->exec("make PREFIX='" . BUILD_ROOT_PATH . "' clean") - ->exec("make -j{$this->builder->concurrency} {$this->builder->getEnvString()} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a") - ->exec('cp libbz2.a ' . BUILD_LIB_PATH) - ->exec('cp bzlib.h ' . BUILD_INCLUDE_PATH); - } -} diff --git a/src/SPC/builder/unix/library/curl.php b/src/SPC/builder/unix/library/curl.php deleted file mode 100644 index caa97b8c..00000000 --- a/src/SPC/builder/unix/library/curl.php +++ /dev/null @@ -1,40 +0,0 @@ -cd($this->source_dir)->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ./CMakeLists.txt'); - - UnixCMakeExecutor::create($this) - ->optionalLib('openssl', '-DCURL_USE_OPENSSL=ON -DCURL_CA_BUNDLE=OFF -DCURL_CA_PATH=OFF -DCURL_CA_FALLBACK=ON', '-DCURL_USE_OPENSSL=OFF -DCURL_ENABLE_SSL=OFF') - ->optionalLib('brotli', ...cmake_boolean_args('CURL_BROTLI')) - ->optionalLib('libssh2', ...cmake_boolean_args('CURL_USE_LIBSSH2')) - ->optionalLib('nghttp2', ...cmake_boolean_args('USE_NGHTTP2')) - ->optionalLib('nghttp3', ...cmake_boolean_args('USE_NGHTTP3')) - ->optionalLib('ngtcp2', ...cmake_boolean_args('USE_NGTCP2')) - ->optionalLib('ldap', ...cmake_boolean_args('CURL_DISABLE_LDAP', true)) - ->optionalLib('zstd', ...cmake_boolean_args('CURL_ZSTD')) - ->optionalLib('idn2', ...cmake_boolean_args('USE_LIBIDN2')) - ->optionalLib('psl', ...cmake_boolean_args('CURL_USE_LIBPSL')) - ->optionalLib('krb5', ...cmake_boolean_args('CURL_USE_GSSAPI')) - ->optionalLib('idn2', ...cmake_boolean_args('CURL_USE_IDN2')) - ->optionalLib('libcares', '-DENABLE_ARES=ON') - ->addConfigureArgs( - '-DBUILD_CURL_EXE=OFF', - '-DBUILD_LIBCURL_DOCS=OFF', - ) - ->build(); - - // patch pkgconf - $this->patchPkgconfPrefix(['libcurl.pc']); - shell()->cd(BUILD_LIB_PATH . '/cmake/CURL/') - ->exec("sed -ie 's|\"/lib/libcurl.a\"|\"" . BUILD_LIB_PATH . "/libcurl.a\"|g' CURLTargets-release.cmake"); - } -} diff --git a/src/SPC/builder/unix/library/fastlz.php b/src/SPC/builder/unix/library/fastlz.php deleted file mode 100644 index 49466475..00000000 --- a/src/SPC/builder/unix/library/fastlz.php +++ /dev/null @@ -1,24 +0,0 @@ -cd($this->source_dir)->initializeEnv($this) - ->exec((getenv('CC') ?: 'cc') . ' -c -O3 -fPIC fastlz.c -o fastlz.o') - ->exec((getenv('AR') ?: 'ar') . ' rcs libfastlz.a fastlz.o'); - - if (!copy($this->source_dir . '/fastlz.h', BUILD_INCLUDE_PATH . '/fastlz.h')) { - throw new BuildFailureException('Failed to copy fastlz.h, file does not exist'); - } - if (!copy($this->source_dir . '/libfastlz.a', BUILD_LIB_PATH . '/libfastlz.a')) { - throw new BuildFailureException('Failed to copy libfastlz.a, file does not exist'); - } - } -} diff --git a/src/SPC/builder/unix/library/freetype.php b/src/SPC/builder/unix/library/freetype.php deleted file mode 100644 index 57c1ac05..00000000 --- a/src/SPC/builder/unix/library/freetype.php +++ /dev/null @@ -1,34 +0,0 @@ -optionalLib('libpng', ...cmake_boolean_args('FT_DISABLE_PNG', true)) - ->addConfigureArgs('-DFT_DISABLE_BZIP2=ON') - ->addConfigureArgs('-DFT_DISABLE_BROTLI=ON') - ->addConfigureArgs('-DFT_DISABLE_HARFBUZZ=ON'); - - // fix cmake 4.0 compatibility - if (version_compare(get_cmake_version(), '4.0.0', '>=')) { - $cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.12'); - } - - $cmake->build(); - - $this->patchPkgconfPrefix(['freetype2.pc']); - FileSystem::replaceFileStr( - BUILD_ROOT_PATH . '/lib/pkgconfig/freetype2.pc', - ' -L/lib ', - ' -L' . BUILD_ROOT_PATH . '/lib ' - ); - } -} diff --git a/src/SPC/builder/unix/library/gettext.php b/src/SPC/builder/unix/library/gettext.php deleted file mode 100644 index d383faf7..00000000 --- a/src/SPC/builder/unix/library/gettext.php +++ /dev/null @@ -1,41 +0,0 @@ -optionalLib('ncurses', "--with-libncurses-prefix={$this->getBuildRootPath()}") - ->optionalLib('libxml2', "--with-libxml2-prefix={$this->getBuildRootPath()}") - ->addConfigureArgs( - '--disable-java', - '--disable-c++', - '--disable-d', - '--disable-rpath', - '--disable-modula2', - '--disable-libasprintf', - '--with-included-libintl', - "--with-iconv-prefix={$this->getBuildRootPath()}", - ); - - // zts - if ($this->builder->getOption('enable-zts')) { - $autoconf->addConfigureArgs('--enable-threads=isoc+posix') - ->appendEnv([ - 'CFLAGS' => '-lpthread -D_REENTRANT', - 'LDFLGAS' => '-lpthread', - ]); - } else { - $autoconf->addConfigureArgs('--disable-threads'); - } - - $autoconf->configure()->make(dir: $this->getSourceDir() . '/gettext-runtime/intl'); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/gmp.php b/src/SPC/builder/unix/library/gmp.php deleted file mode 100644 index 97a88ba1..00000000 --- a/src/SPC/builder/unix/library/gmp.php +++ /dev/null @@ -1,23 +0,0 @@ -appendEnv([ - 'CFLAGS' => '-std=c17', - ]) - ->configure( - '--enable-fat' - ) - ->make(); - $this->patchPkgconfPrefix(['gmp.pc']); - } -} diff --git a/src/SPC/builder/unix/library/gmssl.php b/src/SPC/builder/unix/library/gmssl.php deleted file mode 100644 index 89fc5207..00000000 --- a/src/SPC/builder/unix/library/gmssl.php +++ /dev/null @@ -1,15 +0,0 @@ -build(); - } -} diff --git a/src/SPC/builder/unix/library/grpc.php b/src/SPC/builder/unix/library/grpc.php deleted file mode 100644 index f8fed3d9..00000000 --- a/src/SPC/builder/unix/library/grpc.php +++ /dev/null @@ -1,58 +0,0 @@ -source_dir . '/third_party/re2/util/pcre.h', - ["#define UTIL_PCRE_H_\n#include ", '#define UTIL_PCRE_H_'], - ['#define UTIL_PCRE_H_', "#define UTIL_PCRE_H_\n#include "], - ); - return true; - } - - protected function build(): void - { - $cmake = UnixCMakeExecutor::create($this) - ->setBuildDir("{$this->source_dir}/avoid_BUILD_file_conflict") - ->addConfigureArgs( - '-DgRPC_INSTALL_BINDIR=' . BUILD_BIN_PATH, - '-DgRPC_INSTALL_LIBDIR=' . BUILD_LIB_PATH, - '-DgRPC_INSTALL_SHAREDIR=' . BUILD_ROOT_PATH . '/share/grpc', - '-DCMAKE_C_FLAGS="-DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK -L' . BUILD_LIB_PATH . ' -I' . BUILD_INCLUDE_PATH . '"', - '-DCMAKE_CXX_FLAGS="-DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK -L' . BUILD_LIB_PATH . ' -I' . BUILD_INCLUDE_PATH . '"', - '-DgRPC_BUILD_CODEGEN=OFF', - '-DgRPC_DOWNLOAD_ARCHIVES=OFF', - '-DgRPC_BUILD_TESTS=OFF', - // providers - '-DgRPC_ZLIB_PROVIDER=package', - '-DgRPC_CARES_PROVIDER=package', - '-DgRPC_SSL_PROVIDER=package', - ); - - if (PHP_OS_FAMILY === 'Linux' && SPCTarget::isStatic() && !SystemUtil::isMuslDist()) { - $cmake->addConfigureArgs( - '-DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++"', - '-DCMAKE_SHARED_LINKER_FLAGS="-static-libgcc -static-libstdc++"', - '-DCMAKE_CXX_STANDARD_LIBRARIES="-static-libgcc -static-libstdc++"', - ); - } - - $cmake->build(); - - $re2Content = file_get_contents($this->source_dir . '/third_party/re2/re2.pc'); - $re2Content = 'prefix=' . BUILD_ROOT_PATH . "\nexec_prefix=\${prefix}\n" . $re2Content; - file_put_contents(BUILD_LIB_PATH . '/pkgconfig/re2.pc', $re2Content); - $this->patchPkgconfPrefix(['grpc++.pc', 'grpc.pc', 'grpc++_unsecure.pc', 'grpc_unsecure.pc', 're2.pc']); - } -} diff --git a/src/SPC/builder/unix/library/icu.php b/src/SPC/builder/unix/library/icu.php deleted file mode 100644 index 6f2e8611..00000000 --- a/src/SPC/builder/unix/library/icu.php +++ /dev/null @@ -1,24 +0,0 @@ -configure( - '--disable-nls', - '--disable-doc', - '--enable-year2038', - '--disable-rpath' - ) - ->optionalLib('libiconv', "--with-libiconv-prefix={$this->getBuildRootPath()}") - ->optionalLib('libunistring', "--with-libunistring-prefix={$this->getBuildRootPath()}") - ->optionalLib('gettext', "--with-libnintl-prefix={$this->getBuildRootPath()}") - ->make(); - $this->patchPkgconfPrefix(['libidn2.pc']); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/imagemagick.php b/src/SPC/builder/unix/library/imagemagick.php deleted file mode 100644 index 42064e2d..00000000 --- a/src/SPC/builder/unix/library/imagemagick.php +++ /dev/null @@ -1,75 +0,0 @@ -builder->arch_ld_flags; - if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) { - $this->builder->arch_ld_flags = str_replace('-Wl,--as-needed', '', $original_ldflags); - } - - $ac = UnixAutoconfExecutor::create($this) - ->optionalLib('libzip', ...ac_with_args('zip')) - ->optionalLib('libjpeg', ...ac_with_args('jpeg')) - ->optionalLib('libpng', ...ac_with_args('png')) - ->optionalLib('libwebp', ...ac_with_args('webp')) - ->optionalLib('libxml2', ...ac_with_args('xml')) - ->optionalLib('libheif', ...ac_with_args('heic')) - ->optionalLib('zlib', ...ac_with_args('zlib')) - ->optionalLib('xz', ...ac_with_args('lzma')) - ->optionalLib('zstd', ...ac_with_args('zstd')) - ->optionalLib('freetype', ...ac_with_args('freetype')) - ->optionalLib('bzip2', ...ac_with_args('bzlib')) - ->optionalLib('libjxl', ...ac_with_args('jxl')) - ->optionalLib('jbig', ...ac_with_args('jbig')) - ->addConfigureArgs( - '--disable-openmp', - '--without-x', - ); - - // special: linux-static target needs `-static` - $ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl'; - - // special: macOS needs -iconv - $libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : ''; - - $ac->appendEnv([ - 'LDFLAGS' => $ldflags, - 'LIBS' => $libs, - 'PKG_CONFIG' => '$PKG_CONFIG --static', - ]); - - $ac->configure()->make(); - - $this->builder->arch_ld_flags = $original_ldflags; - - $filelist = [ - 'ImageMagick.pc', - 'ImageMagick-7.Q16HDRI.pc', - 'Magick++.pc', - 'Magick++-7.Q16HDRI.pc', - 'MagickCore.pc', - 'MagickCore-7.Q16HDRI.pc', - 'MagickWand.pc', - 'MagickWand-7.Q16HDRI.pc', - ]; - $this->patchPkgconfPrefix($filelist); - foreach ($filelist as $file) { - FileSystem::replaceFileRegex( - BUILD_LIB_PATH . '/pkgconfig/' . $file, - '#includearchdir=/include/ImageMagick-7#m', - 'includearchdir=${prefix}/include/ImageMagick-7' - ); - } - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/jbig.php b/src/SPC/builder/unix/library/jbig.php deleted file mode 100644 index 5b00f0d6..00000000 --- a/src/SPC/builder/unix/library/jbig.php +++ /dev/null @@ -1,27 +0,0 @@ -source_dir . '/Makefile', 'CFLAGS = -O2 -W -Wno-unused-result', 'CFLAGS = -O2 -W -Wno-unused-result -fPIC'); - return true; - } - - protected function build(): void - { - shell()->cd($this->source_dir)->initializeEnv($this) - ->exec("make -j{$this->builder->concurrency} {$this->builder->getEnvString()} lib") - ->exec('cp libjbig/libjbig.a ' . BUILD_LIB_PATH) - ->exec('cp libjbig/libjbig85.a ' . BUILD_LIB_PATH) - ->exec('cp libjbig/jbig.h ' . BUILD_INCLUDE_PATH) - ->exec('cp libjbig/jbig85.h ' . BUILD_INCLUDE_PATH) - ->exec('cp libjbig/jbig_ar.h ' . BUILD_INCLUDE_PATH); - } -} diff --git a/src/SPC/builder/unix/library/krb5.php b/src/SPC/builder/unix/library/krb5.php deleted file mode 100644 index 4cf0ad44..00000000 --- a/src/SPC/builder/unix/library/krb5.php +++ /dev/null @@ -1,60 +0,0 @@ -source_dir; - $this->source_dir .= '/src'; - shell()->cd($this->source_dir)->exec('ls -lah'); - if (!file_exists($this->source_dir . '/configure')) { - shell()->cd($this->source_dir)->exec('autoreconf -if'); - } - $libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true)); - $spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]); - $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false)); - $extraEnv = [ - 'CFLAGS' => '-fcommon', - 'LIBS' => $config['libs'], - ]; - if (getenv('SPC_LD_LIBRARY_PATH') && getenv('SPC_LIBRARY_PATH')) { - $extraEnv = [...$extraEnv, ...[ - 'LD_LIBRARY_PATH' => getenv('SPC_LD_LIBRARY_PATH'), - 'LIBRARY_PATH' => getenv('SPC_LIBRARY_PATH'), - ]]; - } - $args = [ - '--disable-nls', - '--disable-rpath', - '--without-system-verto', - ]; - if (PHP_OS_FAMILY === 'Darwin') { - $extraEnv['LDFLAGS'] = '-framework Kerberos'; - $args[] = 'ac_cv_func_secure_getenv=no'; - } - UnixAutoconfExecutor::create($this) - ->appendEnv($extraEnv) - ->optionalLib('ldap', '--with-ldap', '--without-ldap') - ->optionalLib('libedit', '--with-libedit', '--without-libedit') - ->configure(...$args) - ->make(); - $this->patchPkgconfPrefix([ - 'krb5-gssapi.pc', - 'krb5.pc', - 'kadm-server.pc', - 'kadm-client.pc', - 'kdb.pc', - 'mit-krb5-gssapi.pc', - 'mit-krb5.pc', - 'gssrpc.pc', - ]); - $this->source_dir = $origin_source_dir; - } -} diff --git a/src/SPC/builder/unix/library/ldap.php b/src/SPC/builder/unix/library/ldap.php deleted file mode 100644 index 3ff72dcb..00000000 --- a/src/SPC/builder/unix/library/ldap.php +++ /dev/null @@ -1,45 +0,0 @@ -source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz ' . $extra); - return true; - } - - protected function build(): void - { - UnixAutoconfExecutor::create($this) - ->optionalLib('openssl', '--with-tls=openssl') - ->optionalLib('gmp', '--with-mp=gmp') - ->optionalLib('libsodium', '--with-argon2=libsodium', '--enable-argon2=no') - ->addConfigureArgs( - '--disable-slapd', - '--without-systemd', - '--without-cyrus-sasl', - 'ac_cv_func_pthread_kill_other_threads_np=no' - ) - ->appendEnv([ - 'CFLAGS' => '-Wno-date-time', - 'LDFLAGS' => "-L{$this->getLibDir()}", - 'CPPFLAGS' => "-I{$this->getIncludeDir()}", - ]) - ->configure() - ->exec('sed -i -e "s/SUBDIRS= include libraries clients servers tests doc/SUBDIRS= include libraries clients servers/g" Makefile') - ->make(); - - FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/ldap.pc', 'Libs: -L${libdir} -lldap', 'Libs: -L${libdir} -lldap -llber'); - $this->patchPkgconfPrefix(['ldap.pc', 'lber.pc']); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/lerc.php b/src/SPC/builder/unix/library/lerc.php deleted file mode 100644 index 5ad0e572..00000000 --- a/src/SPC/builder/unix/library/lerc.php +++ /dev/null @@ -1,16 +0,0 @@ -build(); - } -} diff --git a/src/SPC/builder/unix/library/libacl.php b/src/SPC/builder/unix/library/libacl.php deleted file mode 100644 index 8c5d699d..00000000 --- a/src/SPC/builder/unix/library/libacl.php +++ /dev/null @@ -1,32 +0,0 @@ -exec('libtoolize --force --copy') - ->exec('./autogen.sh || autoreconf -if') - ->configure('--disable-nls', '--disable-tests') - ->make('install-acl_h install-libacl_h install-data install-libLTLIBRARIES install-pkgincludeHEADERS install-sysincludeHEADERS install-pkgconfDATA', with_install: false); - $this->patchPkgconfPrefix(['libacl.pc'], PKGCONF_PATCH_PREFIX); - } -} diff --git a/src/SPC/builder/unix/library/libaom.php b/src/SPC/builder/unix/library/libaom.php deleted file mode 100644 index f2f50d85..00000000 --- a/src/SPC/builder/unix/library/libaom.php +++ /dev/null @@ -1,27 +0,0 @@ -setBuildDir("{$this->source_dir}/builddir") - ->addConfigureArgs('-DAOM_TARGET_CPU=generic') - ->build(); - f_putenv("SPC_COMPILER_EXTRA={$extra}"); - $this->patchPkgconfPrefix(['aom.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libargon2.php b/src/SPC/builder/unix/library/libargon2.php deleted file mode 100644 index 4c760095..00000000 --- a/src/SPC/builder/unix/library/libargon2.php +++ /dev/null @@ -1,30 +0,0 @@ -cd($this->source_dir)->initializeEnv($this) - ->exec("make PREFIX='' clean") - ->exec("make -j{$this->builder->concurrency} PREFIX=''") - ->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); - - $this->patchPkgconfPrefix(['libargon2.pc']); - - foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { - if (str_starts_with($filename, 'libargon2') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) { - unlink(BUILD_ROOT_PATH . '/lib/' . $filename); - } - } - - if (file_exists(BUILD_BIN_PATH . '/argon2')) { - unlink(BUILD_BIN_PATH . '/argon2'); - } - } -} diff --git a/src/SPC/builder/unix/library/libavif.php b/src/SPC/builder/unix/library/libavif.php deleted file mode 100644 index a5b57aef..00000000 --- a/src/SPC/builder/unix/library/libavif.php +++ /dev/null @@ -1,24 +0,0 @@ -optionalLib('libaom', '-DAVIF_CODEC_AOM=SYSTEM', '-DAVIF_CODEC_AOM=OFF') - ->optionalLib('libsharpyuv', '-DAVIF_LIBSHARPYUV=SYSTEM', '-DAVIF_LIBSHARPYUV=OFF') - ->optionalLib('libjpeg', '-DAVIF_JPEG=SYSTEM', '-DAVIF_JPEG=OFF') - ->optionalLib('libxml2', '-DAVIF_LIBXML2=SYSTEM', '-DAVIF_LIBXML2=OFF') - ->optionalLib('libpng', '-DAVIF_LIBPNG=SYSTEM', '-DAVIF_LIBPNG=OFF') - ->addConfigureArgs('-DAVIF_LIBYUV=OFF') - ->build(); - // patch pkgconfig - $this->patchPkgconfPrefix(['libavif.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libcares.php b/src/SPC/builder/unix/library/libcares.php deleted file mode 100644 index 90fd9d76..00000000 --- a/src/SPC/builder/unix/library/libcares.php +++ /dev/null @@ -1,27 +0,0 @@ -source_dir . '/src/lib/thirdparty/apple/dnsinfo.h')) { - FileSystem::createDir($this->source_dir . '/src/lib/thirdparty/apple'); - copy(ROOT_DIR . '/src/globals/extra/libcares_dnsinfo.h', $this->source_dir . '/src/lib/thirdparty/apple/dnsinfo.h'); - return true; - } - return false; - } - - protected function build(): void - { - UnixAutoconfExecutor::create($this)->configure('--disable-tests')->make(); - $this->patchPkgconfPrefix(['libcares.pc'], PKGCONF_PATCH_PREFIX); - } -} diff --git a/src/SPC/builder/unix/library/libde265.php b/src/SPC/builder/unix/library/libde265.php deleted file mode 100644 index 184a4426..00000000 --- a/src/SPC/builder/unix/library/libde265.php +++ /dev/null @@ -1,21 +0,0 @@ -addConfigureArgs( - '-DENABLE_SDL=OFF', - '-DENABLE_DECODER=OFF' - ) - ->build(); - $this->patchPkgconfPrefix(['libde265.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libedit.php b/src/SPC/builder/unix/library/libedit.php deleted file mode 100644 index 2de9077f..00000000 --- a/src/SPC/builder/unix/library/libedit.php +++ /dev/null @@ -1,30 +0,0 @@ -source_dir . '/src/sys.h', - '|//#define\s+strl|', - '#define strl' - ); - return true; - } - - protected function build(): void - { - UnixAutoconfExecutor::create($this) - ->appendEnv(['CFLAGS' => '-D__STDC_ISO_10646__=201103L']) - ->configure() - ->make(); - $this->patchPkgconfPrefix(['libedit.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libevent.php b/src/SPC/builder/unix/library/libevent.php deleted file mode 100644 index c2474d54..00000000 --- a/src/SPC/builder/unix/library/libevent.php +++ /dev/null @@ -1,72 +0,0 @@ -addConfigureArgs( - '-DEVENT__LIBRARY_TYPE=STATIC', - '-DEVENT__DISABLE_BENCHMARK=ON', - '-DEVENT__DISABLE_THREAD_SUPPORT=ON', - '-DEVENT__DISABLE_TESTS=ON', - '-DEVENT__DISABLE_SAMPLES=ON', - '-DEVENT__DISABLE_MBEDTLS=ON ', - ); - if (version_compare(get_cmake_version(), '4.0.0', '>=')) { - $cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.10'); - } - $cmake->build(); - - $this->patchPkgconfPrefix(['libevent.pc', 'libevent_core.pc', 'libevent_extra.pc', 'libevent_openssl.pc']); - - $this->patchPkgconfPrefix( - ['libevent_openssl.pc'], - PKGCONF_PATCH_CUSTOM, - [ - '/Libs.private:.*/m', - 'Libs.private: -lssl -lcrypto', - ] - ); - } - - protected function install(): void - { - parent::install(); - FileSystem::replaceFileStr( - BUILD_LIB_PATH . '/cmake/libevent/LibeventTargets-static.cmake', - '{BUILD_ROOT_PATH}', - BUILD_ROOT_PATH - ); - } -} diff --git a/src/SPC/builder/unix/library/libheif.php b/src/SPC/builder/unix/library/libheif.php deleted file mode 100644 index 095a1f82..00000000 --- a/src/SPC/builder/unix/library/libheif.php +++ /dev/null @@ -1,39 +0,0 @@ -source_dir . '/CMakeLists.txt'), 'libbrotlienc')) { - FileSystem::replaceFileStr( - $this->source_dir . '/CMakeLists.txt', - 'list(APPEND REQUIRES_PRIVATE "libbrotlidec")', - 'list(APPEND REQUIRES_PRIVATE "libbrotlidec")' . "\n" . ' list(APPEND REQUIRES_PRIVATE "libbrotlienc")' - ); - return true; - } - return false; - } - - protected function build(): void - { - UnixCMakeExecutor::create($this) - ->addConfigureArgs( - '--preset=release', - '-DWITH_EXAMPLES=OFF', - '-DWITH_GDK_PIXBUF=OFF', - '-DBUILD_TESTING=OFF', - '-DWITH_LIBSHARPYUV=ON', // optional: libwebp - '-DENABLE_PLUGIN_LOADING=OFF', - ) - ->build(); - $this->patchPkgconfPrefix(['libheif.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libiconv.php b/src/SPC/builder/unix/library/libiconv.php deleted file mode 100644 index 5ccc9484..00000000 --- a/src/SPC/builder/unix/library/libiconv.php +++ /dev/null @@ -1,22 +0,0 @@ -configure( - '--enable-extra-encodings', - '--enable-year2038', - ) - ->make('install-lib', with_install: false) - ->make('install-lib', with_install: false, dir: $this->getSourceDir() . '/libcharset'); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/libjpeg.php b/src/SPC/builder/unix/library/libjpeg.php deleted file mode 100644 index 969fa060..00000000 --- a/src/SPC/builder/unix/library/libjpeg.php +++ /dev/null @@ -1,26 +0,0 @@ -addConfigureArgs( - '-DENABLE_STATIC=ON', - '-DENABLE_SHARED=OFF', - '-DWITH_SYSTEM_ZLIB=ON', - '-DWITH_TOOLS=OFF', - '-DWITH_TESTS=OFF', - '-DWITH_SIMD=OFF', - ) - ->build(); - // patch pkgconfig - $this->patchPkgconfPrefix(['libjpeg.pc', 'libturbojpeg.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libjxl.php b/src/SPC/builder/unix/library/libjxl.php deleted file mode 100644 index 4c922d9d..00000000 --- a/src/SPC/builder/unix/library/libjxl.php +++ /dev/null @@ -1,47 +0,0 @@ -addConfigureArgs( - '-DJPEGXL_ENABLE_TOOLS=OFF', - '-DJPEGXL_ENABLE_EXAMPLES=OFF', - '-DJPEGXL_ENABLE_MANPAGES=OFF', - '-DJPEGXL_ENABLE_BENCHMARK=OFF', - '-DJPEGXL_ENABLE_PLUGINS=OFF', - '-DJPEGXL_ENABLE_SJPEG=ON', - '-DJPEGXL_ENABLE_JNI=OFF', - '-DJPEGXL_ENABLE_TRANSCODE_JPEG=ON', - '-DJPEGXL_STATIC=' . (SPCTarget::isStatic() ? 'ON' : 'OFF'), - '-DJPEGXL_FORCE_SYSTEM_BROTLI=ON', - '-DBUILD_TESTING=OFF' - ); - - if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $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/liblz4.php b/src/SPC/builder/unix/library/liblz4.php deleted file mode 100644 index 2dc2b46f..00000000 --- a/src/SPC/builder/unix/library/liblz4.php +++ /dev/null @@ -1,37 +0,0 @@ -source_dir . '/programs/Makefile', 'install: lz4', "install: lz4\n\ninstallewfwef: lz4"); - return true; - } - - protected function build(): void - { - shell()->cd($this->source_dir)->initializeEnv($this) - ->exec("make PREFIX='' clean") - ->exec("make lib -j{$this->builder->concurrency} PREFIX=''"); - - FileSystem::replaceFileStr($this->source_dir . '/Makefile', '$(MAKE) -C $(PRGDIR) $@', ''); - - shell()->cd($this->source_dir) - ->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); - - $this->patchPkgconfPrefix(['liblz4.pc']); - - foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { - if (str_starts_with($filename, 'liblz4') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) { - unlink(BUILD_ROOT_PATH . '/lib/' . $filename); - } - } - } -} diff --git a/src/SPC/builder/unix/library/libmaxminddb.php b/src/SPC/builder/unix/library/libmaxminddb.php deleted file mode 100644 index 44915f27..00000000 --- a/src/SPC/builder/unix/library/libmaxminddb.php +++ /dev/null @@ -1,20 +0,0 @@ -addConfigureArgs( - '-DBUILD_TESTING=OFF', - '-DMAXMINDDB_BUILD_BINARIES=OFF', - ) - ->build(); - } -} diff --git a/src/SPC/builder/unix/library/librabbitmq.php b/src/SPC/builder/unix/library/librabbitmq.php deleted file mode 100644 index ca67b689..00000000 --- a/src/SPC/builder/unix/library/librabbitmq.php +++ /dev/null @@ -1,15 +0,0 @@ -addConfigureArgs('-DBUILD_STATIC_LIBS=ON')->build(); - } -} diff --git a/src/SPC/builder/unix/library/librdkafka.php b/src/SPC/builder/unix/library/librdkafka.php deleted file mode 100644 index 222760d0..00000000 --- a/src/SPC/builder/unix/library/librdkafka.php +++ /dev/null @@ -1,43 +0,0 @@ -source_dir . '/lds-gen.py', - "funcs.append('rd_ut_coverage_check')", - '' - ); - FileSystem::replaceFileStr( - $this->source_dir . '/src/rd.h', - '#error "IOV_MAX not defined"', - "#define IOV_MAX 1024\n#define __GNU__" - ); - return true; - } - - protected function build(): void - { - UnixCMakeExecutor::create($this) - ->optionalLib('zstd', ...cmake_boolean_args('WITH_ZSTD')) - ->optionalLib('curl', ...cmake_boolean_args('WITH_CURL')) - ->optionalLib('openssl', ...cmake_boolean_args('WITH_SSL')) - ->optionalLib('zlib', ...cmake_boolean_args('WITH_ZLIB')) - ->optionalLib('liblz4', ...cmake_boolean_args('ENABLE_LZ4_EXT')) - ->addConfigureArgs( - '-DWITH_SASL=OFF', - '-DRDKAFKA_BUILD_STATIC=ON', - '-DRDKAFKA_BUILD_EXAMPLES=OFF', - '-DRDKAFKA_BUILD_TESTS=OFF', - ) - ->build(); - } -} diff --git a/src/SPC/builder/unix/library/libsodium.php b/src/SPC/builder/unix/library/libsodium.php deleted file mode 100644 index 441166c9..00000000 --- a/src/SPC/builder/unix/library/libsodium.php +++ /dev/null @@ -1,16 +0,0 @@ -configure()->make(); - $this->patchPkgconfPrefix(['libsodium.pc'], PKGCONF_PATCH_PREFIX); - } -} diff --git a/src/SPC/builder/unix/library/libssh2.php b/src/SPC/builder/unix/library/libssh2.php deleted file mode 100644 index 91fed1a7..00000000 --- a/src/SPC/builder/unix/library/libssh2.php +++ /dev/null @@ -1,23 +0,0 @@ -optionalLib('zlib', ...cmake_boolean_args('ENABLE_ZLIB_COMPRESSION')) - ->addConfigureArgs( - '-DBUILD_EXAMPLES=OFF', - '-DBUILD_TESTING=OFF' - ) - ->build(); - - $this->patchPkgconfPrefix(['libssh2.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libtiff.php b/src/SPC/builder/unix/library/libtiff.php deleted file mode 100644 index ed14f426..00000000 --- a/src/SPC/builder/unix/library/libtiff.php +++ /dev/null @@ -1,44 +0,0 @@ -source_dir . '/configure', '-lwebp', '-lwebp -lsharpyuv'); - FileSystem::replaceFileStr($this->source_dir . '/configure', '-l"$lerc_lib_name"', '-l"$lerc_lib_name" ' . $libcpp); - UnixAutoconfExecutor::create($this) - ->optionalLib('lerc', '--enable-lerc', '--disable-lerc') - ->optionalLib('zstd', '--enable-zstd', '--disable-zstd') - ->optionalLib('libwebp', '--enable-webp', '--disable-webp') - ->optionalLib('xz', '--enable-lzma', '--disable-lzma') - ->optionalLib('jbig', '--enable-jbig', '--disable-jbig') - ->configure( - // zlib deps - '--enable-zlib', - "--with-zlib-include-dir={$this->getIncludeDir()}", - "--with-zlib-lib-dir={$this->getLibDir()}", - // libjpeg deps - '--enable-jpeg', - "--with-jpeg-include-dir={$this->getIncludeDir()}", - "--with-jpeg-lib-dir={$this->getLibDir()}", - '--disable-old-jpeg', - '--disable-jpeg12', - '--disable-libdeflate', - '--disable-tools', - '--disable-contrib', - '--disable-cxx', - '--without-x', - ) - ->make(); - $this->patchPkgconfPrefix(['libtiff-4.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libunistring.php b/src/SPC/builder/unix/library/libunistring.php deleted file mode 100644 index 1d410a8c..00000000 --- a/src/SPC/builder/unix/library/libunistring.php +++ /dev/null @@ -1,18 +0,0 @@ -configure('--disable-nls') - ->make(); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/libuuid.php b/src/SPC/builder/unix/library/libuuid.php deleted file mode 100644 index 2463ac78..00000000 --- a/src/SPC/builder/unix/library/libuuid.php +++ /dev/null @@ -1,34 +0,0 @@ -toStep(2)->build(); - copy($this->source_dir . '/build/libuuid.a', BUILD_LIB_PATH . '/libuuid.a'); - FileSystem::createDir(BUILD_INCLUDE_PATH . '/uuid'); - copy($this->source_dir . '/uuid.h', BUILD_INCLUDE_PATH . '/uuid/uuid.h'); - $pc = FileSystem::readFile($this->source_dir . '/uuid.pc.in'); - $pc = str_replace([ - '@prefix@', - '@exec_prefix@', - '@libdir@', - '@includedir@', - '@LIBUUID_VERSION@', - ], [ - BUILD_ROOT_PATH, - '${prefix}', - '${prefix}/lib', - '${prefix}/include', - '1.0.3', - ], $pc); - FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/uuid.pc', $pc); - } -} diff --git a/src/SPC/builder/unix/library/libuv.php b/src/SPC/builder/unix/library/libuv.php deleted file mode 100644 index 52e4c819..00000000 --- a/src/SPC/builder/unix/library/libuv.php +++ /dev/null @@ -1,19 +0,0 @@ -addConfigureArgs('-DLIBUV_BUILD_SHARED=OFF') - ->build(); - // patch pkgconfig - $this->patchPkgconfPrefix(['libuv-static.pc']); - } -} diff --git a/src/SPC/builder/unix/library/libwebp.php b/src/SPC/builder/unix/library/libwebp.php deleted file mode 100644 index 015fa73b..00000000 --- a/src/SPC/builder/unix/library/libwebp.php +++ /dev/null @@ -1,38 +0,0 @@ - -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=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); - $this->patchPkgconfPrefix(['libsharpyuv.pc'], PKGCONF_PATCH_CUSTOM, ['/^includedir=.*$/m', 'includedir=${prefix}/include/webp']); - } -} diff --git a/src/SPC/builder/unix/library/libxml2.php b/src/SPC/builder/unix/library/libxml2.php deleted file mode 100644 index 7152c0c4..00000000 --- a/src/SPC/builder/unix/library/libxml2.php +++ /dev/null @@ -1,49 +0,0 @@ -optionalLib( - 'zlib', - '-DLIBXML2_WITH_ZLIB=ON ' . - "-DZLIB_LIBRARY={$this->getLibDir()}/libz.a " . - "-DZLIB_INCLUDE_DIR={$this->getIncludeDir()}", - '-DLIBXML2_WITH_ZLIB=OFF', - ) - ->optionalLib('xz', ...cmake_boolean_args('LIBXML2_WITH_LZMA')) - ->addConfigureArgs( - '-DLIBXML2_WITH_ICONV=ON', - '-DLIBXML2_WITH_ICU=OFF', // optional, but discouraged: https://gitlab.gnome.org/GNOME/libxml2/-/blob/master/README.md - '-DLIBXML2_WITH_PYTHON=OFF', - '-DLIBXML2_WITH_PROGRAMS=OFF', - '-DLIBXML2_WITH_TESTS=OFF', - ); - - if ($this instanceof LinuxLibraryBase) { - $cmake->addConfigureArgs('-DIconv_IS_BUILT_IN=OFF'); - } - - $cmake->build(); - - FileSystem::replaceFileStr( - BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc', - '-lxml2 -liconv', - '-lxml2' - ); - FileSystem::replaceFileStr( - BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc', - '-lxml2', - '-lxml2 -liconv' - ); - } -} diff --git a/src/SPC/builder/unix/library/libxslt.php b/src/SPC/builder/unix/library/libxslt.php deleted file mode 100644 index f0e7d512..00000000 --- a/src/SPC/builder/unix/library/libxslt.php +++ /dev/null @@ -1,45 +0,0 @@ -getStaticLibFiles(include_self: false) : ''; - $cpp = $this instanceof MacOSLibraryBase ? '-lc++' : '-lstdc++'; - $ac = UnixAutoconfExecutor::create($this) - ->appendEnv([ - 'CFLAGS' => "-I{$this->getIncludeDir()}", - 'LDFLAGS' => "-L{$this->getLibDir()}", - 'LIBS' => "{$static_libs} {$cpp}", - ]) - ->addConfigureArgs( - '--without-python', - '--without-crypto', - '--without-debug', - '--without-debugger', - "--with-libxml-prefix={$this->getBuildRootPath()}", - ); - if (getenv('SPC_LD_LIBRARY_PATH') && getenv('SPC_LIBRARY_PATH')) { - $ac->appendEnv([ - 'LD_LIBRARY_PATH' => getenv('SPC_LD_LIBRARY_PATH'), - 'LIBRARY_PATH' => getenv('SPC_LIBRARY_PATH'), - ]); - } - $ac->configure()->make(); - - $this->patchPkgconfPrefix(['libexslt.pc', 'libxslt.pc']); - $this->patchLaDependencyPrefix(); - $AR = getenv('AR') ?: 'ar'; - shell()->cd(BUILD_LIB_PATH) - ->exec("{$AR} -t libxslt.a | grep '\\.a$' | xargs -n1 {$AR} d libxslt.a") - ->exec("{$AR} -t libexslt.a | grep '\\.a$' | xargs -n1 {$AR} d libexslt.a"); - } -} diff --git a/src/SPC/builder/unix/library/libyaml.php b/src/SPC/builder/unix/library/libyaml.php deleted file mode 100644 index 12ab3915..00000000 --- a/src/SPC/builder/unix/library/libyaml.php +++ /dev/null @@ -1,35 +0,0 @@ -source_dir . '/CMakeLists.txt'); - if (preg_match('/set \(YAML_VERSION_MAJOR (\d+)\)/', $content, $major) - && preg_match('/set \(YAML_VERSION_MINOR (\d+)\)/', $content, $minor) - && preg_match('/set \(YAML_VERSION_PATCH (\d+)\)/', $content, $patch)) { - return "{$major[1]}.{$minor[1]}.{$patch[1]}"; - } - return null; - } - - protected function build(): void - { - $cmake = UnixCMakeExecutor::create($this)->addConfigureArgs('-DBUILD_TESTING=OFF'); - if (version_compare(get_cmake_version(), '4.0.0', '>=')) { - $cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.5'); - } - $cmake->build(); - } -} diff --git a/src/SPC/builder/unix/library/libzip.php b/src/SPC/builder/unix/library/libzip.php deleted file mode 100644 index ad0befea..00000000 --- a/src/SPC/builder/unix/library/libzip.php +++ /dev/null @@ -1,30 +0,0 @@ -optionalLib('bzip2', ...cmake_boolean_args('ENABLE_BZIP2')) - ->optionalLib('xz', ...cmake_boolean_args('ENABLE_LZMA')) - ->optionalLib('openssl', ...cmake_boolean_args('ENABLE_OPENSSL')) - ->optionalLib('zstd', ...cmake_boolean_args('ENABLE_ZSTD')) - ->addConfigureArgs( - '-DENABLE_GNUTLS=OFF', - '-DENABLE_MBEDTLS=OFF', - '-DBUILD_DOC=OFF', - '-DBUILD_EXAMPLES=OFF', - '-DBUILD_REGRESS=OFF', - '-DBUILD_TOOLS=OFF', - '-DBUILD_OSSFUZZ=OFF', - ) - ->build(); - $this->patchPkgconfPrefix(['libzip.pc'], PKGCONF_PATCH_PREFIX); - } -} diff --git a/src/SPC/builder/unix/library/mimalloc.php b/src/SPC/builder/unix/library/mimalloc.php deleted file mode 100644 index d483ed39..00000000 --- a/src/SPC/builder/unix/library/mimalloc.php +++ /dev/null @@ -1,25 +0,0 @@ -addConfigureArgs( - '-DMI_BUILD_SHARED=OFF', - '-DMI_BUILD_OBJECT=OFF', - '-DMI_INSTALL_TOPLEVEL=ON', - ); - if (SPCTarget::getLibc() === 'musl') { - $cmake->addConfigureArgs('-DMI_LIBC_MUSL=ON'); - } - $cmake->build(); - } -} diff --git a/src/SPC/builder/unix/library/ncurses.php b/src/SPC/builder/unix/library/ncurses.php deleted file mode 100644 index cb8c10df..00000000 --- a/src/SPC/builder/unix/library/ncurses.php +++ /dev/null @@ -1,57 +0,0 @@ -appendEnv([ - 'CFLAGS' => '-std=c17', - 'LDFLAGS' => SPCTarget::isStatic() ? '-static' : '', - ]) - ->configure( - '--enable-overwrite', - '--with-curses-h', - '--enable-pc-files', - '--enable-echo', - '--disable-widec', - '--with-normal', - '--with-ticlib', - '--without-tests', - '--without-dlsym', - '--without-debug', - '--enable-symlinks', - "--bindir={$this->getBinDir()}", - "--includedir={$this->getIncludeDir()}", - "--libdir={$this->getLibDir()}", - "--prefix={$this->getBuildRootPath()}", - ) - ->make(); - $final = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true); - // Remove the new files - $new_files = array_diff($final, $filelist ?: []); - foreach ($new_files as $file) { - @unlink(BUILD_BIN_PATH . '/' . $file); - } - - shell()->cd(BUILD_ROOT_PATH)->exec('rm -rf share/terminfo'); - shell()->cd(BUILD_ROOT_PATH)->exec('rm -rf lib/terminfo'); - - $pkgconf_list = ['form.pc', 'menu.pc', 'ncurses++.pc', 'ncurses.pc', 'panel.pc', 'tic.pc']; - $this->patchPkgconfPrefix($pkgconf_list); - - foreach ($pkgconf_list as $pkgconf) { - FileSystem::replaceFileStr(BUILD_LIB_PATH . '/pkgconfig/' . $pkgconf, '-L' . BUILD_LIB_PATH, '-L${libdir}'); - } - } -} diff --git a/src/SPC/builder/unix/library/net_snmp.php b/src/SPC/builder/unix/library/net_snmp.php deleted file mode 100644 index df464d52..00000000 --- a/src/SPC/builder/unix/library/net_snmp.php +++ /dev/null @@ -1,49 +0,0 @@ -source_dir}/configure", 'LIBS="-lssl ${OPENSSL_LIBS}"', 'LIBS="-lssl ${OPENSSL_LIBS} -lpthread -ldl"'); - return true; - } - return false; - } - - protected function build(): void - { - // use --static for PKG_CONFIG - UnixAutoconfExecutor::create($this) - ->setEnv(['PKG_CONFIG' => getenv('PKG_CONFIG') . ' --static']) - ->configure( - '--disable-mibs', - '--without-nl', - '--disable-agent', - '--disable-applications', - '--disable-manuals', - '--disable-scripts', - '--disable-embedded-perl', - '--without-perl-modules', - '--with-out-mib-modules="if-mib host disman/event-mib ucd-snmp/diskio mibII"', - '--with-out-transports="Unix"', - '--with-mib-modules=""', - '--enable-mini-agent', - '--with-default-snmp-version="3"', - '--with-sys-contact="@@no.where"', - '--with-sys-location="Unknown"', - '--with-logfile="/var/log/snmpd.log"', - '--with-persistent-directory="/var/lib/net-snmp"', - '--with-openssl=' . BUILD_ROOT_PATH, - '--with-zlib=' . BUILD_ROOT_PATH, - )->make(with_install: 'installheaders installlibs install_pkgconfig'); - $this->patchPkgconfPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/nghttp2.php b/src/SPC/builder/unix/library/nghttp2.php deleted file mode 100644 index 249472f7..00000000 --- a/src/SPC/builder/unix/library/nghttp2.php +++ /dev/null @@ -1,42 +0,0 @@ -optionalLib('zlib', ...ac_with_args('zlib', true)) - ->optionalLib('openssl', ...ac_with_args('openssl', true)) - ->optionalLib('libxml2', ...ac_with_args('libxml2', true)) - ->optionalLib('libev', ...ac_with_args('libev', true)) - ->optionalLib('libcares', ...ac_with_args('libcares', true)) - ->optionalLib('ngtcp2', ...ac_with_args('libngtcp2', true)) - ->optionalLib('nghttp3', ...ac_with_args('libnghttp3', true)) - // ->optionalLib('libbpf', ...ac_with_args('libbpf', true)) - // ->optionalLib('libevent-openssl', ...ac_with_args('libevent-openssl', true)) - // ->optionalLib('jansson', ...ac_with_args('jansson', true)) - // ->optionalLib('jemalloc', ...ac_with_args('jemalloc', true)) - // ->optionalLib('systemd', ...ac_with_args('systemd', true)) - ->optionalLib( - 'brotli', - fn ($lib) => implode(' ', [ - '--with-brotlidec=yes', - "LIBBROTLIDEC_CFLAGS=\"-I{$lib->getIncludeDir()}\"", - "LIBBROTLIDEC_LIBS=\"{$lib->getStaticLibFiles()}\"", - '--with-libbrotlienc=yes', - "LIBBROTLIENC_CFLAGS=\"-I{$lib->getIncludeDir()}\"", - "LIBBROTLIENC_LIBS=\"{$lib->getStaticLibFiles()}\"", - ]) - ) - ->configure('--enable-lib-only') - ->make(); - $this->patchPkgconfPrefix(['libnghttp2.pc']); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/nghttp3.php b/src/SPC/builder/unix/library/nghttp3.php deleted file mode 100644 index 35368f79..00000000 --- a/src/SPC/builder/unix/library/nghttp3.php +++ /dev/null @@ -1,17 +0,0 @@ -configure('--enable-lib-only')->make(); - $this->patchPkgconfPrefix(['libnghttp3.pc']); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/ngtcp2.php b/src/SPC/builder/unix/library/ngtcp2.php deleted file mode 100644 index 8b97e8b8..00000000 --- a/src/SPC/builder/unix/library/ngtcp2.php +++ /dev/null @@ -1,46 +0,0 @@ -optionalLib('openssl', fn (LinuxLibraryBase|MacOSLibraryBase $lib) => implode(' ', [ - '--with-openssl=yes', - "OPENSSL_LIBS=\"{$lib->getStaticLibFiles()}\"", - "OPENSSL_CFLAGS=\"-I{$lib->getIncludeDir()}\"", - ]), '--with-openssl=no') - ->optionalLib('libev', ...ac_with_args('libev', true)) - ->optionalLib('nghttp3', ...ac_with_args('libnghttp3', true)) - ->optionalLib('jemalloc', ...ac_with_args('jemalloc', true)) - ->optionalLib( - 'brotli', - fn (LinuxLibraryBase|MacOSLibraryBase $lib) => implode(' ', [ - '--with-brotlidec=yes', - "LIBBROTLIDEC_CFLAGS=\"-I{$lib->getIncludeDir()}\"", - "LIBBROTLIDEC_LIBS=\"{$lib->getStaticLibFiles()}\"", - '--with-libbrotlienc=yes', - "LIBBROTLIENC_CFLAGS=\"-I{$lib->getIncludeDir()}\"", - "LIBBROTLIENC_LIBS=\"{$lib->getStaticLibFiles()}\"", - ]) - ) - ->appendEnv(['PKG_CONFIG' => '$PKG_CONFIG --static']) - ->configure('--enable-lib-only') - ->make(); - $this->patchPkgconfPrefix(['libngtcp2.pc', 'libngtcp2_crypto_ossl.pc']); - $this->patchLaDependencyPrefix(); - - // on macOS, the static library may contain other static libraries? - // ld: archive member 'libssl.a' not a mach-o file in libngtcp2_crypto_ossl.a - $AR = getenv('AR') ?: 'ar'; - shell()->cd(BUILD_LIB_PATH)->exec("{$AR} -t libngtcp2_crypto_ossl.a | grep '\\.a$' | xargs -n1 {$AR} d libngtcp2_crypto_ossl.a"); - } -} diff --git a/src/SPC/builder/unix/library/onig.php b/src/SPC/builder/unix/library/onig.php deleted file mode 100644 index 0bd04317..00000000 --- a/src/SPC/builder/unix/library/onig.php +++ /dev/null @@ -1,16 +0,0 @@ -configure()->make(); - $this->patchPkgconfPrefix(['oniguruma.pc']); - } -} diff --git a/src/SPC/builder/unix/library/pkgconfig.php b/src/SPC/builder/unix/library/pkgconfig.php deleted file mode 100644 index e6f672e5..00000000 --- a/src/SPC/builder/unix/library/pkgconfig.php +++ /dev/null @@ -1,31 +0,0 @@ -appendEnv([ - 'CFLAGS' => '-Wimplicit-function-declaration -Wno-int-conversion', - 'LDFLAGS' => SPCTarget::isStatic() ? '--static' : '', - ]) - ->configure( - '--with-internal-glib', - '--disable-host-tool', - '--without-sysroot', - '--without-system-include-path', - '--without-system-library-path', - '--without-pc-path', - ) - ->make(with_install: 'install-exec'); - - shell()->exec('strip ' . BUILD_ROOT_PATH . '/bin/pkg-config'); - } -} diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php deleted file mode 100644 index a3aed130..00000000 --- a/src/SPC/builder/unix/library/postgresql.php +++ /dev/null @@ -1,101 +0,0 @@ -source_dir}/src/interfaces/libpq/Makefile", 'invokes exit\'; exit 1;', 'invokes exit\';'); - // disable shared libs build - FileSystem::replaceFileStr( - "{$this->source_dir}/src/Makefile.shlib", - [ - '$(LINK.shared) -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK)', - '$(INSTALL_SHLIB) $< \'$(DESTDIR)$(pkglibdir)/$(shlib)\'', - '$(INSTALL_SHLIB) $< \'$(DESTDIR)$(libdir)/$(shlib)\'', - '$(INSTALL_SHLIB) $< \'$(DESTDIR)$(bindir)/$(shlib)\'', - ], - '' - ); - return true; - } - - protected function build(): void - { - $libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true)); - $spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]); - $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false)); - - $env_vars = [ - 'CFLAGS' => $config['cflags'] . ' -std=c17', - 'CPPFLAGS' => '-DPIC', - 'LDFLAGS' => $config['ldflags'], - 'LIBS' => $config['libs'], - ]; - - if ($ldLibraryPath = getenv('SPC_LD_LIBRARY_PATH')) { - $env_vars['LD_LIBRARY_PATH'] = $ldLibraryPath; - } - - FileSystem::resetDir($this->source_dir . '/build'); - - // php source relies on the non-private encoding functions in libpgcommon.a - FileSystem::replaceFileStr( - "{$this->source_dir}/src/common/Makefile", - '$(OBJS_FRONTEND): CPPFLAGS += -DUSE_PRIVATE_ENCODING_FUNCS', - '$(OBJS_FRONTEND): CPPFLAGS += -UUSE_PRIVATE_ENCODING_FUNCS -DFRONTEND', - ); - - // configure - $shell = shell()->cd("{$this->source_dir}/build")->initializeEnv($this) - ->appendEnv($env_vars) - ->exec( - '../configure ' . - "--prefix={$this->getBuildRootPath()} " . - '--enable-coverage=no ' . - '--with-ssl=openssl ' . - '--with-readline ' . - '--with-libxml ' . - ($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') . - ($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') . - ($this->builder->getLib('libxslt') ? '--with-libxslt ' : '--without-libxslt ') . - ($this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ') . - '--without-lz4 ' . - '--without-perl ' . - '--without-python ' . - '--without-pam ' . - '--without-bonjour ' . - '--without-tcl ' - ); - - // patch ldap lib - if ($this->builder->getLib('ldap')) { - $libs = PkgConfigUtil::getLibsArray('ldap'); - $libs = clean_spaces(implode(' ', $libs)); - FileSystem::replaceFileStr($this->source_dir . '/build/config.status', '-lldap', $libs); - FileSystem::replaceFileStr($this->source_dir . '/build/src/Makefile.global', '-lldap', $libs); - } - - $shell - ->exec('make -C src/bin/pg_config install') - ->exec('make -C src/include install') - ->exec('make -C src/common install') - ->exec('make -C src/port install') - ->exec('make -C src/interfaces/libpq install'); - - // remove dynamic libs - shell()->cd($this->source_dir . '/build') - ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so*") - ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib"); - - FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber'); - } -} diff --git a/src/SPC/builder/unix/library/qdbm.php b/src/SPC/builder/unix/library/qdbm.php deleted file mode 100644 index 640e6c4d..00000000 --- a/src/SPC/builder/unix/library/qdbm.php +++ /dev/null @@ -1,20 +0,0 @@ -configure(); - FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/MYLIBS = libqdbm.a.*/m', 'MYLIBS = libqdbm.a'); - $ac->make($this instanceof MacOSLibraryBase ? 'mac' : ''); - $this->patchPkgconfPrefix(['qdbm.pc']); - } -} diff --git a/src/SPC/builder/unix/library/re2c.php b/src/SPC/builder/unix/library/re2c.php deleted file mode 100644 index cd6a562a..00000000 --- a/src/SPC/builder/unix/library/re2c.php +++ /dev/null @@ -1,32 +0,0 @@ -addConfigureArgs( - '-DRE2C_BUILD_TESTS=OFF', - '-DRE2C_BUILD_EXAMPLES=OFF', - '-DRE2C_BUILD_DOCS=OFF', - '-DRE2C_BUILD_RE2D=OFF', - '-DRE2C_BUILD_RE2GO=OFF', - '-DRE2C_BUILD_RE2HS=OFF', - '-DRE2C_BUILD_RE2JAVA=OFF', - '-DRE2C_BUILD_RE2JS=OFF', - '-DRE2C_BUILD_RE2OCAML=OFF', - '-DRE2C_BUILD_RE2PY=OFF', - '-DRE2C_BUILD_RE2RUST=OFF', - '-DRE2C_BUILD_RE2SWIFT=OFF', - '-DRE2C_BUILD_RE2V=OFF', - '-DRE2C_BUILD_RE2ZIG=OFF', - ) - ->build(); - } -} diff --git a/src/SPC/builder/unix/library/readline.php b/src/SPC/builder/unix/library/readline.php deleted file mode 100644 index 758cc03f..00000000 --- a/src/SPC/builder/unix/library/readline.php +++ /dev/null @@ -1,21 +0,0 @@ -configure( - '--with-curses', - '--enable-multibyte=yes', - ) - ->make(); - $this->patchPkgconfPrefix(['readline.pc']); - } -} diff --git a/src/SPC/builder/unix/library/snappy.php b/src/SPC/builder/unix/library/snappy.php deleted file mode 100644 index 060bb0f4..00000000 --- a/src/SPC/builder/unix/library/snappy.php +++ /dev/null @@ -1,21 +0,0 @@ -setBuildDir("{$this->source_dir}/cmake/build") - ->addConfigureArgs( - '-DSNAPPY_BUILD_TESTS=OFF', - '-DSNAPPY_BUILD_BENCHMARKS=OFF', - ) - ->build('../..'); - } -} diff --git a/src/SPC/builder/unix/library/sqlite.php b/src/SPC/builder/unix/library/sqlite.php deleted file mode 100644 index 8f9add24..00000000 --- a/src/SPC/builder/unix/library/sqlite.php +++ /dev/null @@ -1,16 +0,0 @@ -configure()->make(); - $this->patchPkgconfPrefix(['sqlite3.pc']); - } -} diff --git a/src/SPC/builder/unix/library/tidy.php b/src/SPC/builder/unix/library/tidy.php deleted file mode 100644 index 6afaa94f..00000000 --- a/src/SPC/builder/unix/library/tidy.php +++ /dev/null @@ -1,25 +0,0 @@ -setBuildDir("{$this->source_dir}/build-dir") - ->addConfigureArgs( - '-DSUPPORT_CONSOLE_APP=OFF', - '-DBUILD_SHARED_LIB=OFF' - ); - if (version_compare(get_cmake_version(), '4.0.0', '>=')) { - $cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.5'); - } - $cmake->build(); - $this->patchPkgconfPrefix(['tidy.pc']); - } -} diff --git a/src/SPC/builder/unix/library/unixodbc.php b/src/SPC/builder/unix/library/unixodbc.php deleted file mode 100644 index cf923f24..00000000 --- a/src/SPC/builder/unix/library/unixodbc.php +++ /dev/null @@ -1,45 +0,0 @@ - match (GNU_ARCH) { - 'x86_64' => '/usr/local/etc', - 'aarch64' => '/opt/homebrew/etc', - default => throw new WrongUsageException('Unsupported architecture: ' . GNU_ARCH), - }, - 'Linux' => '/etc', - default => throw new WrongUsageException('Unsupported OS: ' . PHP_OS_FAMILY), - }; - UnixAutoconfExecutor::create($this) - ->configure( - '--disable-debug', - '--disable-dependency-tracking', - "--with-libiconv-prefix={$this->getBuildRootPath()}", - '--with-included-ltdl', - "--sysconfdir={$sysconf_selector}", - '--enable-gui=no', - ) - ->make(); - $pkgConfigs = ['odbc.pc', 'odbccr.pc', 'odbcinst.pc']; - $this->patchPkgconfPrefix($pkgConfigs); - foreach ($pkgConfigs as $file) { - FileSystem::replaceFileStr( - BUILD_LIB_PATH . "/pkgconfig/{$file}", - '$(top_build_prefix)libltdl/libltdlc.la', - '' - ); - } - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/watcher.php b/src/SPC/builder/unix/library/watcher.php deleted file mode 100644 index 359fedd2..00000000 --- a/src/SPC/builder/unix/library/watcher.php +++ /dev/null @@ -1,26 +0,0 @@ -getLibExtraCXXFlags(); - if (stripos($cflags, '-fpic') === false) { - $cflags .= ' -fPIC'; - } - $ldflags = $this->getLibExtraLdFlags() ? ' ' . $this->getLibExtraLdFlags() : ''; - shell()->cd($this->source_dir . '/watcher-c') - ->exec(getenv('CXX') . " -c -o libwatcher-c.o ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -Wall -Wextra {$cflags}{$ldflags}") - ->exec(getenv('AR') . ' rcs libwatcher-c.a libwatcher-c.o'); - - copy($this->source_dir . '/watcher-c/libwatcher-c.a', BUILD_LIB_PATH . '/libwatcher-c.a'); - FileSystem::createDir(BUILD_INCLUDE_PATH . '/wtr'); - copy($this->source_dir . '/watcher-c/include/wtr/watcher-c.h', BUILD_INCLUDE_PATH . '/wtr/watcher-c.h'); - } -} diff --git a/src/SPC/builder/unix/library/xz.php b/src/SPC/builder/unix/library/xz.php deleted file mode 100644 index e17f92b1..00000000 --- a/src/SPC/builder/unix/library/xz.php +++ /dev/null @@ -1,24 +0,0 @@ -configure( - '--disable-scripts', - '--disable-doc', - '--with-libiconv', - '--bindir=/tmp/xz', // xz binary will corrupt `tar` command, that's really strange. - ) - ->make(); - $this->patchPkgconfPrefix(['liblzma.pc']); - $this->patchLaDependencyPrefix(); - } -} diff --git a/src/SPC/builder/unix/library/zlib.php b/src/SPC/builder/unix/library/zlib.php deleted file mode 100644 index 394e4a4f..00000000 --- a/src/SPC/builder/unix/library/zlib.php +++ /dev/null @@ -1,16 +0,0 @@ -exec("./configure --static --prefix={$this->getBuildRootPath()}")->make(); - $this->patchPkgconfPrefix(['zlib.pc']); - } -} diff --git a/src/SPC/builder/unix/library/zstd.php b/src/SPC/builder/unix/library/zstd.php deleted file mode 100644 index 59b26701..00000000 --- a/src/SPC/builder/unix/library/zstd.php +++ /dev/null @@ -1,22 +0,0 @@ -setBuildDir("{$this->source_dir}/build/cmake/build") - ->addConfigureArgs( - '-DZSTD_BUILD_STATIC=ON', - '-DZSTD_BUILD_SHARED=OFF', - ) - ->build(); - $this->patchPkgconfPrefix(['libzstd.pc']); - } -} diff --git a/src/SPC/builder/windows/SystemUtil.php b/src/SPC/builder/windows/SystemUtil.php deleted file mode 100644 index 3a0c23ae..00000000 --- a/src/SPC/builder/windows/SystemUtil.php +++ /dev/null @@ -1,106 +0,0 @@ -|false False if not installed, array contains 'version' and 'dir' - */ - public static function findVisualStudio(): array|false - { - $check_path = [ - 'C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe' => 'vs17', - 'C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe' => 'vs17', - 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe' => 'vs17', - 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe' => 'vs16', - 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe' => 'vs16', - 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe' => 'vs16', - ]; - foreach ($check_path as $path => $vs_version) { - if (file_exists($path)) { - $vs_ver = $vs_version; - $d_dir = dirname($path, 4); - return [ - 'version' => $vs_ver, - 'dir' => $d_dir, - ]; - } - } - return false; - } - - /** - * Get CPU count for concurrency. - */ - public static function getCpuCount(): int - { - $result = f_exec('echo %NUMBER_OF_PROCESSORS%', $out, $code); - if ($code !== 0 || !$result) { - return 1; - } - return intval($result); - } - - /** - * Create CMake toolchain file. - * - * @param null|string $cflags CFLAGS for cmake, default use '/MT /Os /Ob1 /DNDEBUG /D_ACRTIMP= /D_CRTIMP=' - * @param null|string $ldflags LDFLAGS for cmake, default use '/nodefaultlib:msvcrt /nodefaultlib:msvcrtd /defaultlib:libcmt' - */ - public static function makeCmakeToolchainFile(?string $cflags = null, ?string $ldflags = null): string - { - if ($cflags === null) { - $cflags = '/MT /Os /Ob1 /DNDEBUG /D_ACRTIMP= /D_CRTIMP='; - } - if ($ldflags === null) { - $ldflags = '/nodefaultlib:msvcrt /nodefaultlib:msvcrtd /defaultlib:libcmt'; - } - $buildroot = str_replace('\\', '\\\\', BUILD_ROOT_PATH); - $toolchain = <<options = $options; - - GlobalEnvManager::init(); - GlobalEnvManager::afterInit(); - - // ---------- set necessary options ---------- - // set sdk (require visual studio 16 or 17) - $vs = SystemUtil::findVisualStudio()['version']; - $this->sdk_prefix = getenv('PHP_SDK_PATH') . "\\phpsdk-{$vs}-x64.bat -t"; - - // set zts - $this->zts = $this->getOption('enable-zts', false); - - // set concurrency - $this->concurrency = (int) getenv('SPC_CONCURRENCY'); - - // make cmake toolchain - $this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile(); - - f_mkdir(BUILD_INCLUDE_PATH, recursive: true); - f_mkdir(BUILD_LIB_PATH, recursive: true); - } - - public function buildPHP(int $build_target = BUILD_TARGET_NONE): void - { - $enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI; - $enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; - $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; - $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; - $enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI; - - SourcePatcher::patchBeforeBuildconf($this); - - cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} buildconf.bat"); - - SourcePatcher::patchBeforeConfigure($this); - - $zts = $this->zts ? '--enable-zts=yes ' : '--enable-zts=no '; - - $opcache_jit = !$this->getOption('disable-opcache-jit', false); - $opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit=yes ' : '--enable-opcache-jit=no '; - - if (($logo = $this->getOption('with-micro-logo')) !== null) { - // realpath - // $logo = realpath($logo); - $micro_logo = '--enable-micro-logo=' . $logo . ' '; - copy($logo, SOURCE_PATH . '\php-src\\' . $logo); - } else { - $micro_logo = ''; - } - - $micro_w32 = $this->getOption('enable-micro-win32') ? ' --enable-micro-win32=yes' : ''; - - $config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ? - ('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : ''; - - cmd()->cd(SOURCE_PATH . '\php-src') - ->exec( - "{$this->sdk_prefix} configure.bat --task-args \"" . - '--disable-all ' . - '--with-php-build=' . BUILD_ROOT_PATH . ' ' . - '--with-extra-includes=' . BUILD_INCLUDE_PATH . ' ' . - '--with-extra-libs=' . BUILD_LIB_PATH . ' ' . - ($enableCli ? '--enable-cli ' : '--disable-cli ') . - ($enableMicro ? ('--enable-micro ' . $micro_logo . $micro_w32) : '--disable-micro ') . - ($enableEmbed ? '--enable-embed ' : '--disable-embed ') . - ($enableCgi ? '--enable-cgi ' : '--disable-cgi ') . - $config_file_scan_dir . - $opcache_jit_arg . - "{$this->makeStaticExtensionArgs()} " . - $zts . - '"' - ); - - SourcePatcher::patchBeforeMake($this); - - $this->cleanMake(); - - if ($enableCli) { - logger()->info('building cli'); - $this->buildCli(); - } - if ($enableFpm) { - logger()->warning('Windows does not support fpm SAPI, I will skip it.'); - } - if ($enableCgi) { - logger()->info('building cgi'); - $this->buildCgi(); - } - if ($enableMicro) { - logger()->info('building micro'); - $this->buildMicro(); - - SourcePatcher::unpatchMicroWin32(); - } - if ($enableEmbed) { - logger()->warning('Windows does not currently support embed SAPI.'); - // logger()->info('building embed'); - $this->buildEmbed(); - } - } - - public function testPHP(int $build_target = BUILD_TARGET_NONE): void - { - $this->sanityCheck($build_target); - } - - public function buildCli(): void - { - SourcePatcher::patchWindowsCLITarget(); - - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - - // Add debug symbols for release build if --no-strip is specified - // We need to modify CFLAGS to replace /Ox with /Zi and add /DEBUG to LDFLAGS - $debug_overrides = ''; - if ($this->getOption('no-strip', false)) { - // Read current CFLAGS from Makefile and replace optimization flags - $makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile'); - if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) { - $cflags = $matches[1]; - // Replace /Ox (full optimization) with /Zi (debug info) and /Od (disable optimization) - // Keep optimization for speed: /O2 /Zi instead of /Od /Zi - $cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags); - $debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_CLI=/DEBUG" '; - } - } - - // add nmake wrapper - FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cli_wrapper.bat', "nmake /nologo {$debug_overrides}LIBS_CLI=\"ws2_32.lib shell32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*"); - - cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cli_wrapper.bat --task-args php.exe"); - - $this->deploySAPIBinary(BUILD_TARGET_CLI); - } - - public function buildCgi(): void - { - SourcePatcher::patchWindowsCGITarget(); - - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - - // Add debug symbols for release build if --no-strip is specified - $debug_overrides = ''; - if ($this->getOption('no-strip', false)) { - $makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile'); - if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) { - $cflags = $matches[1]; - $cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags); - $debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_CGI=/DEBUG" '; - } - } - - // add nmake wrapper - FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cgi_wrapper.bat', "nmake /nologo {$debug_overrides}LIBS_CGI=\"ws2_32.lib kernel32.lib advapi32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*"); - - cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cgi_wrapper.bat --task-args php-cgi.exe"); - - $this->deploySAPIBinary(BUILD_TARGET_CGI); - } - - public function buildEmbed(): void - { - // TODO: add embed support for windows - /* - FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_embed_wrapper.bat', 'nmake /nologo %*'); - - cmd()->cd(SOURCE_PATH . '\php-src') - ->exec("{$this->sdk_prefix} nmake_embed_wrapper.bat --task-args php8embed.lib"); - */ - } - - public function buildMicro(): void - { - // workaround for fiber (originally from https://github.com/dixyes/lwmbs/blob/master/windows/MicroBuild.php) - $makefile = FileSystem::readFile(SOURCE_PATH . '\php-src\Makefile'); - if ($this->getPHPVersionID() >= 80200 && str_contains($makefile, 'FIBER_ASM_ARCH')) { - $makefile .= "\r\n" . '$(MICRO_SFX): $(BUILD_DIR)\Zend\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.obj $(BUILD_DIR)\Zend\make_$(FIBER_ASM_ARCH)_ms_pe_masm.obj' . "\r\n\r\n"; - } elseif ($this->getPHPVersionID() >= 80400 && str_contains($makefile, 'FIBER_ASM_ABI')) { - $makefile .= "\r\n" . '$(MICRO_SFX): $(BUILD_DIR)\Zend\jump_$(FIBER_ASM_ABI).obj $(BUILD_DIR)\Zend\make_$(FIBER_ASM_ABI).obj' . "\r\n\r\n"; - } - FileSystem::writeFile(SOURCE_PATH . '\php-src\Makefile', $makefile); - - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - - // Add debug symbols for release build if --no-strip is specified - $debug_overrides = ''; - if ($this->getOption('no-strip', false) && !$this->getOption('debug', false)) { - $makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile'); - if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) { - $cflags = $matches[1]; - $cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags); - $debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_MICRO=/DEBUG" '; - } - } - - // add nmake wrapper - $fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' /DPHP_MICRO_FAKE_CLI" ' : ''; - $wrapper = "nmake /nologo {$debug_overrides}LIBS_MICRO=\"ws2_32.lib shell32.lib {$extra_libs}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" %*"; - FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_micro_wrapper.bat', $wrapper); - - // phar patch for micro - if ($this->getExt('phar')) { - $this->phar_patched = true; - SourcePatcher::patchMicroPhar($this->getPHPVersionID()); - } - - try { - cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_micro_wrapper.bat --task-args micro"); - } finally { - if ($this->phar_patched) { - SourcePatcher::unpatchMicroPhar(); - } - } - - $this->deploySAPIBinary(BUILD_TARGET_MICRO); - } - - public function proveLibs(array $sorted_libraries): void - { - // search all supported libs - $support_lib_list = []; - $classes = FileSystem::getClassesPsr4( - ROOT_DIR . '\src\SPC\builder\\' . osfamily2dir() . '\library', - 'SPC\builder\\' . osfamily2dir() . '\library' - ); - foreach ($classes as $class) { - if (defined($class . '::NAME') && $class::NAME !== 'unknown' && Config::getLib($class::NAME) !== null) { - $support_lib_list[$class::NAME] = $class; - } - } - - // if no libs specified, compile all supported libs - if ($sorted_libraries === [] && $this->isLibsOnly()) { - $libraries = array_keys($support_lib_list); - $sorted_libraries = DependencyUtil::getLibs($libraries); - } - - // add lib object for builder - foreach ($sorted_libraries as $library) { - if (!in_array(Config::getLib($library, 'type', 'lib'), ['lib', 'package'])) { - continue; - } - // if some libs are not supported (but in config "lib.json", throw exception) - if (!isset($support_lib_list[$library])) { - throw new WrongUsageException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!'); - } - $lib = new ($support_lib_list[$library])($this); - $this->addLib($lib); - } - - // calculate and check dependencies - foreach ($this->libs as $lib) { - $lib->calcDependency(); - } - $this->lib_list = $sorted_libraries; - } - - public function cleanMake(): void - { - FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_clean_wrapper.bat', 'nmake /nologo %*'); - cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_clean_wrapper.bat --task-args \"clean\""); - } - - /** - * Run extension and PHP cli and micro check - */ - public function sanityCheck(mixed $build_target): void - { - // remove all .dll from `buildroot/bin/` - logger()->debug('Removing all .dll files from buildroot/bin/'); - $dlls = glob(BUILD_BIN_PATH . '\*.dll'); - foreach ($dlls as $dll) { - @unlink($dll); - } - // sanity check for php-cli - if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { - logger()->info('running cli sanity check'); - [$ret, $output] = cmd()->execWithResult(BUILD_BIN_PATH . '\php.exe -n -r "echo \"hello\";"'); - if ($ret !== 0 || trim(implode('', $output)) !== 'hello') { - throw new ValidationException('cli failed sanity check', validation_module: 'php-cli function check'); - } - - foreach ($this->getExts(false) as $ext) { - logger()->debug('testing ext: ' . $ext->getName()); - $ext->runCliCheckWindows(); - } - } - - // sanity check for phpmicro - if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) { - $test_task = $this->getMicroTestTasks(); - foreach ($test_task as $task_name => $task) { - $test_file = SOURCE_PATH . '/' . $task_name . '.exe'; - if (file_exists($test_file)) { - @unlink($test_file); - } - file_put_contents($test_file, file_get_contents(BUILD_BIN_PATH . '\micro.sfx') . $task['content']); - chmod($test_file, 0755); - [$ret, $out] = cmd()->execWithResult($test_file); - foreach ($task['conditions'] as $condition => $closure) { - if (!$closure($ret, $out)) { - $raw_out = trim(implode('', $out)); - throw new ValidationException( - "failure info: {$condition}, code: {$ret}, output: {$raw_out}", - validation_module: "phpmicro sanity check item [{$task_name}]" - ); - } - } - } - } - - // sanity check for php-cgi - if (($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) { - logger()->info('running cgi sanity check'); - FileSystem::writeFile(SOURCE_PATH . '\php-cgi-test.php', 'Hello, World!"; ?>'); - [$ret, $output] = cmd()->execWithResult(BUILD_BIN_PATH . '\php-cgi.exe -n -f ' . SOURCE_PATH . '\php-cgi-test.php'); - $raw_output = implode("\n", $output); - if ($ret !== 0 || !str_contains($raw_output, 'Hello, World!')) { - throw new ValidationException("cgi failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cgi sanity check'); - } - } - } - - /** - * Deploy the binary file to buildroot/bin/ - * - * @param int $type Deploy type - */ - public function deploySAPIBinary(int $type): void - { - logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file'); - - $debug_dir = BUILD_ROOT_PATH . '\debug'; - $bin_path = BUILD_BIN_PATH; - - // create dirs - FileSystem::createDir($debug_dir); - FileSystem::createDir($bin_path); - - // determine source path for different SAPI - $rel_type = 'Release'; // TODO: Debug build support - $ts = $this->zts ? '_TS' : ''; - $src = match ($type) { - BUILD_TARGET_CLI => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'php.exe', 'php.pdb'], - BUILD_TARGET_MICRO => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'micro.sfx', 'micro.pdb'], - BUILD_TARGET_CGI => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'php-cgi.exe', 'php-cgi.pdb'], - default => throw new SPCInternalException("Deployment does not accept type {$type}"), - }; - - $src = "{$src[0]}\\{$src[1]}"; - $dst = BUILD_BIN_PATH . '\\' . basename($src); - - // file must exists - if (!file_exists($src)) { - throw new SPCInternalException("Deploy failed. Cannot find file: {$src}"); - } - // dst dir must exists - FileSystem::createDir(dirname($dst)); - - // copy file - if (realpath($src) !== realpath($dst)) { - cmd()->exec('copy ' . escapeshellarg($src) . ' ' . escapeshellarg($dst)); - } - - // extract debug info in buildroot/debug - if ($this->getOption('no-strip', false) && file_exists("{$src[0]}\\{$src[2]}")) { - cmd()->exec('copy ' . escapeshellarg("{$src[0]}\\{$src[2]}") . ' ' . escapeshellarg($debug_dir)); - } - - // with-upx-pack for cli and micro - if ($this->getOption('with-upx-pack', false)) { - if ($type === BUILD_TARGET_CLI || $type === BUILD_TARGET_CGI || ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0)) { - cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg($dst)); - } - } - } - - /** - * Generate command wrapper prefix for php-sdk internal commands. - * - * @param string $internal_cmd command in php-sdk-tools\bin - * @return string Example: C:\php-sdk-tools\phpsdk-vs17-x64.bat -t source\cmake_wrapper.bat --task-args - */ - public function makeSimpleWrapper(string $internal_cmd): string - { - $wrapper_bat = SOURCE_PATH . '\\' . crc32($internal_cmd) . '_wrapper.bat'; - if (!file_exists($wrapper_bat)) { - file_put_contents($wrapper_bat, $internal_cmd . ' %*'); - } - return "{$this->sdk_prefix} {$wrapper_bat} --task-args"; - } -} diff --git a/src/SPC/builder/windows/library/WindowsLibraryBase.php b/src/SPC/builder/windows/library/WindowsLibraryBase.php deleted file mode 100644 index dfc221c9..00000000 --- a/src/SPC/builder/windows/library/WindowsLibraryBase.php +++ /dev/null @@ -1,22 +0,0 @@ -builder; - } -} diff --git a/src/SPC/builder/windows/library/brotli.php b/src/SPC/builder/windows/library/brotli.php deleted file mode 100644 index f22f402c..00000000 --- a/src/SPC/builder/windows/library/brotli.php +++ /dev/null @@ -1,36 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBROTLI_BUILD_TOOLS=OFF ' . - '-DBROTLI_BUNDLED_MODE=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/bzip2.php b/src/SPC/builder/windows/library/bzip2.php deleted file mode 100644 index 81a74b0a..00000000 --- a/src/SPC/builder/windows/library/bzip2.php +++ /dev/null @@ -1,21 +0,0 @@ -builder->makeSimpleWrapper('nmake /nologo /f Makefile.msc CFLAGS="-DWIN32 -MT -Ox -D_FILE_OFFSET_BITS=64 -nologo"'); - cmd()->cd($this->source_dir) - ->execWithWrapper($nmake, 'clean') - ->execWithWrapper($nmake, 'lib'); - copy($this->source_dir . '\libbz2.lib', BUILD_LIB_PATH . '\libbz2.lib'); - copy($this->source_dir . '\libbz2.lib', BUILD_LIB_PATH . '\libbz2_a.lib'); - copy($this->source_dir . '\bzlib.h', BUILD_INCLUDE_PATH . '\bzlib.h'); - } -} diff --git a/src/SPC/builder/windows/library/curl.php b/src/SPC/builder/windows/library/curl.php deleted file mode 100644 index bba130e1..00000000 --- a/src/SPC/builder/windows/library/curl.php +++ /dev/null @@ -1,58 +0,0 @@ -source_dir . '\cmakebuild'); - - // lib:zstd - $alt = $this->builder->getLib('zstd') ? '' : '-DCURL_ZSTD=OFF'; - // lib:brotli - $alt .= $this->builder->getLib('brotli') ? '' : ' -DCURL_BROTLI=OFF'; - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B cmakebuild ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . - '-DBUILD_CURL_EXE=OFF ' . // disable curl.exe - '-DBUILD_TESTING=OFF ' . // disable tests - '-DBUILD_EXAMPLES=OFF ' . // disable examples - '-DUSE_LIBIDN2=OFF ' . // disable libidn2 - '-DCURL_USE_LIBPSL=OFF ' . // disable libpsl - '-DUSE_WINDOWS_SSPI=ON ' . // use Schannel instead of OpenSSL - '-DCURL_USE_SCHANNEL=ON ' . // use Schannel instead of OpenSSL - '-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 - $alt - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build cmakebuild --config Release --target install -j{$this->builder->concurrency}" - ); - // 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/freetype.php b/src/SPC/builder/windows/library/freetype.php deleted file mode 100644 index 8401b4de..00000000 --- a/src/SPC/builder/windows/library/freetype.php +++ /dev/null @@ -1,38 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DFT_DISABLE_BROTLI=TRUE ' . - '-DFT_DISABLE_BZIP2=TRUE ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - // freetype.lib to libfreetype_a.lib - copy(BUILD_LIB_PATH . '\freetype.lib', BUILD_LIB_PATH . '\libfreetype_a.lib'); - } -} diff --git a/src/SPC/builder/windows/library/gmssl.php b/src/SPC/builder/windows/library/gmssl.php deleted file mode 100644 index ed991635..00000000 --- a/src/SPC/builder/windows/library/gmssl.php +++ /dev/null @@ -1,33 +0,0 @@ -source_dir . '\builddir'); - - // start build - cmd()->cd($this->source_dir . '\builddir') - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake .. -G "NMake Makefiles" -DWIN32=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" -DCMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" -DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH), - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH - ); - - FileSystem::writeFile($this->source_dir . '\builddir\cmake_install.cmake', 'set(CMAKE_INSTALL_PREFIX "' . str_replace('\\', '/', BUILD_ROOT_PATH) . '")' . PHP_EOL . FileSystem::readFile($this->source_dir . '\builddir\cmake_install.cmake')); - - cmd()->cd($this->source_dir . '\builddir') - ->execWithWrapper( - $this->builder->makeSimpleWrapper('nmake'), - 'install XCFLAGS=/MT' - ); - } -} diff --git a/src/SPC/builder/windows/library/icu_static_win.php b/src/SPC/builder/windows/library/icu_static_win.php deleted file mode 100644 index fdd9e6cd..00000000 --- a/src/SPC/builder/windows/library/icu_static_win.php +++ /dev/null @@ -1,27 +0,0 @@ -source_dir}\\lib\\icudt.lib", "{$this->getLibDir()}\\icudt.lib"); - copy("{$this->source_dir}\\lib\\icuin.lib", "{$this->getLibDir()}\\icuin.lib"); - copy("{$this->source_dir}\\lib\\icuio.lib", "{$this->getLibDir()}\\icuio.lib"); - copy("{$this->source_dir}\\lib\\icuuc.lib", "{$this->getLibDir()}\\icuuc.lib"); - - // create libpq folder in buildroot/includes/libpq - if (!file_exists("{$this->getIncludeDir()}\\unicode")) { - mkdir("{$this->getIncludeDir()}\\unicode"); - } - - FileSystem::copyDir("{$this->source_dir}\\include\\unicode", "{$this->getIncludeDir()}\\unicode"); - } -} diff --git a/src/SPC/builder/windows/library/libaom.php b/src/SPC/builder/windows/library/libaom.php deleted file mode 100644 index 06d53cbc..00000000 --- a/src/SPC/builder/windows/library/libaom.php +++ /dev/null @@ -1,41 +0,0 @@ -source_dir . '\builddir'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-S . -B builddir ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DAOM_TARGET_CPU=generic ' . - '-DENABLE_DOCS=OFF ' . - '-DENABLE_EXAMPLES=OFF ' . - '-DENABLE_TESTDATA=OFF ' . - '-DENABLE_TESTS=OFF ' . - '-DENABLE_TOOLS=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build builddir --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/libavif.php b/src/SPC/builder/windows/library/libavif.php deleted file mode 100644 index c9c966a7..00000000 --- a/src/SPC/builder/windows/library/libavif.php +++ /dev/null @@ -1,40 +0,0 @@ -source_dir . '\src\read.c', 'avifFileType ftyp = {};', 'avifFileType ftyp = { 0 };'); - // reset cmake - FileSystem::resetDir($this->source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DAVIF_BUILD_APPS=OFF ' . - '-DAVIF_BUILD_TESTS=OFF ' . - '-DAVIF_LIBYUV=OFF ' . - '-DAVID_ENABLE_GTEST=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/libffi_win.php b/src/SPC/builder/windows/library/libffi_win.php deleted file mode 100644 index 8d92acdf..00000000 --- a/src/SPC/builder/windows/library/libffi_win.php +++ /dev/null @@ -1,52 +0,0 @@ -vs_ver_dir = match ($ver = SystemUtil::findVisualStudio()['version']) { - 'vs17' => '\win32\vs17_x64', - 'vs16' => '\win32\vs16_x64', - default => throw new EnvironmentException("Current VS version {$ver} is not supported !"), - }; - } - - protected function build(): void - { - // start build - cmd()->cd($this->source_dir . $this->vs_ver_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('msbuild'), - 'libffi-msvc.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64' - ); - FileSystem::createDir(BUILD_LIB_PATH); - FileSystem::createDir(BUILD_INCLUDE_PATH); - - FileSystem::copy("{$this->source_dir}{$this->vs_ver_dir}\\x64\\Release\\libffi.lib", BUILD_LIB_PATH . '\libffi.lib'); - FileSystem::copy("{$this->source_dir}{$this->vs_ver_dir}\\x64\\Release\\libffi.pdb", BUILD_LIB_PATH . '\libffi.pdb'); - FileSystem::copy($this->source_dir . '\include\ffi.h', BUILD_INCLUDE_PATH . '\ffi.h'); - - FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\ffi.h', '#define LIBFFI_H', "#define LIBFFI_H\n#define FFI_BUILDING"); - FileSystem::copy($this->source_dir . '\src\x86\ffitarget.h', BUILD_INCLUDE_PATH . '\ffitarget.h'); - FileSystem::copy($this->source_dir . '\fficonfig.h', BUILD_INCLUDE_PATH . '\fficonfig.h'); - - // copy($this->source_dir . '\msvc_build\out\static-Release\X64\libffi.lib', BUILD_LIB_PATH . '\libffi.lib'); - // copy($this->source_dir . '\msvc_build\include\ffi.h', BUILD_INCLUDE_PATH . '\ffi.h'); - // copy($this->source_dir . '\msvc_build\include\fficonfig.h', BUILD_INCLUDE_PATH . '\fficonfig.h'); - // copy($this->source_dir . '\src\x86\ffitarget.h', BUILD_INCLUDE_PATH . '\ffitarget.h'); - - // FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\ffi.h', '..\..\src\x86\ffitarget.h', 'ffitarget.h'); - } -} diff --git a/src/SPC/builder/windows/library/libiconv_win.php b/src/SPC/builder/windows/library/libiconv_win.php deleted file mode 100644 index 36d7e79e..00000000 --- a/src/SPC/builder/windows/library/libiconv_win.php +++ /dev/null @@ -1,40 +0,0 @@ -vs_ver_dir = match ($ver = SystemUtil::findVisualStudio()['version']) { - 'vs17' => '\MSVC17', - 'vs16' => '\MSVC16', - default => throw new EnvironmentException("Current VS version {$ver} is not supported yet!"), - }; - } - - protected function build(): void - { - // start build - cmd()->cd($this->source_dir . $this->vs_ver_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('msbuild'), - 'libiconv.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64' - ); - FileSystem::createDir(BUILD_LIB_PATH); - FileSystem::createDir(BUILD_INCLUDE_PATH); - copy("{$this->source_dir}{$this->vs_ver_dir}\\x64\\lib\\libiconv.lib", BUILD_LIB_PATH . '\libiconv.lib'); - copy("{$this->source_dir}{$this->vs_ver_dir}\\x64\\lib\\libiconv_a.lib", BUILD_LIB_PATH . '\libiconv_a.lib'); - copy($this->source_dir . '\source\include\iconv.h', BUILD_INCLUDE_PATH . '\iconv.h'); - } -} diff --git a/src/SPC/builder/windows/library/libjpeg.php b/src/SPC/builder/windows/library/libjpeg.php deleted file mode 100644 index 0e5a6999..00000000 --- a/src/SPC/builder/windows/library/libjpeg.php +++ /dev/null @@ -1,42 +0,0 @@ -builder->getLib('zlib') ? 'ON' : 'OFF'; - // reset cmake - FileSystem::resetDir($this->source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DENABLE_SHARED=OFF ' . - '-DENABLE_STATIC=ON ' . - '-DBUILD_TESTING=OFF ' . - '-DWITH_JAVA=OFF ' . - '-DWITH_SIMD=OFF ' . - '-DWITH_CRT_DLL=OFF ' . - "-DENABLE_ZLIB_COMPRESSION={$zlib} " . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - copy(BUILD_LIB_PATH . '\jpeg-static.lib', BUILD_LIB_PATH . '\libjpeg_a.lib'); - } -} diff --git a/src/SPC/builder/windows/library/libpng.php b/src/SPC/builder/windows/library/libpng.php deleted file mode 100644 index a722fa79..00000000 --- a/src/SPC/builder/windows/library/libpng.php +++ /dev/null @@ -1,40 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DSKIP_INSTALL_PROGRAM=ON ' . - '-DSKIP_INSTALL_FILES=ON ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DPNG_STATIC=ON ' . - '-DPNG_SHARED=OFF ' . - '-DPNG_TESTS=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - copy(BUILD_LIB_PATH . '\libpng16_static.lib', BUILD_LIB_PATH . '\libpng_a.lib'); - } -} diff --git a/src/SPC/builder/windows/library/librabbitmq.php b/src/SPC/builder/windows/library/librabbitmq.php deleted file mode 100644 index 19c33a31..00000000 --- a/src/SPC/builder/windows/library/librabbitmq.php +++ /dev/null @@ -1,36 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - rename(BUILD_LIB_PATH . '\librabbitmq.4.lib', BUILD_LIB_PATH . '\rabbitmq.4.lib'); - } -} diff --git a/src/SPC/builder/windows/library/libsodium.php b/src/SPC/builder/windows/library/libsodium.php deleted file mode 100644 index c2ddb9ac..00000000 --- a/src/SPC/builder/windows/library/libsodium.php +++ /dev/null @@ -1,63 +0,0 @@ -vs_ver_dir = match ($ver = SystemUtil::findVisualStudio()['version']) { - 'vs17' => '\vs2022', - 'vs16' => '\vs2019', - default => throw new EnvironmentException("Current VS version {$ver} is not supported yet!"), - }; - } - - public function patchBeforeBuild(): bool - { - FileSystem::replaceFileStr($this->source_dir . '\src\libsodium\include\sodium\export.h', '#ifdef SODIUM_STATIC', '#if 1'); - return true; - } - - protected function build(): void - { - // start build - cmd()->cd($this->source_dir . '\builds\msvc' . $this->vs_ver_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('msbuild'), - 'libsodium.sln /t:Rebuild /p:Configuration=StaticRelease /p:Platform=x64 /p:PreprocessorDefinitions="SODIUM_STATIC=1"' - ); - FileSystem::createDir(BUILD_LIB_PATH); - FileSystem::createDir(BUILD_INCLUDE_PATH); - - // copy include - FileSystem::copyDir($this->source_dir . '\src\libsodium\include\sodium', BUILD_INCLUDE_PATH . '\sodium'); - copy($this->source_dir . '\src\libsodium\include\sodium.h', BUILD_INCLUDE_PATH . '\sodium.h'); - // copy lib - $ls = FileSystem::scanDirFiles($this->source_dir . '\bin'); - $find = false; - foreach ($ls as $file) { - if (str_ends_with($file, 'libsodium.lib')) { - copy($file, BUILD_LIB_PATH . '\libsodium.lib'); - $find = true; - } - if (str_ends_with($file, 'libsodium.pdb')) { - copy($file, BUILD_LIB_PATH . '\libsodium.pdb'); - } - } - if (!$find) { - throw new BuildFailureException("Build libsodium success, but cannot find libsodium.lib in {$this->source_dir}\\bin ."); - } - } -} diff --git a/src/SPC/builder/windows/library/libssh2.php b/src/SPC/builder/windows/library/libssh2.php deleted file mode 100644 index f064e139..00000000 --- a/src/SPC/builder/windows/library/libssh2.php +++ /dev/null @@ -1,38 +0,0 @@ -builder->getLib('zlib') ? 'ON' : 'OFF'; - // reset cmake - FileSystem::resetDir($this->source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DBUILD_TESTING=OFF ' . - "-DENABLE_ZLIB_COMPRESSION={$zlib} " . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/libwebp.php b/src/SPC/builder/windows/library/libwebp.php deleted file mode 100644 index 96813e68..00000000 --- a/src/SPC/builder/windows/library/libwebp.php +++ /dev/null @@ -1,52 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DWEBP_LINK_STATIC=ON ' . - '-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_LIBWEBPMUX=OFF ' . - '-DWEBP_BUILD_WEBPMUX=OFF ' . - '-DWEBP_BUILD_EXTRAS=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - - // Actually we don't need pkgconf in windows, but for packing, we still need patching prefix. - // for libsharpyuv, libwebp, libwebpdecoder, libwebpdemux - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '\pkgconfig\libsharpyuv.pc', '/^prefix=.*/m', 'prefix=${pcfiledir}/../..'); - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '\pkgconfig\libwebp.pc', '/^prefix=.*/m', 'prefix=${pcfiledir}/../..'); - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '\pkgconfig\libwebpdecoder.pc', '/^prefix=.*/m', 'prefix=${pcfiledir}/../..'); - FileSystem::replaceFileRegex(BUILD_LIB_PATH . '\pkgconfig\libwebpdemux.pc', '/^prefix=.*/m', 'prefix=${pcfiledir}/../..'); - } -} diff --git a/src/SPC/builder/windows/library/libxml2.php b/src/SPC/builder/windows/library/libxml2.php deleted file mode 100644 index d4a4b9b4..00000000 --- a/src/SPC/builder/windows/library/libxml2.php +++ /dev/null @@ -1,44 +0,0 @@ -builder->getLib('zlib') ? 'ON' : 'OFF'; - // reset cmake - FileSystem::resetDir($this->source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_STATIC_LIBS=ON ' . - "-DLIBXML2_WITH_ZLIB={$zlib} " . - '-DLIBXML2_WITH_PYTHON=OFF ' . - '-DLIBXML2_WITH_ICONV=ON ' . - '-DIconv_LIBRARY=' . BUILD_LIB_PATH . ' ' . - '-DIconv_INCLUDE_DIR=' . BUILD_INCLUDE_PATH . ' ' . - '-DLIBXML2_WITH_LZMA=OFF ' . // xz not supported yet - '-DLIBXML2_WITH_PROGRAMS=OFF ' . - '-DLIBXML2_WITH_TESTS=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - copy(BUILD_LIB_PATH . '\libxml2s.lib', BUILD_LIB_PATH . '\libxml2_a.lib'); - } -} diff --git a/src/SPC/builder/windows/library/libyaml.php b/src/SPC/builder/windows/library/libyaml.php deleted file mode 100644 index 5d4026c5..00000000 --- a/src/SPC/builder/windows/library/libyaml.php +++ /dev/null @@ -1,44 +0,0 @@ -source_dir . '\build'); - - // check missing files: cmake\config.h.in and .\YamlConfig.cmake.in - if (!file_exists($this->source_dir . '\cmake\config.h.in')) { - FileSystem::createDir($this->source_dir . '\cmake'); - copy(ROOT_DIR . '\src\globals\extra\libyaml_config.h.in', $this->source_dir . '\cmake\config.h.in'); - } - if (!file_exists($this->source_dir . '\YamlConfig.cmake.in')) { - copy(ROOT_DIR . '\src\globals\extra\libyaml_YamlConfig.cmake.in', $this->source_dir . '\YamlConfig.cmake.in'); - } - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_TESTING=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/libzip.php b/src/SPC/builder/windows/library/libzip.php deleted file mode 100644 index 9a8206af..00000000 --- a/src/SPC/builder/windows/library/libzip.php +++ /dev/null @@ -1,46 +0,0 @@ -source_dir . '\build'); - - $openssl = $this->builder->getLib('openssl') ? 'ON' : 'OFF'; - $zstd = $this->builder->getLib('zstd') ? 'ON' : 'OFF'; - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DENABLE_BZIP2=ON ' . - '-DENABLE_LZMA=ON ' . - "-DENABLE_ZSTD={$zstd} " . - "-DENABLE_OPENSSL={$openssl} " . - '-DBUILD_TOOLS=OFF ' . - '-DBUILD_DOC=OFF ' . - '-DBUILD_EXAMPLES=OFF ' . - '-DBUILD_REGRESS=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - copy(BUILD_LIB_PATH . '\zip.lib', BUILD_LIB_PATH . '\libzip_a.lib'); - } -} diff --git a/src/SPC/builder/windows/library/nghttp2.php b/src/SPC/builder/windows/library/nghttp2.php deleted file mode 100644 index 5a1c6bf1..00000000 --- a/src/SPC/builder/windows/library/nghttp2.php +++ /dev/null @@ -1,44 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DENABLE_SHARED_LIB=OFF ' . - '-DENABLE_STATIC_LIB=ON ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DENABLE_STATIC_CRT=ON ' . - '-DENABLE_LIB_ONLY=ON ' . - '-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/builder/windows/library/nghttp3.php b/src/SPC/builder/windows/library/nghttp3.php deleted file mode 100644 index 1586a4d8..00000000 --- a/src/SPC/builder/windows/library/nghttp3.php +++ /dev/null @@ -1,39 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DENABLE_SHARED_LIB=OFF ' . - '-DENABLE_STATIC_LIB=ON ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DENABLE_STATIC_CRT=ON ' . - '-DENABLE_LIB_ONLY=ON ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/ngtcp2.php b/src/SPC/builder/windows/library/ngtcp2.php deleted file mode 100644 index 79895dd6..00000000 --- a/src/SPC/builder/windows/library/ngtcp2.php +++ /dev/null @@ -1,40 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DENABLE_SHARED_LIB=OFF ' . - '-DENABLE_STATIC_LIB=ON ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DENABLE_STATIC_CRT=ON ' . - '-DENABLE_LIB_ONLY=ON ' . - '-DENABLE_OPENSSL=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - } -} diff --git a/src/SPC/builder/windows/library/onig.php b/src/SPC/builder/windows/library/onig.php deleted file mode 100644 index 11ce815e..00000000 --- a/src/SPC/builder/windows/library/onig.php +++ /dev/null @@ -1,37 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DBUILD_STATIC_LIBS=ON ' . - '-DMSVC_STATIC_RUNTIME=ON ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - copy(BUILD_LIB_PATH . '/onig.lib', BUILD_LIB_PATH . '/onig_a.lib'); - } -} diff --git a/src/SPC/builder/windows/library/openssl.php b/src/SPC/builder/windows/library/openssl.php deleted file mode 100644 index 491a33b4..00000000 --- a/src/SPC/builder/windows/library/openssl.php +++ /dev/null @@ -1,61 +0,0 @@ -perl = file_exists($perl_path_native) ? ($perl_path_native) : SystemUtil::findCommand('perl.exe'); - if ($this->perl === null) { - throw new EnvironmentException( - 'You need to install perl first!', - "Please run \"{$argv[0]} doctor\" to fix the environment.", - ); - } - } - - protected function build(): void - { - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper($this->perl), - 'Configure zlib VC-WIN64A ' . - 'no-shared ' . - '--prefix=' . quote(BUILD_ROOT_PATH) . ' ' . - '--with-zlib-lib=' . quote(BUILD_LIB_PATH) . ' ' . - '--with-zlib-include=' . quote(BUILD_INCLUDE_PATH) . ' ' . - '--release ' . - 'no-legacy ' - ); - - // patch zlib - FileSystem::replaceFileStr($this->source_dir . '\Makefile', 'ZLIB1', 'zlibstatic.lib'); - // patch debug: https://stackoverflow.com/questions/18486243/how-do-i-build-openssl-statically-linked-against-windows-runtime - FileSystem::replaceFileStr($this->source_dir . '\Makefile', '/debug', '/incremental:no /opt:icf /dynamicbase /nxcompat /ltcg /nodefaultlib:msvcrt'); - cmd()->cd($this->source_dir)->execWithWrapper( - $this->builder->makeSimpleWrapper('nmake'), - 'install_dev ' . - 'CNF_LDFLAGS="/NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:msvcrt /NODEFAULTLIB:msvcrtd /DEFAULTLIB:libcmt /LIBPATH:' . BUILD_LIB_PATH . ' zlibstatic.lib"' - ); - copy($this->source_dir . '\ms\applink.c', BUILD_INCLUDE_PATH . '\openssl\applink.c'); - - FileSystem::replaceFileRegex( - BUILD_LIB_PATH . '\cmake\OpenSSL\OpenSSLConfig.cmake', - '/set\(OPENSSL_LIBCRYPTO_DEPENDENCIES .*\)/m', - 'set(OPENSSL_LIBCRYPTO_DEPENDENCIES "${OPENSSL_LIBRARY_DIR}" ws2_32.lib gdi32.lib advapi32.lib crypt32.lib user32.lib)' - ); - } -} diff --git a/src/SPC/builder/windows/library/postgresql_win.php b/src/SPC/builder/windows/library/postgresql_win.php deleted file mode 100644 index 7f708be6..00000000 --- a/src/SPC/builder/windows/library/postgresql_win.php +++ /dev/null @@ -1,27 +0,0 @@ -source_dir . '\pgsql\lib\libpq.lib', BUILD_LIB_PATH . '\libpq.lib'); - copy($this->source_dir . '\pgsql\lib\libpgport.lib', BUILD_LIB_PATH . '\libpgport.lib'); - copy($this->source_dir . '\pgsql\lib\libpgcommon.lib', BUILD_LIB_PATH . '\libpgcommon.lib'); - - // create libpq folder in buildroot/includes/libpq - if (!file_exists(BUILD_INCLUDE_PATH . '\libpq')) { - mkdir(BUILD_INCLUDE_PATH . '\libpq'); - } - - $headerFiles = ['libpq-fe.h', 'postgres_ext.h', 'pg_config_ext.h', 'libpq\libpq-fs.h']; - foreach ($headerFiles as $header) { - copy($this->source_dir . '\pgsql\include\\' . $header, BUILD_INCLUDE_PATH . '\\' . $header); - } - } -} diff --git a/src/SPC/builder/windows/library/pthreads4w.php b/src/SPC/builder/windows/library/pthreads4w.php deleted file mode 100644 index 66707cbb..00000000 --- a/src/SPC/builder/windows/library/pthreads4w.php +++ /dev/null @@ -1,29 +0,0 @@ -cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper( - 'nmake /E /nologo /f Makefile ' . - 'DESTROOT=' . BUILD_ROOT_PATH . ' ' . - 'XCFLAGS="/MT" ' . // no dll - 'EHFLAGS="/I. /DHAVE_CONFIG_H /Os /Ob2 /D__PTW32_STATIC_LIB /D__PTW32_BUILD_INLINED"' - ), - 'pthreadVC3.inlined_static_stamp' - ); - copy($this->source_dir . '\libpthreadVC3.lib', BUILD_LIB_PATH . '\libpthreadVC3.lib'); - copy($this->source_dir . '\_ptw32.h', BUILD_INCLUDE_PATH . '\_ptw32.h'); - copy($this->source_dir . '\pthread.h', BUILD_INCLUDE_PATH . '\pthread.h'); - copy($this->source_dir . '\sched.h', BUILD_INCLUDE_PATH . '\sched.h'); - copy($this->source_dir . '\semaphore.h', BUILD_INCLUDE_PATH . '\semaphore.h'); - } -} diff --git a/src/SPC/builder/windows/library/qdbm.php b/src/SPC/builder/windows/library/qdbm.php deleted file mode 100644 index 67617b34..00000000 --- a/src/SPC/builder/windows/library/qdbm.php +++ /dev/null @@ -1,24 +0,0 @@ -cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('nmake'), - '/f VCMakefile' - ); - copy($this->source_dir . '\qdbm_a.lib', BUILD_LIB_PATH . '\qdbm_a.lib'); - copy($this->source_dir . '\depot.h', BUILD_INCLUDE_PATH . '\depot.h'); - // FileSystem::copyDir($this->source_dir . '\include\curl', BUILD_INCLUDE_PATH . '\curl'); - } -} diff --git a/src/SPC/builder/windows/library/sqlite.php b/src/SPC/builder/windows/library/sqlite.php deleted file mode 100644 index 096c1e97..00000000 --- a/src/SPC/builder/windows/library/sqlite.php +++ /dev/null @@ -1,21 +0,0 @@ -source_dir . '/Makefile'); - return true; - } - - protected function build(): void - { - cmd()->cd($this->source_dir)->execWithWrapper($this->builder->makeSimpleWrapper('nmake'), 'PREFIX=' . BUILD_ROOT_PATH . ' install-static'); - } -} diff --git a/src/SPC/builder/windows/library/xz.php b/src/SPC/builder/windows/library/xz.php deleted file mode 100644 index a48df52d..00000000 --- a/src/SPC/builder/windows/library/xz.php +++ /dev/null @@ -1,39 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - - // copy liblzma.lib to liblzma_a.lib - copy(BUILD_LIB_PATH . '/lzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib'); - // patch lzma.h - FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '/lzma.h', 'defined(LZMA_API_STATIC)', 'defined(_WIN32)'); - } -} diff --git a/src/SPC/builder/windows/library/zlib.php b/src/SPC/builder/windows/library/zlib.php deleted file mode 100644 index a5fd346b..00000000 --- a/src/SPC/builder/windows/library/zlib.php +++ /dev/null @@ -1,54 +0,0 @@ -source_dir . '\build'); - - // start build - cmd()->cd($this->source_dir) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - '-B build ' . - '-A x64 ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . - '-DCMAKE_BUILD_TYPE=Release ' . - '-DBUILD_SHARED_LIBS=OFF ' . - '-DSKIP_INSTALL_FILES=ON ' . - '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' - ) - ->execWithWrapper( - $this->builder->makeSimpleWrapper('cmake'), - "--build build --config Release --target install -j{$this->builder->concurrency}" - ); - $detect_list = [ - 'zlibstatic.lib', - 'zs.lib', - 'libzs.lib', - 'libz.lib', - ]; - foreach ($detect_list as $item) { - if (file_exists(BUILD_LIB_PATH . '\\' . $item)) { - FileSystem::copy(BUILD_LIB_PATH . '\\' . $item, BUILD_LIB_PATH . '\zlib_a.lib'); - FileSystem::copy(BUILD_LIB_PATH . '\\' . $item, BUILD_LIB_PATH . '\zlibstatic.lib'); - break; - } - } - FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '\bin\zlib.dll'); - FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\zlib.lib'); - FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\libz.dll'); - FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\libz.lib'); - FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\z.lib'); - FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\z.dll'); - } -} diff --git a/src/SPC/command/BaseCommand.php b/src/SPC/command/BaseCommand.php deleted file mode 100644 index 745dbe28..00000000 --- a/src/SPC/command/BaseCommand.php +++ /dev/null @@ -1,213 +0,0 @@ -addOption('debug', null, null, 'Enable debug mode'); - $this->addOption('no-motd', null, null, 'Disable motd'); - $this->addOption('preserve-log', null, null, 'Preserve log files, do not delete them on initialized'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - if ($input->getOption('no-motd')) { - $this->no_motd = true; - } - - set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) { - $tips = [ - E_WARNING => ['PHP Warning: ', 'warning'], - E_NOTICE => ['PHP Notice: ', 'notice'], - E_USER_ERROR => ['PHP Error: ', 'error'], - E_USER_WARNING => ['PHP Warning: ', 'warning'], - E_USER_NOTICE => ['PHP Notice: ', 'notice'], - E_RECOVERABLE_ERROR => ['PHP Recoverable Error: ', 'error'], - E_DEPRECATED => ['PHP Deprecated: ', 'notice'], - E_USER_DEPRECATED => ['PHP User Deprecated: ', 'notice'], - ]; - $level_tip = $tips[$error_no] ?? ['PHP Unknown: ', 'error']; - $error = $level_tip[0] . $error_msg . ' in ' . $error_file . ' on ' . $error_line; - logger()->{$level_tip[1]}($error); - // 如果 return false 则错误会继续递交给 PHP 标准错误处理 - return true; - }); - $version = ConsoleApplication::VERSION; - if (!$this->no_motd) { - echo " _ _ _ _ - ___| |_ __ _| |_(_) ___ _ __ | |__ _ __ -/ __| __/ _` | __| |/ __|____| '_ \\| '_ \\| '_ \\ -\\__ \\ || (_| | |_| | (_|_____| |_) | | | | |_) | -|___/\\__\\__,_|\\__|_|\\___| | .__/|_| |_| .__/ v{$version} - |_| |_| -"; - } - } - - abstract public function handle(): int; - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $this->input = $input; - $this->output = $output; - - // init log - $this->initLogFiles(); - - // init logger - $this->initConsoleLogger(); - - // load attribute maps - AttributeMapper::init(); - - // init windows fallback - $this->initWindowsPromptFallback($input, $output); - - // init GlobalEnv - if (!$this instanceof BuildCommand) { - GlobalEnvManager::init(); - f_putenv('SPC_SKIP_TOOLCHAIN_CHECK=yes'); - } - - try { - // show raw argv list for logger()->debug - logger()->debug('argv: ' . implode(' ', $_SERVER['argv'])); - return $this->handle(); - } /* @noinspection PhpRedundantCatchClauseInspection */ catch (SPCException $e) { - // Handle SPCException and log it - ExceptionHandler::handleSPCException($e); - return static::FAILURE; - } catch (\Throwable $e) { - // Handle any other exceptions - ExceptionHandler::handleDefaultException($e); - return static::FAILURE; - } - } - - protected function getOption(string $name): mixed - { - return $this->input->getOption($name); - } - - protected function getArgument(string $name): mixed - { - return $this->input->getArgument($name); - } - - protected function logWithResult(bool $result, string $success_msg, string $fail_msg): int - { - if ($result) { - logger()->info($success_msg); - return static::SUCCESS; - } - logger()->error($fail_msg); - return static::FAILURE; - } - - /** - * Parse extension list from string, replace alias and filter internal extensions. - * - * @param array|string $ext_list Extension string list, e.g. "mbstring,posix,sockets" or array - */ - protected function parseExtensionList(array|string $ext_list): array - { - // replace alias - $ls = array_map(function ($x) { - $lower = strtolower(trim($x)); - if (isset(SPC_EXTENSION_ALIAS[$lower])) { - logger()->debug("Extension [{$lower}] is an alias of [" . SPC_EXTENSION_ALIAS[$lower] . '], it will be replaced.'); - return SPC_EXTENSION_ALIAS[$lower]; - } - return $lower; - }, is_array($ext_list) ? $ext_list : array_filter(explode(',', $ext_list))); - - // filter internals - return array_values(array_filter($ls, function ($x) { - if (in_array($x, SPC_INTERNAL_EXTENSIONS)) { - logger()->debug("Extension [{$x}] is an builtin extension, it will be ignored."); - return false; - } - return true; - })); - } - - /** - * Initialize spc log files. - */ - private function initLogFiles(): void - { - $log_dir = SPC_LOGS_DIR; - if (!file_exists($log_dir)) { - mkdir($log_dir, 0755, true); - } elseif (!$this->getOption('preserve-log')) { - // Clean up old log files - $files = glob($log_dir . '/*.log'); - foreach ($files as $file) { - if (is_file($file)) { - unlink($file); - } - } - } - } - - /** - * Initialize console logger. - */ - private function initConsoleLogger(): void - { - global $ob_logger; - if ($this->input->getOption('debug') || $this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $ob_logger = new ConsoleLogger(LogLevel::DEBUG, decorated: !$this->input->getOption('no-ansi')); - define('DEBUG_MODE', true); - } else { - $ob_logger = new ConsoleLogger(decorated: !$this->input->getOption('no-ansi')); - } - $log_file_fd = fopen(SPC_OUTPUT_LOG, 'a'); - $ob_logger->addLogCallback(function ($level, $output) use ($log_file_fd) { - if ($log_file_fd) { - fwrite($log_file_fd, strip_ansi_colors($output) . "\n"); - } - return true; - }); - } - - /** - * Initialize Windows prompt fallback for laravel-prompts. - */ - private function initWindowsPromptFallback(InputInterface $input, OutputInterface $output): void - { - Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows'); - ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) { - $helper = new QuestionHelper(); - $case = $prompt->default ? ' [Y/n] ' : ' [y/N] '; - $question = new ConfirmationQuestion($prompt->label . $case, $prompt->default); - return $helper->ask($input, $output, $question); - }); - } -} diff --git a/src/SPC/command/BuildCommand.php b/src/SPC/command/BuildCommand.php deleted file mode 100644 index 0285c333..00000000 --- a/src/SPC/command/BuildCommand.php +++ /dev/null @@ -1,24 +0,0 @@ -addOption('with-sdk-binary-dir', null, InputOption::VALUE_REQUIRED, 'path to binary sdk'); - $this->addOption('vs-ver', null, InputOption::VALUE_REQUIRED, 'vs version, e.g. "17" for Visual Studio 2022'); - } - - $this->addOption('with-clean', null, null, 'fresh build, remove `source` and `buildroot` dir before build'); - $this->addOption('rebuild', 'r', null, 'Delete old build and rebuild'); - $this->addOption('enable-zts', null, null, 'enable ZTS support'); - } -} diff --git a/src/SPC/command/BuildLibsCommand.php b/src/SPC/command/BuildLibsCommand.php deleted file mode 100644 index de1f1bba..00000000 --- a/src/SPC/command/BuildLibsCommand.php +++ /dev/null @@ -1,71 +0,0 @@ -addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated'); - $this->addOption('clean', null, null, 'Clean old download cache and source before fetch'); - $this->addOption('all', 'A', null, 'Build all libs that static-php-cli needed'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - // --all 等于 "" - if ($input->getOption('all')) { - $input->setArgument('libraries', ''); - } - parent::initialize($input, $output); - } - - public function handle(): int - { - // 从参数中获取要编译的 libraries,并转换为数组 - $libraries = array_map('trim', array_filter(explode(',', $this->getArgument('libraries')))); - - // 删除旧资源 - if ($this->getOption('clean')) { - logger()->warning('You are doing some operations that not recoverable: removing directories below'); - logger()->warning(BUILD_ROOT_PATH); - logger()->warning('I will remove these dir after you press [Enter] !'); - echo 'Confirm operation? [Yes] '; - fgets(STDIN); - if (PHP_OS_FAMILY === 'Windows') { - f_passthru('rmdir /s /q ' . BUILD_ROOT_PATH); - } else { - f_passthru('rm -rf ' . BUILD_ROOT_PATH); - } - } - - // 构建对象 - $builder = BuilderProvider::makeBuilderByInput($this->input); - // 只编译 library 的情况下,标记 - $builder->setLibsOnly(); - // 编译和检查库完整 - $libraries = DependencyUtil::getLibs($libraries); - $display_libs = array_filter($libraries, fn ($lib) => in_array(Config::getLib($lib, 'type', 'lib'), ['lib', 'package'])); - - logger()->info('Building libraries: ' . implode(',', $display_libs)); - sleep(2); - $builder->proveLibs($libraries); - $builder->validateLibsAndExts(); - $builder->setupLibs(); - - $time = round(microtime(true) - START_TIME, 3); - logger()->info('Build libs complete, used ' . $time . ' s !'); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/BuildPHPCommand.php b/src/SPC/command/BuildPHPCommand.php deleted file mode 100644 index ad884b3b..00000000 --- a/src/SPC/command/BuildPHPCommand.php +++ /dev/null @@ -1,315 +0,0 @@ -addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated'); - $this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', ''); - $this->addOption('build-shared', 'D', InputOption::VALUE_REQUIRED, 'Shared extensions to build, comma separated', ''); - $this->addOption('build-micro', null, null, 'Build micro SAPI'); - $this->addOption('build-cli', null, null, 'Build cli SAPI'); - $this->addOption('build-fpm', null, null, 'Build fpm SAPI (not available on Windows)'); - $this->addOption('build-embed', null, null, 'Build embed SAPI (not available on Windows)'); - $this->addOption('build-frankenphp', null, null, 'Build FrankenPHP SAPI (not available on Windows)'); - $this->addOption('build-cgi', null, null, 'Build cgi SAPI'); - $this->addOption('build-all', null, null, 'Build all SAPI'); - $this->addOption('no-strip', null, null, 'build without strip, keep symbols to debug'); - $this->addOption('disable-opcache-jit', null, null, 'disable opcache jit'); - $this->addOption('with-config-file-path', null, InputOption::VALUE_REQUIRED, 'Set the path in which to look for php.ini', $isWindows ? null : '/usr/local/etc/php'); - $this->addOption('with-config-file-scan-dir', null, InputOption::VALUE_REQUIRED, 'Set the directory to scan for .ini files after reading php.ini', $isWindows ? null : '/usr/local/etc/php/conf.d'); - $this->addOption('with-hardcoded-ini', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Patch PHP source code, inject hardcoded INI'); - $this->addOption('with-micro-fake-cli', null, null, 'Let phpmicro\'s PHP_SAPI use "cli" instead of "micro"'); - $this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs'); - $this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts'); - $this->addOption('with-added-patch', 'P', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Inject patch script outside'); - $this->addOption('without-micro-ext-test', null, null, 'Disable phpmicro with extension test code'); - $this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)'); - $this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)'); - $this->addOption('enable-micro-win32', null, null, 'Enable win32 mode for phpmicro (Windows only)'); - $this->addOption('with-frankenphp-app', null, InputOption::VALUE_REQUIRED, 'Path to a folder to be embedded in FrankenPHP'); - } - - public function handle(): int - { - // transform string to array - $libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs')))); - // transform string to array - $shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared')))); - // transform string to array - $static_extensions = $this->parseExtensionList($this->getArgument('extensions')); - - // parse rule with options - $rule = $this->parseRules($shared_extensions); - - // check dynamic extension build env - // linux must build with glibc - if (!empty($shared_extensions) && SPCTarget::isStatic()) { - $this->output->writeln('Linux does not support dynamic extension loading with fully static builds, please build with a shared C runtime target!'); - return static::FAILURE; - } - $static_and_shared = array_intersect($static_extensions, $shared_extensions); - if (!empty($static_and_shared)) { - $this->output->writeln('Building extensions [' . implode(',', $static_and_shared) . '] as both static and shared, tests may not be accurate or fail.'); - } - - if ($rule === BUILD_TARGET_NONE) { - $this->output->writeln('Please add at least one build SAPI!'); - $this->output->writeln("\t--build-cli\t\tBuild php-cli SAPI"); - $this->output->writeln("\t--build-micro\t\tBuild phpmicro SAPI"); - $this->output->writeln("\t--build-fpm\t\tBuild php-fpm SAPI"); - $this->output->writeln("\t--build-embed\t\tBuild embed SAPI/libphp"); - $this->output->writeln("\t--build-frankenphp\tBuild FrankenPHP SAPI/libphp"); - $this->output->writeln("\t--build-all\t\tBuild all SAPI: cli, micro, fpm, embed, frankenphp"); - return static::FAILURE; - } - if ($rule === BUILD_TARGET_ALL) { - logger()->warning('--build-all option makes `--no-strip` always true, be aware!'); - } - if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO && $this->getOption('with-micro-logo')) { - $logo = $this->getOption('with-micro-logo'); - if (!file_exists($logo)) { - logger()->error('Logo file ' . $logo . ' not exist !'); - return static::FAILURE; - } - } - - // Check upx - $suffix = PHP_OS_FAMILY === 'Windows' ? '.exe' : ''; - if ($this->getOption('with-upx-pack')) { - // only available for linux for now - if (!in_array(PHP_OS_FAMILY, ['Linux', 'Windows'])) { - logger()->error('UPX is only available on Linux and Windows!'); - return static::FAILURE; - } - // need to install this manually - if (!file_exists(PKG_ROOT_PATH . '/bin/upx' . $suffix)) { - global $argv; - logger()->error('upx does not exist, please install it first:'); - logger()->error(''); - logger()->error("\t" . $argv[0] . ' install-pkg upx'); - logger()->error(''); - return static::FAILURE; - } - // exclusive with no-strip - if ($this->getOption('no-strip')) { - logger()->warning('--with-upx-pack conflicts with --no-strip, --no-strip won\'t work!'); - } - if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) { - logger()->warning('Some cases micro.sfx cannot be packed via UPX due to dynamic size bug, be aware!'); - } - } - // create builder - $builder = BuilderProvider::makeBuilderByInput($this->input); - $include_suggest_ext = $this->getOption('with-suggested-exts'); - $include_suggest_lib = $this->getOption('with-suggested-libs'); - [$extensions, $libraries, $not_included] = DependencyUtil::getExtsAndLibs(array_merge($static_extensions, $shared_extensions), $libraries, $include_suggest_ext, $include_suggest_lib); - $display_libs = array_filter($libraries, fn ($lib) => in_array(Config::getLib($lib, 'type', 'lib'), ['lib', 'package'])); - - // separate static and shared extensions from $extensions - // filter rule: including shared extensions if they are in $static_extensions or $shared_extensions - $static_extensions = array_filter($extensions, fn ($ext) => !in_array($ext, $shared_extensions) || in_array($ext, $static_extensions)); - - // print info - $indent_texts = [ - 'Build OS' => PHP_OS_FAMILY . ' (' . php_uname('m') . ')', - 'Build Target' => getenv('SPC_TARGET'), - 'Build Toolchain' => getenv('SPC_TOOLCHAIN'), - 'Build SAPI' => $builder->getBuildTypeName($rule), - 'Static Extensions (' . count($static_extensions) . ')' => implode(',', $static_extensions), - 'Shared Extensions (' . count($shared_extensions) . ')' => implode(',', $shared_extensions), - 'Libraries (' . count($libraries) . ')' => implode(',', $display_libs), - 'Strip Binaries' => $builder->getOption('no-strip') ? 'no' : 'yes', - 'Enable ZTS' => $builder->getOption('enable-zts') ? 'yes' : 'no', - ]; - if (!empty($shared_extensions) || ($rule & BUILD_TARGET_EMBED)) { - $indent_texts['Build Dev'] = 'yes'; - } - if (!empty($this->input->getOption('with-config-file-path'))) { - $indent_texts['Config File Path'] = $this->input->getOption('with-config-file-path'); - } - if (!empty($this->input->getOption('with-hardcoded-ini'))) { - $indent_texts['Hardcoded INI'] = $this->input->getOption('with-hardcoded-ini'); - } - if ($this->input->getOption('disable-opcache-jit')) { - $indent_texts['Opcache JIT'] = 'disabled'; - } - if ($this->input->getOption('with-upx-pack') && in_array(PHP_OS_FAMILY, ['Linux', 'Windows'])) { - $indent_texts['UPX Pack'] = 'enabled'; - } - - $ver = $builder->getPHPVersionFromArchive() ?: $builder->getPHPVersion(false); - $indent_texts['PHP Version'] = $ver; - - if (!empty($not_included)) { - $indent_texts['Extra Exts (' . count($not_included) . ')'] = implode(', ', $not_included); - } - $this->printFormatInfo($this->getDefinedEnvs(), true); - $this->printFormatInfo($indent_texts); - - // bind extra info to exception handler - ExceptionHandler::bindBuildPhpExtraInfo($indent_texts); - - logger()->notice('Build will start after 2s ...'); - sleep(2); - - // compile libraries - $builder->proveLibs($libraries); - // check extensions - $builder->proveExts($static_extensions, $shared_extensions); - // validate libs and extensions - $builder->validateLibsAndExts(); - - // check some things before building all the things - $builder->checkBeforeBuildPHP($rule); - - // clean builds and sources - if ($this->input->getOption('with-clean')) { - logger()->info('Cleaning source and previous build dir...'); - FileSystem::removeDir(SOURCE_PATH); - FileSystem::removeDir(BUILD_ROOT_PATH); - } - - // build or install libraries - $builder->setupLibs(); - - // Process -I option - $custom_ini = []; - foreach ($this->input->getOption('with-hardcoded-ini') as $value) { - [$source_name, $ini_value] = explode('=', $value, 2); - $custom_ini[$source_name] = $ini_value; - logger()->info('Adding hardcoded INI [' . $source_name . ' = ' . $ini_value . ']'); - } - if (!empty($custom_ini)) { - SourcePatcher::patchHardcodedINI($custom_ini); - } - - // add static-php-cli.version to main.c, in order to debug php failure more easily - SourcePatcher::patchSPCVersionToPHP($this->getApplication()->getVersion()); - - // clean old modules that may conflict with the new php build - FileSystem::removeDir(BUILD_MODULES_PATH); - // start to build - $builder->buildPHP($rule); - - $builder->testPHP($rule); - - // compile stopwatch :P - $time = round(microtime(true) - START_TIME, 3); - logger()->info(''); - logger()->info(' Build complete, used ' . $time . ' s !'); - logger()->info(''); - - // ---------- When using bin/spc-alpine-docker, the build root path is different from the host system ---------- - $build_root_path = BUILD_ROOT_PATH; - $fixed = ''; - $build_root_path = get_display_path($build_root_path); - if (!empty(getenv('SPC_FIX_DEPLOY_ROOT'))) { - $fixed = ' (host system)'; - } - if (($rule & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { - $win_suffix = PHP_OS_FAMILY === 'Windows' ? '.exe' : ''; - $path = FileSystem::convertPath("{$build_root_path}/bin/php{$win_suffix}"); - logger()->info("Static php binary path{$fixed}: {$path}"); - } - if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) { - $path = FileSystem::convertPath("{$build_root_path}/bin/micro.sfx"); - logger()->info("phpmicro binary path{$fixed}: {$path}"); - } - if (($rule & BUILD_TARGET_FPM) === BUILD_TARGET_FPM && PHP_OS_FAMILY !== 'Windows') { - $path = FileSystem::convertPath("{$build_root_path}/bin/php-fpm"); - logger()->info("Static php-fpm binary path{$fixed}: {$path}"); - } - if (!empty($shared_extensions)) { - foreach ($shared_extensions as $ext) { - $path = FileSystem::convertPath("{$build_root_path}/modules/{$ext}.so"); - if (file_exists(BUILD_MODULES_PATH . "/{$ext}.so")) { - logger()->info("Shared extension [{$ext}] path{$fixed}: {$path}"); - } elseif (Config::getExt($ext, 'type') !== 'addon') { - logger()->warning("Shared extension [{$ext}] not found, please check!"); - } - } - } - - // export metadata - file_put_contents(BUILD_ROOT_PATH . '/build-extensions.json', json_encode($extensions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); - file_put_contents(BUILD_ROOT_PATH . '/build-libraries.json', json_encode($libraries, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); - // export licenses - $dumper = new LicenseDumper(); - $dumper->addExts($extensions)->addLibs($libraries)->addSources(['php-src'])->dump(BUILD_ROOT_PATH . '/license'); - $path = FileSystem::convertPath("{$build_root_path}/license/"); - logger()->info("License path{$fixed}: {$path}"); - return static::SUCCESS; - } - - /** - * Parse build options to rule int. - */ - private function parseRules(array $shared_extensions = []): int - { - $rule = BUILD_TARGET_NONE; - $rule |= ($this->getOption('build-cli') ? BUILD_TARGET_CLI : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-micro') ? BUILD_TARGET_MICRO : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-fpm') ? BUILD_TARGET_FPM : BUILD_TARGET_NONE); - $rule |= $this->getOption('build-embed') || !empty($shared_extensions) ? BUILD_TARGET_EMBED : BUILD_TARGET_NONE; - $rule |= ($this->getOption('build-frankenphp') ? (BUILD_TARGET_FRANKENPHP | BUILD_TARGET_EMBED) : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-cgi') ? BUILD_TARGET_CGI : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE); - return $rule; - } - - private function getDefinedEnvs(): array - { - $envs = GlobalEnvManager::getInitializedEnv(); - $final = []; - foreach ($envs as $env) { - $exp = explode('=', $env, 2); - $final['Init var [' . $exp[0] . ']'] = $exp[1]; - } - return $final; - } - - private function printFormatInfo(array $indent_texts, bool $debug = false): void - { - // calculate space count for every line - $maxlen = 0; - foreach ($indent_texts as $k => $v) { - $maxlen = max(strlen($k), $maxlen); - } - foreach ($indent_texts as $k => $v) { - if (is_string($v)) { - /* @phpstan-ignore-next-line */ - logger()->{$debug ? 'debug' : 'info'}($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow($v)); - } elseif (is_array($v) && !is_assoc_array($v)) { - $first = array_shift($v); - /* @phpstan-ignore-next-line */ - logger()->{$debug ? 'debug' : 'info'}($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow($first)); - foreach ($v as $vs) { - /* @phpstan-ignore-next-line */ - logger()->{$debug ? 'debug' : 'info'}(str_pad('', $maxlen + 2) . ConsoleColor::yellow($vs)); - } - } - } - } -} diff --git a/src/SPC/command/CraftCommand.php b/src/SPC/command/CraftCommand.php deleted file mode 100644 index 6c40133d..00000000 --- a/src/SPC/command/CraftCommand.php +++ /dev/null @@ -1,180 +0,0 @@ -addArgument('craft', null, 'Path to craft.yml file', WORKING_DIR . '/craft.yml'); - } - - public function handle(): int - { - $craft_file = $this->getArgument('craft'); - // Check if the craft.yml file exists - if (!file_exists($craft_file)) { - $this->output->writeln('craft.yml not found, please create one!'); - return static::FAILURE; - } - - // Check if the craft.yml file is valid - try { - $craft = ConfigValidator::validateAndParseCraftFile($craft_file, $this); - if ($craft['debug']) { - $this->input->setOption('debug', true); - } - } catch (ValidationException $e) { - $this->output->writeln('craft.yml parse error: ' . $e->getMessage() . ''); - return static::FAILURE; - } - - // Craft!!! - $this->output->writeln('Crafting...'); - - // apply env - if (isset($craft['extra-env'])) { - $env = $craft['extra-env']; - foreach ($env as $key => $val) { - f_putenv("{$key}={$val}"); - } - } - - $static_extensions = implode(',', $craft['extensions']); - $shared_extensions = implode(',', $craft['shared-extensions'] ?? []); - $libs = implode(',', $craft['libs']); - - // craft doctor - if ($craft['craft-options']['doctor']) { - $retcode = $this->runCommand('doctor', '--auto-fix'); - if ($retcode !== 0) { - $this->output->writeln('craft doctor failed'); - return static::FAILURE; - } - } - // install go and xcaddy for frankenphp - if (in_array('frankenphp', $craft['sapi']) && !GoXcaddy::isInstalled()) { - $retcode = $this->runCommand('install-pkg', 'go-xcaddy'); - if ($retcode !== 0) { - $this->output->writeln('craft go-xcaddy failed'); - return static::FAILURE; - } - } - // install zig if requested - if (ToolchainManager::getToolchainClass() === ZigToolchain::class && !Zig::isInstalled()) { - $retcode = $this->runCommand('install-pkg', 'zig'); - if ($retcode !== 0) { - $this->output->writeln('craft zig failed'); - return static::FAILURE; - } - } - // craft download - if ($craft['craft-options']['download']) { - $sharedAppend = $shared_extensions ? ',' . $shared_extensions : ''; - $args = ["--for-extensions={$static_extensions}{$sharedAppend}"]; - if ($craft['libs'] !== []) { - $args[] = "--for-libs={$libs}"; - } - if (isset($craft['php-version'])) { - $args[] = '--with-php=' . $craft['php-version']; - if (!array_key_exists('ignore-cache-sources', $craft['download-options'])) { - $craft['download-options']['ignore-cache-sources'] = 'php-src'; - } - } - $this->optionsToArguments($craft['download-options'], $args); - $retcode = $this->runCommand('download', ...$args); - if ($retcode !== 0) { - $this->output->writeln('craft download failed'); - return static::FAILURE; - } - } - - // craft build - if ($craft['craft-options']['build']) { - $args = [$static_extensions, "--with-libs={$libs}", "--build-shared={$shared_extensions}", ...array_map(fn ($x) => "--build-{$x}", $craft['sapi'])]; - $this->optionsToArguments($craft['build-options'], $args); - $retcode = $this->runCommand('build', ...$args); - if ($retcode !== 0) { - $this->output->writeln('craft build failed'); - return static::FAILURE; - } - } - - return 0; - } - - public function processLogCallback($type, $buffer): void - { - if ($type === Process::ERR) { - fwrite(STDERR, $buffer); - } else { - fwrite(STDOUT, $buffer); - } - } - - private function runCommand(string $cmd, ...$args): int - { - global $argv; - if ($this->getOption('debug')) { - array_unshift($args, '--debug'); - } - array_unshift($args, '--preserve-log'); - $prefix = PHP_SAPI === 'cli' ? [PHP_BINARY, $argv[0]] : [$argv[0]]; - - $env = getenv(); - $process = new Process([...$prefix, $cmd, '--no-motd', ...$args], env: $env, timeout: null); - - if (PHP_OS_FAMILY === 'Windows') { - sapi_windows_set_ctrl_handler(function () use ($process) { - if ($process->isRunning()) { - $process->signal(-1073741510); - } - }); - } elseif (extension_loaded('pcntl')) { - pcntl_signal(SIGINT, function () use ($process) { - /* @noinspection PhpComposerExtensionStubsInspection */ - $process->signal(SIGINT); - }); - } else { - logger()->debug('You have not enabled `pcntl` extension, cannot prevent download file corruption when Ctrl+C'); - } - // $process->setTty(true); - $process->run([$this, 'processLogCallback']); - return $process->getExitCode(); - } - - private function optionsToArguments(array $options, array &$args): void - { - foreach ($options as $option => $val) { - if ((is_bool($val) && $val) || $val === null) { - $args[] = "--{$option}"; - - continue; - } - if (is_string($val)) { - $args[] = "--{$option}={$val}"; - - continue; - } - if (is_array($val)) { - foreach ($val as $v) { - if (is_string($v)) { - $args[] = "--{$option}={$v}"; - } - } - } - } - } -} diff --git a/src/SPC/command/DeleteDownloadCommand.php b/src/SPC/command/DeleteDownloadCommand.php deleted file mode 100644 index 82dd62c4..00000000 --- a/src/SPC/command/DeleteDownloadCommand.php +++ /dev/null @@ -1,81 +0,0 @@ -addArgument('sources', InputArgument::REQUIRED, 'The sources/packages will be deleted, comma separated'); - $this->addOption('all', 'A', null, 'Delete all downloaded and locked sources/packages'); - $this->addOption('pre-built-only', 'W', null, 'Delete only pre-built sources/packages, not the original ones'); - $this->addOption('source-only', 'S', null, 'Delete only sources, not the pre-built packages'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - if ($input->getOption('all')) { - $input->setArgument('sources', ''); - } - parent::initialize($input, $output); - } - - public function handle(): int - { - // get source list that will be downloaded - $sources = array_map('trim', array_filter(explode(',', $this->getArgument('sources')))); - if (empty($sources)) { - logger()->notice('Removing downloads/ directory ...'); - FileSystem::removeDir(DOWNLOAD_PATH); - logger()->info('Removed downloads/ dir!'); - return static::SUCCESS; - } - $chosen_sources = $sources; - - $deleted_sources = []; - foreach ($chosen_sources as $source) { - $source = trim($source); - if (LockFile::get($source) && !$this->getOption('pre-built-only')) { - $deleted_sources[] = $source; - } - if (LockFile::get(Downloader::getPreBuiltLockName($source)) && !$this->getOption('source-only')) { - $deleted_sources[] = Downloader::getPreBuiltLockName($source); - } - } - - foreach ($deleted_sources as $lock_name) { - $lock = LockFile::get($lock_name); - // remove download file/dir if exists - if ($lock['source_type'] === SPC_SOURCE_ARCHIVE) { - if (file_exists($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock['filename']))) { - logger()->info('Deleting file ' . $path); - unlink($path); - } else { - logger()->warning("Source/Package [{$lock_name}] file not found, skip deleting file."); - } - } else { - if (is_dir($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock['dirname']))) { - logger()->info('Deleting dir ' . $path); - FileSystem::removeDir($path); - } else { - logger()->warning("Source/Package [{$lock_name}] directory not found, skip deleting dir."); - } - } - // remove locked sources - LockFile::put($lock_name, null); - } - logger()->info('Delete success!'); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/DoctorCommand.php b/src/SPC/command/DoctorCommand.php deleted file mode 100644 index 77580b40..00000000 --- a/src/SPC/command/DoctorCommand.php +++ /dev/null @@ -1,95 +0,0 @@ -addOption('auto-fix', null, InputOption::VALUE_OPTIONAL, 'Automatically fix failed items (if possible)', false); - } - - public function handle(): int - { - $fix_policy = match ($this->input->getOption('auto-fix')) { - 'never' => FIX_POLICY_DIE, - true, null => FIX_POLICY_AUTOFIX, - default => FIX_POLICY_PROMPT, - }; - $fix_map = AttributeMapper::getDoctorFixMap(); - - foreach (DoctorHandler::getValidCheckList() as $check) { - // output - $this->output->write("Checking {$check->item_name} ... "); - - // null => skipped - if (($result = call_user_func($check->callback)) === null) { - $this->output->writeln('skipped'); - continue; - } - // invalid return value => skipped - if (!$result instanceof CheckResult) { - $this->output->writeln('Skipped due to invalid return value'); - continue; - } - // true => OK - if ($result->isOK()) { - /* @phpstan-ignore-next-line */ - $this->output->writeln($result->getMessage() ?? (string) ConsoleColor::green('✓')); - continue; - } - - // Failed => output error message - $this->output->writeln('' . $result->getMessage() . ''); - // If the result is not fixable, fail immediately - if ($result->getFixItem() === '') { - $this->output->writeln('This check item can not be fixed !'); - return static::FAILURE; - } - if (!isset($fix_map[$result->getFixItem()])) { - $this->output->writeln("Internal error: Unknown fix item: {$result->getFixItem()}"); - return static::FAILURE; - } - - // prompt for fix - if ($fix_policy === FIX_POLICY_PROMPT) { - if (!confirm('Do you want to fix it?')) { - $this->output->writeln('You canceled fix.'); - return static::FAILURE; - } - if (DoctorHandler::emitFix($this->output, $result)) { - $this->output->writeln('Fix applied successfully!'); - } else { - $this->output->writeln('Failed to apply fix!'); - return static::FAILURE; - } - } - - // auto fix - if ($fix_policy === FIX_POLICY_AUTOFIX) { - $this->output->writeln('Automatically fixing ' . $result->getFixItem() . ' ...'); - if (DoctorHandler::emitFix($this->output, $result)) { - $this->output->writeln('Fix applied successfully!'); - } else { - $this->output->writeln('Failed to apply fix!'); - return static::FAILURE; - } - } - } - - $this->output->writeln('Doctor check complete !'); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/DownloadCommand.php b/src/SPC/command/DownloadCommand.php deleted file mode 100644 index b7f2b078..00000000 --- a/src/SPC/command/DownloadCommand.php +++ /dev/null @@ -1,365 +0,0 @@ -addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated'); - $this->addOption('shallow-clone', null, null, 'Clone shallow'); - $this->addOption('with-openssl11', null, null, 'Use openssl 1.1'); - $this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.5)', '8.5'); - $this->addOption('clean', null, null, 'Clean old download cache and source before fetch'); - $this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed'); - $this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"'); - $this->addOption('custom-git', 'G', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source git url, e.g "php-src:master:https://github.com/php/php-src.git"'); - $this->addOption('from-zip', 'Z', InputOption::VALUE_REQUIRED, 'Fetch from zip archive'); - $this->addOption('for-extensions', 'e', InputOption::VALUE_REQUIRED, 'Fetch by extensions, e.g "openssl,mbstring"'); - $this->addOption('for-libs', 'l', InputOption::VALUE_REQUIRED, 'Fetch by libraries, e.g "libcares,openssl,onig"'); - $this->addOption('without-suggestions', null, null, 'Do not fetch suggested sources when using --for-extensions'); - $this->addOption('ignore-cache-sources', null, InputOption::VALUE_OPTIONAL, 'Ignore some source caches, comma separated, e.g "php-src,curl,openssl"', false); - $this->addOption('retry', 'R', InputOption::VALUE_REQUIRED, 'Set retry time when downloading failed (default: 0)', '0'); - $this->addOption('prefer-pre-built', 'P', null, 'Download pre-built libraries when available'); - $this->addOption('no-alt', null, null, 'Do not download alternative sources'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - // mode: --all - if ($input->getOption('all')) { - $input->setArgument('sources', implode(',', array_keys(Config::getSources()))); - parent::initialize($input, $output); - return; - } - // mode: --clean and --from-zip - if ($input->getOption('clean') || $input->getOption('from-zip')) { - $input->setArgument('sources', ''); - parent::initialize($input, $output); - return; - } - // mode: normal - if (!empty($input->getArgument('sources'))) { - $final_sources = array_map('trim', array_filter(explode(',', $input->getArgument('sources')))); - } else { - $final_sources = []; - } - // mode: --for-extensions - if ($for_ext = $input->getOption('for-extensions')) { - $ext = $this->parseExtensionList($for_ext); - $sources = $this->calculateSourcesByExt($ext, !$input->getOption('without-suggestions')); - $final_sources = array_merge($final_sources, array_diff($sources, $final_sources)); - } - // mode: --for-libs - if ($for_lib = $input->getOption('for-libs')) { - $lib = array_map('trim', array_filter(explode(',', $for_lib))); - $sources = $this->calculateSourcesByLib($lib, !$input->getOption('without-suggestions')); - $final_sources = array_merge($final_sources, array_diff($sources, $final_sources)); - } - if (!empty($final_sources)) { - $input->setArgument('sources', implode(',', $final_sources)); - } - parent::initialize($input, $output); - } - - public function handle(): int - { - if ($this->getOption('clean')) { - return $this->_clean(); - } - - // --from-zip - if ($path = $this->getOption('from-zip')) { - return $this->downloadFromZip($path); - } - - // Define PHP major version - $ver = $this->php_major_ver = $this->getOption('with-php'); - define('SPC_BUILD_PHP_VERSION', $ver); - if ($ver !== 'git' && !preg_match('/^\d+\.\d+$/', $ver)) { - // If not git, we need to check the version format - if (!preg_match('/^\d+\.\d+(\.\d+)?$/', $ver)) { - logger()->error("bad version arg: {$ver}, x.y or x.y.z required!"); - return static::FAILURE; - } - } - - // retry - $retry = (int) $this->getOption('retry'); - f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry); - - // Use shallow-clone can reduce git resource download - if ($this->getOption('shallow-clone')) { - define('GIT_SHALLOW_CLONE', true); - } - - // To read config - Config::getSource('openssl'); - - // use openssl 1.1 - if ($this->getOption('with-openssl11')) { - logger()->debug('Using openssl 1.1'); - Config::$source['openssl']['regex'] = '/href="(?openssl-(?1.[^"]+)\.tar\.gz)\"/'; - } - - $chosen_sources = array_map('trim', array_filter(explode(',', $this->getArgument('sources')))); - - $sss = $this->getOption('ignore-cache-sources'); - if ($sss === false) { - // false is no-any-ignores, that is, default. - $force_all = false; - $force_list = []; - } elseif ($sss === null) { - // null means all sources will be ignored, equals to --force-all (but we don't want to add too many options) - $force_all = true; - $force_list = []; - } else { - // ignore some sources - $force_all = false; - $force_list = array_map('trim', array_filter(explode(',', $this->getOption('ignore-cache-sources')))); - } - - if ($this->getOption('all')) { - logger()->notice('Downloading with --all option will take more times to download, we recommend you to download with --for-extensions option !'); - } - - // Process -U options - $custom_urls = []; - foreach ($this->input->getOption('custom-url') as $value) { - [$source_name, $url] = explode(':', $value, 2); - $custom_urls[$source_name] = $url; - } - // Process -G options - $custom_gits = []; - foreach ($this->input->getOption('custom-git') as $value) { - [$source_name, $branch, $url] = explode(':', $value, 3); - $custom_gits[$source_name] = [$branch, $url]; - } - - // If passing --prefer-pre-built option, we need to load pre-built library list from pre-built.json targeted releases - if ($this->getOption('prefer-pre-built')) { - $repo = Config::getPreBuilt('repo'); - $pre_built_libs = Downloader::getLatestGithubRelease($repo, [ - 'repo' => $repo, - 'prefer-stable' => Config::getPreBuilt('prefer-stable'), - ], false); - } else { - $pre_built_libs = []; - } - - // Download them - f_mkdir(DOWNLOAD_PATH); - $cnt = count($chosen_sources); - $ni = 0; - foreach ($chosen_sources as $source) { - ++$ni; - if (isset($custom_urls[$source])) { - $config = Config::getSource($source); - $new_config = [ - 'type' => 'url', - 'url' => $custom_urls[$source], - ]; - if (isset($config['path'])) { - $new_config['path'] = $config['path']; - } - if (isset($config['filename'])) { - $new_config['filename'] = $config['filename']; - } - logger()->info("[{$ni}/{$cnt}] Downloading source {$source} from custom url: {$new_config['url']}"); - Downloader::downloadSource($source, $new_config, true); - } elseif (isset($custom_gits[$source])) { - $config = Config::getSource($source); - $new_config = [ - 'type' => 'git', - 'rev' => $custom_gits[$source][0], - 'url' => $custom_gits[$source][1], - ]; - if (isset($config['path'])) { - $new_config['path'] = $config['path']; - } - logger()->info("[{$ni}/{$cnt}] Downloading source {$source} from custom git: {$new_config['url']}"); - Downloader::downloadSource($source, $new_config, true); - } else { - $config = Config::getSource($source); - // Prefer pre-built, we need to search pre-built library - if ($this->getOption('prefer-pre-built') && ($config['provide-pre-built'] ?? false) === true) { - // We need to replace pattern - $replace = [ - '{name}' => $source, - '{arch}' => arch2gnu(php_uname('m')), - '{os}' => strtolower(PHP_OS_FAMILY), - '{libc}' => SPCTarget::getLibc() ?? 'default', - '{libcver}' => SPCTarget::getLibcVersion() ?? 'default', - ]; - $find = str_replace(array_keys($replace), array_values($replace), Config::getPreBuilt('match-pattern')); - // find filename in asset list - if (($url = $this->findPreBuilt($pre_built_libs, $find)) !== null) { - logger()->info("[{$ni}/{$cnt}] Downloading pre-built content {$source}"); - Downloader::downloadSource($source, ['type' => 'url', 'url' => $url], $force_all || in_array($source, $force_list), SPC_DOWNLOAD_PRE_BUILT); - continue; - } - logger()->warning("Pre-built content not found for {$source}, fallback to source download"); - } - logger()->info("[{$ni}/{$cnt}] Downloading source {$source}"); - try { - Downloader::downloadSource($source, $config, $force_all || in_array($source, $force_list)); - } catch (SPCException $e) { - // if `--no-alt` option is set, we will not download alternative sources - if ($this->getOption('no-alt')) { - throw $e; - } - // if download failed, we will try to download alternative sources - logger()->warning("Download failed: {$e->getMessage()}"); - $alt_sources = Config::getSource($source)['alt'] ?? null; - if ($alt_sources === null) { - logger()->warning("No alternative sources found for {$source}, using default alternative source"); - $alt_config = array_merge($config, Downloader::getDefaultAlternativeSource($source)); - } elseif ($alt_sources === false) { - throw new DownloaderException("No alternative sources found for {$source}, skipping alternative download"); - } else { - logger()->notice("Trying to download alternative sources for {$source}"); - $alt_config = array_merge($config, $alt_sources); - } - Downloader::downloadSource($source, $alt_config, $force_all || in_array($source, $force_list)); - } - } - } - $time = round(microtime(true) - START_TIME, 3); - logger()->info('Download complete, used ' . $time . ' s !'); - return static::SUCCESS; - } - - private function downloadFromZip(string $path): int - { - if (!file_exists($path)) { - logger()->critical('File ' . $path . ' not exist or not a zip archive.'); - return static::FAILURE; - } - // remove old download files first - if (is_dir(DOWNLOAD_PATH)) { - logger()->warning('You are doing some operations that not recoverable: removing directories below'); - logger()->warning(DOWNLOAD_PATH); - logger()->alert('I will remove these dir after 5 seconds !'); - sleep(5); - f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH); - } - // unzip command check - if (PHP_OS_FAMILY !== 'Windows' && !self::findCommand('unzip')) { - $this->output->writeln('Missing unzip command, you need to install it first !'); - $this->output->writeln('You can use "bin/spc doctor" command to check and install required tools'); - return static::FAILURE; - } - // create downloads - if (PHP_OS_FAMILY === 'Windows') { - // Windows TODO - $this->output->writeln('Windows currently does not support --from-zip !'); - return static::FAILURE; - } - $abs_path = realpath($path); - f_passthru('mkdir ' . DOWNLOAD_PATH . ' && cd ' . DOWNLOAD_PATH . ' && unzip ' . escapeshellarg($abs_path)); - - if (!file_exists(LockFile::LOCK_FILE)) { - $this->output->writeln('.lock.json not exist in "downloads/", please run "bin/spc download" first !'); - return static::FAILURE; - } - $this->output->writeln('Extract success'); - return static::SUCCESS; - } - - /** - * Calculate the sources by extensions - * - * @param array $extensions extension list - * @param bool $include_suggests include suggested libs and extensions (default: true) - */ - private function calculateSourcesByExt(array $extensions, bool $include_suggests = true): array - { - [$extensions, $libraries] = $include_suggests ? DependencyUtil::getExtsAndLibs($extensions, [], true, true) : DependencyUtil::getExtsAndLibs($extensions); - $sources = []; - foreach ($extensions as $extension) { - if (Config::getExt($extension, 'type') === 'external') { - $sources[] = Config::getExt($extension, 'source'); - } - } - foreach ($libraries as $library) { - $source = Config::getLib($library, 'source'); - if ($source !== null) { - $sources[] = $source; - } - } - return array_values(array_unique($sources)); - } - - /** - * Calculate the sources by libraries - * - * @param array $libs library list - * @param bool $include_suggests include suggested libs (default: true) - */ - private function calculateSourcesByLib(array $libs, bool $include_suggests = true): array - { - $libs = DependencyUtil::getLibs($libs, $include_suggests); - $sources = []; - foreach ($libs as $library) { - $sources[] = Config::getLib($library, 'source'); - } - return array_values(array_unique($sources)); - } - - /** - * @param array $assets Asset list from GitHub API - * @param string $filename Match file name, e.g. pkg-config-aarch64-darwin.txz - * @return null|string Return the download URL if found, otherwise null - */ - private function findPreBuilt(array $assets, string $filename): ?string - { - logger()->debug("Finding pre-built asset {$filename}"); - foreach ($assets as $asset) { - if ($asset['name'] === $filename) { - return $asset['browser_download_url']; - } - } - return null; - } - - private function _clean(): int - { - logger()->warning('You are doing some operations that not recoverable: removing directories below'); - logger()->warning(SOURCE_PATH); - logger()->warning(DOWNLOAD_PATH); - logger()->warning(BUILD_ROOT_PATH); - logger()->alert('I will remove these dir after 5 seconds !'); - sleep(5); - if (PHP_OS_FAMILY === 'Windows') { - f_passthru('rmdir /s /q ' . SOURCE_PATH); - f_passthru('rmdir /s /q ' . DOWNLOAD_PATH); - f_passthru('rmdir /s /q ' . BUILD_ROOT_PATH); - } else { - f_passthru('rm -rf ' . SOURCE_PATH . '/*'); - f_passthru('rm -rf ' . DOWNLOAD_PATH . '/*'); - f_passthru('rm -rf ' . BUILD_ROOT_PATH . '/*'); - } - return static::FAILURE; - } -} diff --git a/src/SPC/command/DumpExtensionsCommand.php b/src/SPC/command/DumpExtensionsCommand.php deleted file mode 100644 index ffb80a46..00000000 --- a/src/SPC/command/DumpExtensionsCommand.php +++ /dev/null @@ -1,160 +0,0 @@ -addArgument('path', InputArgument::OPTIONAL, 'Path to project root', '.'); - $this->addOption('format', 'F', InputOption::VALUE_REQUIRED, 'Parsed output format', 'default'); - // output zero extension replacement rather than exit as failure - $this->addOption('no-ext-output', 'N', InputOption::VALUE_REQUIRED, 'When no extensions found, output default combination (comma separated)'); - // no dev - $this->addOption('no-dev', null, null, 'Do not include dev dependencies'); - // no spc filter - $this->addOption('no-spc-filter', 'S', null, 'Do not use SPC filter to determine the required extensions'); - } - - public function handle(): int - { - $path = FileSystem::convertPath($this->getArgument('path')); - - $path_installed = FileSystem::convertPath(rtrim($path, '/\\') . '/vendor/composer/installed.json'); - $path_lock = FileSystem::convertPath(rtrim($path, '/\\') . '/composer.lock'); - - $ext_installed = $this->extractFromInstalledJson($path_installed, !$this->getOption('no-dev')); - if ($ext_installed === null) { - if ($this->getOption('format') === 'default') { - $this->output->writeln('vendor/composer/installed.json load failed, skipped'); - } - $ext_installed = []; - } - - $ext_lock = $this->extractFromComposerLock($path_lock, !$this->getOption('no-dev')); - if ($ext_lock === null) { - $this->output->writeln('composer.lock load failed'); - return static::FAILURE; - } - - $extensions = array_unique(array_merge($ext_installed, $ext_lock)); - sort($extensions); - - if (empty($extensions)) { - if ($this->getOption('no-ext-output')) { - $this->outputExtensions(explode(',', $this->getOption('no-ext-output'))); - return static::SUCCESS; - } - $this->output->writeln('No extensions found'); - return static::FAILURE; - } - - $this->outputExtensions($extensions); - return static::SUCCESS; - } - - private function filterExtensions(array $requirements): array - { - return array_map( - fn ($key) => substr($key, 4), - array_keys( - array_filter($requirements, function ($key) { - return str_starts_with($key, 'ext-'); - }, ARRAY_FILTER_USE_KEY) - ) - ); - } - - private function loadJson(string $file): array|bool - { - if (!file_exists($file)) { - return false; - } - - $data = json_decode(file_get_contents($file), true); - if (!$data) { - return false; - } - return $data; - } - - private function extractFromInstalledJson(string $file, bool $include_dev = true): ?array - { - if (!($data = $this->loadJson($file))) { - return null; - } - - $packages = $data['packages'] ?? []; - - if (!$include_dev) { - $packages = array_filter($packages, fn ($package) => !in_array($package['name'], $data['dev-package-names'] ?? [])); - } - - return array_merge( - ...array_map(fn ($x) => isset($x['require']) ? $this->filterExtensions($x['require']) : [], $packages) - ); - } - - private function extractFromComposerLock(string $file, bool $include_dev = true): ?array - { - if (!($data = $this->loadJson($file))) { - return null; - } - - // get packages ext - $packages = $data['packages'] ?? []; - $exts = array_merge( - ...array_map(fn ($package) => $this->filterExtensions($package['require'] ?? []), $packages) - ); - - // get dev packages ext - if ($include_dev) { - $packages = $data['packages-dev'] ?? []; - $exts = array_merge( - $exts, - ...array_map(fn ($package) => $this->filterExtensions($package['require'] ?? []), $packages) - ); - } - - // get require ext - $platform = $data['platform'] ?? []; - $exts = array_merge($exts, $this->filterExtensions($platform)); - - // get require-dev ext - if ($include_dev) { - $platform = $data['platform-dev'] ?? []; - $exts = array_merge($exts, $this->filterExtensions($platform)); - } - - return $exts; - } - - private function outputExtensions(array $extensions): void - { - if (!$this->getOption('no-spc-filter')) { - $extensions = $this->parseExtensionList($extensions); - } - switch ($this->getOption('format')) { - case 'json': - $this->output->writeln(json_encode($extensions, JSON_PRETTY_PRINT)); - break; - case 'text': - $this->output->writeln(implode(',', $extensions)); - break; - default: - $this->output->writeln('Required PHP extensions' . ($this->getOption('no-dev') ? ' (without dev)' : '') . ':'); - $this->output->writeln(implode(',', $extensions)); - } - } -} diff --git a/src/SPC/command/DumpLicenseCommand.php b/src/SPC/command/DumpLicenseCommand.php deleted file mode 100644 index e441fd9e..00000000 --- a/src/SPC/command/DumpLicenseCommand.php +++ /dev/null @@ -1,68 +0,0 @@ -addOption('for-extensions', null, InputOption::VALUE_REQUIRED, 'Dump by extensions and related libraries', null); - $this->addOption('without-php', null, InputOption::VALUE_NONE, 'Dump without php-src'); - $this->addOption('for-libs', null, InputOption::VALUE_REQUIRED, 'Dump by libraries', null); - $this->addOption('for-sources', null, InputOption::VALUE_REQUIRED, 'Dump by original sources (source.json)', null); - $this->addOption('dump-dir', null, InputOption::VALUE_REQUIRED, 'Change dump directory', BUILD_ROOT_PATH . '/license'); - } - - public function handle(): int - { - $dumper = new LicenseDumper(); - if ($this->getOption('for-extensions') !== null) { - // 从参数中获取要编译的 extensions,并转换为数组 - $extensions = $this->parseExtensionList($this->getOption('for-extensions')); - // 根据提供的扩展列表获取依赖库列表并编译 - [$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions); - $dumper->addExts($extensions); - $dumper->addLibs($libraries); - if (!$this->getOption('without-php')) { - $dumper->addSources(['php-src']); - } - $dumper->dump($this->getOption('dump-dir')); - $this->output->writeln('Dump license with extensions: ' . implode(', ', $extensions)); - $this->output->writeln('Dump license with libraries: ' . implode(', ', $libraries)); - $this->output->writeln('Dump license with' . ($this->getOption('without-php') ? 'out' : '') . ' php-src'); - $this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir')); - return static::SUCCESS; - } - if ($this->getOption('for-libs') !== null) { - $libraries = array_map('trim', array_filter(explode(',', $this->getOption('for-libs')))); - $libraries = DependencyUtil::getLibs($libraries); - $dumper->addLibs($libraries); - $dumper->dump($this->getOption('dump-dir')); - return $this->logWithResult( - $dumper->dump($this->getOption('dump-dir')), - 'Dump target dir: ' . $this->getOption('dump-dir'), - 'Dump failed!' - ); - } - if ($this->getOption('for-sources') !== null) { - $sources = array_map('trim', array_filter(explode(',', $this->getOption('for-sources')))); - $dumper->addSources($sources); - $dumper->dump($this->getOption('dump-dir')); - $this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir')); - return static::SUCCESS; - } - $this->output->writeln('You must use one of "--for-extensions=", "--for-libs=", "--for-sources=" to dump'); - return static::FAILURE; - } -} diff --git a/src/SPC/command/ExtractCommand.php b/src/SPC/command/ExtractCommand.php deleted file mode 100644 index c189e0ce..00000000 --- a/src/SPC/command/ExtractCommand.php +++ /dev/null @@ -1,34 +0,0 @@ -addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated'); - $this->addOption('source-only', null, null, 'Only check the source exist, do not check the lib and ext'); - } - - public function handle(): int - { - $sources = array_map('trim', array_filter(explode(',', $this->getArgument('sources')))); - if (empty($sources)) { - $this->output->writeln('sources cannot be empty, at least contain one !'); - return static::FAILURE; - } - SourceManager::initSource(sources: $sources, source_only: $this->getOption('source-only')); - logger()->info('Extract done !'); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/InstallPkgCommand.php b/src/SPC/command/InstallPkgCommand.php deleted file mode 100644 index 13a07888..00000000 --- a/src/SPC/command/InstallPkgCommand.php +++ /dev/null @@ -1,84 +0,0 @@ -addArgument('packages', InputArgument::REQUIRED, 'The packages will be installed, comma separated'); - $this->addOption('shallow-clone', null, null, 'Clone shallow'); - $this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"'); - $this->addOption('no-alt', null, null, 'Do not download alternative packages'); - $this->addOption('skip-extract', null, null, 'Skip package extraction, just download the package archive'); - } - - public function handle(): int - { - // Use shallow-clone can reduce git resource download - if ($this->getOption('shallow-clone')) { - define('GIT_SHALLOW_CLONE', true); - } - - // Process -U options - $custom_urls = []; - foreach ($this->input->getOption('custom-url') as $value) { - [$pkg_name, $url] = explode(':', $value, 2); - $custom_urls[$pkg_name] = $url; - } - - $chosen_pkgs = array_map('trim', array_filter(explode(',', $this->getArgument('packages')))); - - // Download them - f_mkdir(DOWNLOAD_PATH); - $ni = 0; - $cnt = count($chosen_pkgs); - - foreach ($chosen_pkgs as $pkg) { - ++$ni; - if (isset($custom_urls[$pkg])) { - $config = Config::getPkg($pkg); - $new_config = [ - 'type' => 'url', - 'url' => $custom_urls[$pkg], - ]; - if (isset($config['extract'])) { - $new_config['extract'] = $config['extract']; - } - if (isset($config['filename'])) { - $new_config['filename'] = $config['filename']; - } - logger()->info("Installing source {$pkg} from custom url [{$ni}/{$cnt}]"); - PackageManager::installPackage( - $pkg, - $new_config, - allow_alt: false, - extract: !$this->getOption('skip-extract') - ); - } else { - logger()->info("Fetching package {$pkg} [{$ni}/{$cnt}]"); - PackageManager::installPackage( - $pkg, - Config::getPkg($pkg), - allow_alt: !$this->getOption('no-alt'), - extract: !$this->getOption('skip-extract') - ); - } - } - $time = round(microtime(true) - START_TIME, 3); - logger()->info('Install packages complete, used ' . $time . ' s !'); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/MicroCombineCommand.php b/src/SPC/command/MicroCombineCommand.php deleted file mode 100644 index 3987ca78..00000000 --- a/src/SPC/command/MicroCombineCommand.php +++ /dev/null @@ -1,120 +0,0 @@ -addArgument('file', InputArgument::REQUIRED, 'The php or phar file to be combined'); - $this->addOption('with-micro', 'M', InputOption::VALUE_REQUIRED, 'Customize your micro.sfx file'); - $this->addOption('with-ini-set', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'ini to inject into micro.sfx when combining'); - $this->addOption('with-ini-file', 'N', InputOption::VALUE_REQUIRED, 'ini file to inject into micro.sfx when combining'); - $this->addOption('output', 'O', InputOption::VALUE_REQUIRED, 'Customize your output binary file name'); - } - - public function handle(): int - { - // 0. Initialize path variables - $internal = FileSystem::convertPath(BUILD_ROOT_PATH . '/bin/micro.sfx'); - $micro_file = $this->input->getOption('with-micro'); - $file = $this->getArgument('file'); - $ini_set = $this->input->getOption('with-ini-set'); - $ini_file = $this->input->getOption('with-ini-file'); - $target_ini = []; - $output = $this->input->getOption('output') ?? 'my-app'; - $ini_part = ''; - // 1. Make sure specified micro.sfx file exists - if ($micro_file !== null && !file_exists($micro_file)) { - $this->output->writeln('The micro.sfx file you specified is incorrect or does not exist!'); - return static::FAILURE; - } - // 2. Make sure buildroot/bin/micro.sfx exists - if ($micro_file === null && !file_exists($internal)) { - $this->output->writeln('You haven\'t compiled micro.sfx yet, please use "build" command and "--build-micro" to compile phpmicro first!'); - return static::FAILURE; - } - // 3. Use buildroot/bin/micro.sfx - if ($micro_file === null) { - $micro_file = $internal; - } - // 4. Make sure php or phar file exists - if (!is_file(FileSystem::convertPath($file))) { - $this->output->writeln('The file to combine does not exist!'); - return static::FAILURE; - } - // 5. Confirm ini files (ini-set has higher priority) - if ($ini_file !== null) { - // Check file exist first - if (!file_exists($ini_file)) { - $this->output->writeln('The ini file to combine does not exist! (' . $ini_file . ')'); - return static::FAILURE; - } - $arr = parse_ini_file($ini_file); - if ($arr === false) { - $this->output->writeln('Cannot parse ini file'); - return static::FAILURE; - } - $target_ini = array_merge($target_ini, $arr); - } - // 6. Confirm ini sets - if ($ini_set !== []) { - foreach ($ini_set as $item) { - $arr = parse_ini_string($item); - if ($arr === false) { - $this->output->writeln('--with-ini-set parse failed'); - return static::FAILURE; - } - $target_ini = array_merge($target_ini, $arr); - } - } - // 7. Generate ini injection parts - if (!empty($target_ini)) { - $ini_str = $this->encodeINI($target_ini); - logger()->debug('Injecting ini parts: ' . PHP_EOL . $ini_str); - $ini_part = "\xfd\xf6\x69\xe6"; - $ini_part .= pack('N', strlen($ini_str)); - $ini_part .= $ini_str; - } - // 8. Combine ! - $output = FileSystem::isRelativePath($output) ? (WORKING_DIR . '/' . $output) : $output; - $file_target = file_get_contents($micro_file) . $ini_part . file_get_contents($file); - if (PHP_OS_FAMILY === 'Windows' && !str_ends_with(strtolower($output), '.exe')) { - $output .= '.exe'; - } - $output = FileSystem::convertPath($output); - $result = file_put_contents($output, $file_target); - if ($result === false) { - $this->output->writeln('Combine failed.'); - return static::FAILURE; - } - // 9. chmod +x - chmod($output, 0755); - $this->output->writeln('Combine success! Binary file: ' . $output . ''); - return static::SUCCESS; - } - - private function encodeINI(array $array): string - { - $res = []; - foreach ($array as $key => $val) { - if (is_array($val)) { - $res[] = "[{$key}]"; - foreach ($val as $skey => $sval) { - $res[] = "{$skey}=" . (is_numeric($sval) ? $sval : '"' . $sval . '"'); - } - } else { - $res[] = "{$key}=" . (is_numeric($val) ? $val : '"' . $val . '"'); - } - } - return implode("\n", $res); - } -} diff --git a/src/SPC/command/SPCConfigCommand.php b/src/SPC/command/SPCConfigCommand.php deleted file mode 100644 index 5e21c9a1..00000000 --- a/src/SPC/command/SPCConfigCommand.php +++ /dev/null @@ -1,55 +0,0 @@ -addArgument('extensions', InputArgument::OPTIONAL, 'The extensions will be compiled, comma separated'); - $this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', ''); - $this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs'); - $this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts'); - $this->addOption('includes', null, null, 'Add additional include path'); - $this->addOption('libs', null, null, 'Add additional libs path'); - $this->addOption('libs-only-deps', null, null, 'Output dependent libraries with -l prefix'); - $this->addOption('absolute-libs', null, null, 'Output absolute paths for libraries'); - $this->addOption('no-php', null, null, 'Do not link to PHP library'); - } - - public function handle(): int - { - // transform string to array - $libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs')))); - // transform string to array - $extensions = $this->getArgument('extensions') ? $this->parseExtensionList($this->getArgument('extensions')) : []; - $include_suggest_ext = $this->getOption('with-suggested-exts'); - $include_suggest_lib = $this->getOption('with-suggested-libs'); - - $util = new SPCConfigUtil(options: [ - 'no_php' => $this->getOption('no-php'), - 'libs_only_deps' => $this->getOption('libs-only-deps'), - 'absolute_libs' => $this->getOption('absolute-libs'), - ]); - $config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); - - $this->output->writeln(match (true) { - $this->getOption('includes') => $config['cflags'], - $this->getOption('libs-only-deps') => $config['libs'], - $this->getOption('libs') => "{$config['ldflags']} {$config['libs']}", - default => "{$config['cflags']} {$config['ldflags']} {$config['libs']}", - }); - - return 0; - } -} diff --git a/src/SPC/command/SwitchPhpVersionCommand.php b/src/SPC/command/SwitchPhpVersionCommand.php deleted file mode 100644 index 04a31a75..00000000 --- a/src/SPC/command/SwitchPhpVersionCommand.php +++ /dev/null @@ -1,65 +0,0 @@ -addArgument( - 'php-major-version', - InputArgument::REQUIRED, - 'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5)', - null, - fn () => ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] - ); - $this->no_motd = true; - - $this->addOption('retry', 'R', InputOption::VALUE_REQUIRED, 'Set retry time when downloading failed (default: 0)', '0'); - } - - public function handle(): int - { - $php_ver = $this->input->getArgument('php-major-version'); - if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'])) { - // match x.y.z - preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches); - if (!$matches) { - $this->output->writeln('Invalid PHP version ' . $php_ver . ' !'); - return static::FAILURE; - } - } - - if (LockFile::isLockFileExists('php-src')) { - $this->output->writeln('Removing old PHP source...'); - LockFile::put('php-src', null); - } - - // Download new PHP source - $this->output->writeln('Downloading PHP source...'); - define('SPC_BUILD_PHP_VERSION', $php_ver); - - // retry - $retry = intval($this->getOption('retry')); - f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry); - - Downloader::downloadSource('php-src', Config::getSource('php-src')); - - // Remove source/php-src dir - FileSystem::removeDir(SOURCE_PATH . '/php-src'); - - $this->output->writeln('Switched to PHP ' . $php_ver . ' successfully!'); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/AllExtCommand.php b/src/SPC/command/dev/AllExtCommand.php deleted file mode 100644 index 04085778..00000000 --- a/src/SPC/command/dev/AllExtCommand.php +++ /dev/null @@ -1,88 +0,0 @@ -addArgument('extensions', InputArgument::OPTIONAL, 'List of extensions that will be displayed, comma separated'); - $this->addOption( - 'columns', - null, - InputOption::VALUE_REQUIRED, - 'List of columns that will be displayed, comma separated (lib-depends, lib-suggests, ext-depends, ext-suggests, unix-only)', - 'lib-depends,lib-suggests,ext-depends,ext-suggests,unix-only' - ); - } - - public function handle(): int - { - $extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions') ?? ''))); - $columns = array_map('trim', array_filter(explode(',', $this->getOption('columns')))); - - foreach ($columns as $column) { - if (!in_array($column, ['lib-depends', 'lib-suggests', 'ext-depends', 'ext-suggests', 'unix-only', 'type'])) { - $this->output->writeln('Column name [' . $column . '] is not valid.'); - $this->output->writeln('Available column name: lib-depends, lib-suggests, ext-depends, ext-suggests, unix-only, type'); - return static::FAILURE; - } - } - array_unshift($columns, 'name'); - - $style = new SymfonyStyle($this->input, $this->output); - $style->writeln($extensions ? 'Available extensions:' : 'Extensions:'); - - $data = []; - foreach (Config::getExts() as $extension => $details) { - if ($extensions !== [] && !\in_array($extension, $extensions, true)) { - continue; - } - - try { - [, $libraries, $not_included] = DependencyUtil::getExtsAndLibs([$extension]); - } catch (WrongUsageException) { - $libraries = $not_included = []; - } - - $lib_suggests = Config::getExt($extension, 'lib-suggests', []); - $ext_suggests = Config::getExt($extension, 'ext-suggests', []); - - $row = []; - foreach ($columns as $column) { - $row[] = match ($column) { - 'name' => $extension, - 'type' => Config::getExt($extension, 'type'), - 'lib-depends' => implode(', ', $libraries), - 'lib-suggests' => implode(', ', $lib_suggests), - 'ext-depends' => implode(',', $not_included), - 'ext-suggests' => implode(', ', $ext_suggests), - 'unix-only' => Config::getExt($extension, 'unix-only', false) ? 'true' : 'false', - default => '', - }; - } - $data[] = $row; - } - - if ($data === []) { - $style->warning('Unknown extension selected: ' . implode(',', $extensions)); - } else { - $func = PHP_OS_FAMILY === 'Windows' ? [$style, 'table'] : '\Laravel\Prompts\table'; - call_user_func($func, $columns, $data); - } - - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/EnvCommand.php b/src/SPC/command/dev/EnvCommand.php deleted file mode 100644 index d5a0cec3..00000000 --- a/src/SPC/command/dev/EnvCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -addArgument('env', InputArgument::REQUIRED, 'The environment variable to show, if not set, all will be shown'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - $this->no_motd = true; - parent::initialize($input, $output); - } - - public function handle(): int - { - $env = $this->getArgument('env'); - if (($val = getenv($env)) === false) { - $this->output->writeln("Environment variable '{$env}' is not set."); - return static::FAILURE; - } - $this->output->writeln("{$val}"); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/ExtVerCommand.php b/src/SPC/command/dev/ExtVerCommand.php deleted file mode 100644 index 3154a6bb..00000000 --- a/src/SPC/command/dev/ExtVerCommand.php +++ /dev/null @@ -1,49 +0,0 @@ -addArgument('extension', InputArgument::REQUIRED, 'The library name'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - $this->no_motd = true; - parent::initialize($input, $output); - } - - public function handle(): int - { - // Get lib object - $builder = BuilderProvider::makeBuilderByInput($this->input); - - $builder->proveExts([$this->getArgument('extension')], [], true); - - // Check whether lib is extracted - // if (!is_dir(SOURCE_PATH . '/' . $this->getArgument('library'))) { - // $this->output->writeln("Library {$this->getArgument('library')} is not extracted"); - // return static::FAILURE; - // } - - $version = $builder->getExt($this->getArgument('extension'))->getExtVersion(); - if ($version === null) { - $this->output->writeln("Failed to get version of extension {$this->getArgument('extension')}"); - return static::FAILURE; - } - $this->output->writeln("{$version}"); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/GenerateExtDepDocsCommand.php b/src/SPC/command/dev/GenerateExtDepDocsCommand.php deleted file mode 100644 index afa6c9ff..00000000 --- a/src/SPC/command/dev/GenerateExtDepDocsCommand.php +++ /dev/null @@ -1,166 +0,0 @@ - $ext) { - $line_linux = [ - "{$ext_name}", - implode('
', $ext['ext-depends-linux'] ?? $ext['ext-depends-unix'] ?? $ext['ext-depends'] ?? []), - implode('
', $ext['ext-suggests-linux'] ?? $ext['ext-suggests-unix'] ?? $ext['ext-suggests'] ?? []), - implode('
', $ext['lib-depends-linux'] ?? $ext['lib-depends-unix'] ?? $ext['lib-depends'] ?? []), - implode('
', $ext['lib-suggests-linux'] ?? $ext['lib-suggests-unix'] ?? $ext['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_linux, $line_linux); - if ($this->isSupported($ext, 'Linux') && !$this->isEmptyLine($line_linux)) { - $md_lines_linux[] = $line_linux; - } - $line_macos = [ - "{$ext_name}", - implode('
', $ext['ext-depends-macos'] ?? $ext['ext-depends-unix'] ?? $ext['ext-depends'] ?? []), - implode('
', $ext['ext-suggests-macos'] ?? $ext['ext-suggests-unix'] ?? $ext['ext-suggests'] ?? []), - implode('
', $ext['lib-depends-macos'] ?? $ext['lib-depends-unix'] ?? $ext['lib-depends'] ?? []), - implode('
', $ext['lib-suggests-macos'] ?? $ext['lib-suggests-unix'] ?? $ext['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_macos, $line_macos); - if ($this->isSupported($ext, 'macOS') && !$this->isEmptyLine($line_macos)) { - $md_lines_macos[] = $line_macos; - } - $line_windows = [ - "{$ext_name}", - implode('
', $ext['ext-depends-windows'] ?? $ext['ext-depends-win'] ?? $ext['ext-depends'] ?? []), - implode('
', $ext['ext-suggests-windows'] ?? $ext['ext-suggests-win'] ?? $ext['ext-suggests'] ?? []), - implode('
', $ext['lib-depends-windows'] ?? $ext['lib-depends-win'] ?? $ext['lib-depends'] ?? []), - implode('
', $ext['lib-suggests-windows'] ?? $ext['lib-suggests-win'] ?? $ext['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_windows, $line_windows); - if ($this->isSupported($ext, 'Windows') && !$this->isEmptyLine($line_windows)) { - $md_lines_windows[] = $line_windows; - } - $line_freebsd = [ - "{$ext_name}", - implode('
', $ext['ext-depends-freebsd'] ?? $ext['ext-depends-bsd'] ?? $ext['ext-depends-unix'] ?? $ext['ext-depends'] ?? []), - implode('
', $ext['ext-suggests-freebsd'] ?? $ext['ext-suggests-bsd'] ?? $ext['ext-suggests-unix'] ?? $ext['ext-suggests'] ?? []), - implode('
', $ext['lib-depends-freebsd'] ?? $ext['lib-depends-bsd'] ?? $ext['lib-depends-unix'] ?? $ext['lib-depends'] ?? []), - implode('
', $ext['lib-suggests-freebsd'] ?? $ext['lib-suggests-bsd'] ?? $ext['lib-suggests-unix'] ?? $ext['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_freebsd, $line_freebsd); - if ($this->isSupported($ext, 'BSD') && !$this->isEmptyLine($line_freebsd)) { - $md_lines_freebsd[] = $line_freebsd; - } - } - - // Generate markdown - if (!empty($md_lines_linux)) { - $content .= "### Linux\n\n"; - $content .= '| '; - $pads = ['Extension Name', 'Required Extensions', 'Suggested Extensions', 'Required Libraries', 'Suggested Libraries']; - // 生成首行 - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_linux[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - // 生成第二行表格分割符 | --- | --- | --- | --- | --- | - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_linux[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_linux as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_linux[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - if (!empty($md_lines_macos)) { - $content .= "\n\n### macOS\n\n"; - $content .= '| '; - $pads = ['Extension Name', 'Required Extensions', 'Suggested Extensions', 'Required Libraries', 'Suggested Libraries']; - // 生成首行 - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_macos[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - // 生成第二行表格分割符 | --- | --- | --- | --- | --- | - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_macos[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_macos as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_macos[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - if (!empty($md_lines_windows)) { - $content .= "\n\n### Windows\n\n"; - $content .= '| '; - $pads = ['Extension Name', 'Required Extensions', 'Suggested Extensions', 'Required Libraries', 'Suggested Libraries']; - // 生成首行 - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_windows[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - // 生成第二行表格分割符 | --- | --- | --- | --- | --- | - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_windows[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_windows as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_windows[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - if (!empty($md_lines_freebsd)) { - $content .= "\n\n### FreeBSD\n\n"; - $content .= '| '; - $pads = ['Extension Name', 'Required Extensions', 'Suggested Extensions', 'Required Libraries', 'Suggested Libraries']; - // 生成首行 - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_freebsd[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - // 生成第二行表格分割符 | --- | --- | --- | --- | --- | - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_freebsd[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_freebsd as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_freebsd[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - - $this->output->writeln($content); - return static::SUCCESS; - } - - private function applyMaxLen(array &$max, array $lines): void - { - foreach ($max as $k => $v) { - $max[$k] = max($v, strlen($lines[$k])); - } - } - - private function isSupported(array $ext, string $os): bool - { - return !in_array($ext['support'][$os] ?? 'yes', ['no', 'wip']); - } - - private function isEmptyLine(array $line): bool - { - return $line[1] === '' && $line[2] === '' && $line[3] === '' && $line[4] === ''; - } -} diff --git a/src/SPC/command/dev/GenerateExtDocCommand.php b/src/SPC/command/dev/GenerateExtDocCommand.php deleted file mode 100644 index c53e529d..00000000 --- a/src/SPC/command/dev/GenerateExtDocCommand.php +++ /dev/null @@ -1,80 +0,0 @@ - $ext) { - // notes is optional - $name = ($ext['notes'] ?? false) === true ? "[{$ext_name}](./extension-notes#{$ext_name})" : $ext_name; - // calculate max length - $max_name = max($max_name, strlen($name)); - - // linux - $linux = match ($ext['support']['Linux'] ?? 'yes') { - 'wip' => '', - default => $ext['support']['Linux'] ?? 'yes', - }; - $max_linux = max($max_linux, strlen($linux)); - - // macos - $macos = match ($ext['support']['Darwin'] ?? 'yes') { - 'wip' => '', - default => $ext['support']['Darwin'] ?? 'yes', - }; - $max_macos = max($max_macos, strlen($macos)); - - // freebsd - $freebsd = match ($ext['support']['BSD'] ?? 'yes') { - 'wip' => '', - default => $ext['support']['BSD'] ?? 'yes', - }; - $max_freebsd = max($max_freebsd, strlen($freebsd)); - - // windows - $windows = match ($ext['support']['Windows'] ?? 'yes') { - 'wip' => '', - default => $ext['support']['Windows'] ?? 'yes', - }; - $max_windows = max($max_windows, strlen($windows)); - $md_lines[] = [ - $name, - $linux, - $macos, - $freebsd, - $windows, - ]; - } - - // generate markdown - $md = '| ' . str_pad('Extension Name', $max_name) . ' | ' . str_pad('Linux', $max_linux) . ' | ' . str_pad('macOS', $max_macos) . ' | ' . str_pad('FreeBSD', $max_freebsd) . ' | ' . str_pad('Windows', $max_windows) . ' |' . PHP_EOL; - $md .= '| ' . str_repeat('-', $max_name) . ' | ' . str_repeat('-', $max_linux) . ' | ' . str_repeat('-', $max_macos) . ' | ' . str_repeat('-', $max_freebsd) . ' | ' . str_repeat('-', $max_windows) . ' |' . PHP_EOL; - foreach ($md_lines as $line) { - $md .= '| ' . str_pad($line[0], $max_name) . ' | ' . str_pad($line[1], $max_linux) . ' | ' . str_pad($line[2], $max_macos) . ' | ' . str_pad($line[3], $max_freebsd) . ' | ' . str_pad($line[4], $max_windows) . ' |' . PHP_EOL; - } - $this->output->writeln($md); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/GenerateLibDepDocsCommand.php b/src/SPC/command/dev/GenerateLibDepDocsCommand.php deleted file mode 100644 index feee99af..00000000 --- a/src/SPC/command/dev/GenerateLibDepDocsCommand.php +++ /dev/null @@ -1,172 +0,0 @@ -support_lib_list[$os] = []; - $classes = FileSystem::getClassesPsr4( - FileSystem::convertPath(ROOT_DIR . '/src/SPC/builder/' . $os . '/library'), - 'SPC\builder\\' . $os . '\library' - ); - foreach ($classes as $class) { - if (defined($class . '::NAME') && $class::NAME !== 'unknown' && Config::getLib($class::NAME) !== null) { - $this->support_lib_list[$os][$class::NAME] = $class; - } - } - } - - // Get lib.json - $libs = json_decode(FileSystem::readFile(ROOT_DIR . '/config/lib.json'), true); - ConfigValidator::validateLibs($libs); - - // Markdown table needs format, we need to calculate the max length of each column - $content = ''; - - // Calculate table column max length - $max_linux = [0, 20, 19]; - $max_macos = [0, 20, 19]; - $max_windows = [0, 20, 19]; - $max_freebsd = [0, 20, 19]; - - $md_lines_linux = []; - $md_lines_macos = []; - $md_lines_windows = []; - $md_lines_freebsd = []; - - foreach ($libs as $lib_name => $lib) { - $line_linux = [ - "{$lib_name}", - implode('
', $lib['lib-depends-linux'] ?? $lib['lib-depends-unix'] ?? $lib['lib-depends'] ?? []), - implode('
', $lib['lib-suggests-linux'] ?? $lib['lib-suggests-unix'] ?? $lib['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_linux, $line_linux); - if ($this->isSupported($lib_name, 'linux') && !$this->isEmptyLine($line_linux)) { - $md_lines_linux[] = $line_linux; - } - $line_macos = [ - "{$lib_name}", - implode('
', $lib['lib-depends-macos'] ?? $lib['lib-depends-unix'] ?? $lib['lib-depends'] ?? []), - implode('
', $lib['lib-suggests-macos'] ?? $lib['lib-suggests-unix'] ?? $lib['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_macos, $line_macos); - if ($this->isSupported($lib_name, 'macos') && !$this->isEmptyLine($line_macos)) { - $md_lines_macos[] = $line_macos; - } - $line_windows = [ - "{$lib_name}", - implode('
', $lib['lib-depends-windows'] ?? $lib['lib-depends-win'] ?? $lib['lib-depends'] ?? []), - implode('
', $lib['lib-suggests-windows'] ?? $lib['lib-suggests-win'] ?? $lib['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_windows, $line_windows); - if ($this->isSupported($lib_name, 'windows') && !$this->isEmptyLine($line_windows)) { - $md_lines_windows[] = $line_windows; - } - $line_freebsd = [ - "{$lib_name}", - implode('
', $lib['lib-depends-freebsd'] ?? $lib['lib-depends-bsd'] ?? $lib['lib-depends-unix'] ?? $lib['lib-depends'] ?? []), - implode('
', $lib['lib-suggests-freebsd'] ?? $lib['lib-suggests-bsd'] ?? $lib['lib-suggests-unix'] ?? $lib['lib-suggests'] ?? []), - ]; - $this->applyMaxLen($max_freebsd, $line_freebsd); - if ($this->isSupported($lib_name, 'freebsd') && !$this->isEmptyLine($line_freebsd)) { - $md_lines_freebsd[] = $line_freebsd; - } - } - - // Generate markdown - if (!empty($md_lines_linux)) { - $content .= "### Linux\n\n"; - $content .= '| '; - $pads = ['Library Name', 'Required Libraries', 'Suggested Libraries']; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_linux[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_linux[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_linux as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_linux[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - - if (!empty($md_lines_macos)) { - $content .= "### macOS\n\n"; - $content .= '| '; - $pads = ['Library Name', 'Required Libraries', 'Suggested Libraries']; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_macos[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_macos[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_macos as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_macos[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - - if (!empty($md_lines_windows)) { - $content .= "### Windows\n\n"; - $content .= '| '; - $pads = ['Library Name', 'Required Libraries', 'Suggested Libraries']; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_windows[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_windows[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_windows as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_windows[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - - if (!empty($md_lines_freebsd)) { - $content .= "### FreeBSD\n\n"; - $content .= '| '; - $pads = ['Library Name', 'Required Libraries', 'Suggested Libraries']; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad($pad, $max_freebsd[$i]), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - $content .= '| '; - $content .= implode(' | ', array_map(fn ($i, $pad) => str_pad('', $max_freebsd[$i], '-'), array_keys($pads), $pads)); - $content .= ' |' . PHP_EOL; - foreach ($md_lines_freebsd as $line) { - $content .= '| ' . implode(' | ', array_map(fn ($i, $pad) => str_pad($line[$i], $max_freebsd[$i]), array_keys($line), $line)) . ' |' . PHP_EOL; - } - } - - $this->output->writeln($content); - return static::SUCCESS; - } - - private function applyMaxLen(array &$max, array $lines): void - { - foreach ($max as $k => $v) { - $max[$k] = max($v, strlen($lines[$k])); - } - } - - private function isSupported(string $ext_name, string $os): bool - { - if (!in_array($os, ['linux', 'macos', 'freebsd', 'windows'])) { - throw new \InvalidArgumentException('Invalid os: ' . $os); - } - return isset($this->support_lib_list[$os][$ext_name]); - } - - private function isEmptyLine(array $line): bool - { - return $line[1] === '' && $line[2] === ''; - } -} diff --git a/src/SPC/command/dev/LibVerCommand.php b/src/SPC/command/dev/LibVerCommand.php deleted file mode 100644 index 246618e4..00000000 --- a/src/SPC/command/dev/LibVerCommand.php +++ /dev/null @@ -1,64 +0,0 @@ -addArgument('library', InputArgument::REQUIRED, 'The library name'); - } - - public function initialize(InputInterface $input, OutputInterface $output): void - { - $this->no_motd = true; - parent::initialize($input, $output); - } - - public function handle(): int - { - // Get lib object - $builder = BuilderProvider::makeBuilderByInput($this->input); - $builder->setLibsOnly(); - - // check lib name exist in lib.json - try { - Config::getLib($this->getArgument('library')); - } catch (WrongUsageException $e) { - $this->output->writeln("Library {$this->getArgument('library')} is not supported yet"); - return static::FAILURE; - } - - // parse the dependencies - [, $libs] = DependencyUtil::getExtsAndLibs([], [$this->getArgument('library')]); - - $builder->proveLibs($libs); - - // Check whether lib is extracted - if (!is_dir(SOURCE_PATH . '/' . $this->getArgument('library'))) { - $this->output->writeln("Library {$this->getArgument('library')} is not extracted"); - return static::FAILURE; - } - - $version = $builder->getLib($this->getArgument('library'))->getLibVersion(); - if ($version === null) { - $this->output->writeln("Failed to get version of library {$this->getArgument('library')}. The version getter for [{$this->getArgument('library')}] is not implemented."); - return static::FAILURE; - } - $this->output->writeln("{$version}"); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/PackLibCommand.php b/src/SPC/command/dev/PackLibCommand.php deleted file mode 100644 index 9b02fd3f..00000000 --- a/src/SPC/command/dev/PackLibCommand.php +++ /dev/null @@ -1,175 +0,0 @@ -addArgument('library', InputArgument::REQUIRED, 'The library will be compiled'); - $this->addOption('show-libc-ver', null, null); - } - - public function handle(): int - { - $lib_name = $this->getArgument('library'); - $builder = BuilderProvider::makeBuilderByInput($this->input); - $builder->setLibsOnly(); - $libraries = DependencyUtil::getLibs([$lib_name]); - logger()->info('Building libraries: ' . implode(',', $libraries)); - sleep(2); - - FileSystem::createDir(WORKING_DIR . '/dist'); - - $builder->proveLibs($libraries); - $builder->validateLibsAndExts(); - - // before pack, check if the dependency tree contains lib-suggests - foreach ($libraries as $lib) { - if (Config::getLib($lib, 'lib-suggests', []) !== []) { - logger()->critical("The library {$lib} has lib-suggests, packing [{$lib_name}] is not safe, abort !"); - return static::FAILURE; - } - } - - $origin_files = []; - // get pack placehoder defines - $placehoder = get_pack_replace(); - - foreach ($builder->getLibs() as $lib) { - if ($lib->getName() !== $lib_name) { - // other dependencies: install or build, both ok - $lib->setup(); - } else { - // Get lock info - $source = Config::getLib($lib->getName(), 'source'); - if (($lock = LockFile::get($source)) === null || ($lock['lock_as'] === SPC_DOWNLOAD_PRE_BUILT)) { - logger()->critical("The library {$lib->getName()} is downloaded as pre-built, we need to build it instead of installing pre-built."); - return static::FAILURE; - } - // Before build: load buildroot/ directory - $before_buildroot = FileSystem::scanDirFiles(BUILD_ROOT_PATH, relative: true); - // build - $lib->tryBuild(true); - // do something like patching pkg-conf files. - $lib->beforePack(); - // sanity check for libs (check if the libraries are built correctly) - $this->sanityCheckLib($lib); - // After build: load buildroot/ directory, and calculate increase files - $after_buildroot = FileSystem::scanDirFiles(BUILD_ROOT_PATH, relative: true); - $increase_files = array_diff($after_buildroot, $before_buildroot); - - // patch pkg-config and la files with absolute path - foreach ($increase_files as $file) { - if (str_ends_with($file, '.pc') || str_ends_with($file, '.la')) { - $content = FileSystem::readFile(BUILD_ROOT_PATH . '/' . $file); - $origin_files[$file] = $content; - // replace relative paths with absolute paths - $content = str_replace( - array_keys($placehoder), - array_values($placehoder), - $content - ); - FileSystem::writeFile(BUILD_ROOT_PATH . '/' . $file, $content); - } - } - - // add .spc-extract-placeholder.json in BUILD_ROOT_PATH - $placeholder_file = BUILD_ROOT_PATH . '/.spc-extract-placeholder.json'; - file_put_contents($placeholder_file, json_encode(array_keys($origin_files), JSON_PRETTY_PRINT)); - $increase_files[] = '.spc-extract-placeholder.json'; - - // every file mapped with BUILD_ROOT_PATH - // get BUILD_ROOT_PATH last dir part - $buildroot_part = basename(BUILD_ROOT_PATH); - $increase_files = array_map(fn ($file) => $buildroot_part . '/' . $file, $increase_files); - // write list to packlib_files.txt - FileSystem::writeFile(WORKING_DIR . '/packlib_files.txt', implode("\n", $increase_files)); - // pack - $filename = Config::getPreBuilt('match-pattern'); - $replace = [ - '{name}' => $lib->getName(), - '{arch}' => arch2gnu(php_uname('m')), - '{os}' => strtolower(PHP_OS_FAMILY), - '{libc}' => SPCTarget::getLibc() ?? 'default', - '{libcver}' => SPCTarget::getLibcVersion() ?? 'default', - ]; - // detect suffix, for proper tar option - $tar_option = $this->getTarOptionFromSuffix(Config::getPreBuilt('match-pattern')); - $filename = str_replace(array_keys($replace), array_values($replace), $filename); - $filename = WORKING_DIR . '/dist/' . $filename; - f_passthru("tar {$tar_option} {$filename} -T " . WORKING_DIR . '/packlib_files.txt'); - logger()->info('Pack library ' . $lib->getName() . ' to ' . $filename . ' complete.'); - - // remove temp files - unlink($placeholder_file); - } - } - - foreach ($origin_files as $file => $content) { - // restore original files - if (file_exists(BUILD_ROOT_PATH . '/' . $file)) { - FileSystem::writeFile(BUILD_ROOT_PATH . '/' . $file, $content); - } - } - - $time = round(microtime(true) - START_TIME, 3); - logger()->info('Build libs complete, used ' . $time . ' s !'); - return static::SUCCESS; - } - - private function sanityCheckLib(LibraryBase $lib): void - { - logger()->info('Sanity check for library ' . $lib->getName()); - // config - foreach ($lib->getStaticLibs() as $static_lib) { - if (!file_exists(FileSystem::convertPath(BUILD_LIB_PATH . '/' . $static_lib))) { - throw new ValidationException( - 'Static library ' . $static_lib . ' not found in ' . BUILD_LIB_PATH, - validation_module: "Static library {$static_lib} existence check" - ); - } - } - } - - /** - * Get tar compress options from suffix - * - * @param string $name Package file name - * @return string Tar options for packaging libs - */ - private function getTarOptionFromSuffix(string $name): string - { - if (str_ends_with($name, '.tar')) { - return '-cf'; - } - if (str_ends_with($name, '.tar.gz') || str_ends_with($name, '.tgz')) { - return '-czf'; - } - if (str_ends_with($name, '.tar.bz2') || str_ends_with($name, '.tbz2')) { - return '-cjf'; - } - if (str_ends_with($name, '.tar.xz') || str_ends_with($name, '.txz')) { - return '-cJf'; - } - if (str_ends_with($name, '.tar.lz') || str_ends_with($name, '.tlz')) { - return '-c --lzma -f'; - } - return '-cf'; - } -} diff --git a/src/SPC/command/dev/PhpVerCommand.php b/src/SPC/command/dev/PhpVerCommand.php deleted file mode 100644 index 05af1267..00000000 --- a/src/SPC/command/dev/PhpVerCommand.php +++ /dev/null @@ -1,41 +0,0 @@ -no_motd = true; - parent::initialize($input, $output); - } - - public function handle(): int - { - // Find php from source/php-src - $file = SOURCE_PATH . '/php-src/main/php_version.h'; - if (!file_exists($file)) { - $this->output->writeln('PHP source not found, maybe you need to extract first ?'); - - return static::FAILURE; - } - - $result = preg_match('/#define PHP_VERSION "([^"]+)"/', file_get_contents($file), $match); - if ($result === false) { - $this->output->writeln('PHP source not found, maybe you need to extract first ?'); - - return static::FAILURE; - } - - $this->output->writeln('' . $match[1] . ''); - return static::SUCCESS; - } -} diff --git a/src/SPC/command/dev/SortConfigCommand.php b/src/SPC/command/dev/SortConfigCommand.php deleted file mode 100644 index 7c897cd9..00000000 --- a/src/SPC/command/dev/SortConfigCommand.php +++ /dev/null @@ -1,80 +0,0 @@ -addArgument('config-name', InputArgument::REQUIRED, 'Your config to be sorted, you can sort "lib", "source" and "ext".'); - } - - public function handle(): int - { - switch ($name = $this->getArgument('config-name')) { - case 'lib': - $file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/lib.json'), true); - ConfigValidator::validateLibs($file); - uksort($file, function ($a, $b) use ($file) { - $type_a = $file[$a]['type'] ?? 'lib'; - $type_b = $file[$b]['type'] ?? 'lib'; - $type_order = ['root', 'target', 'package', 'lib']; - // compare type first - if ($type_a !== $type_b) { - return array_search($type_a, $type_order) <=> array_search($type_b, $type_order); - } - // compare name - return $a <=> $b; - }); - if (!file_put_contents(ROOT_DIR . '/config/lib.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n")) { - $this->output->writeln('Write file lib.json failed!'); - return static::FAILURE; - } - break; - case 'source': - $file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/source.json'), true); - ConfigValidator::validateSource($file); - uksort($file, fn ($a, $b) => $a === 'php-src' ? -1 : ($b === 'php-src' ? 1 : ($a < $b ? -1 : 1))); - if (!file_put_contents(ROOT_DIR . '/config/source.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n")) { - $this->output->writeln('Write file source.json failed!'); - return static::FAILURE; - } - break; - case 'ext': - $file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/ext.json'), true); - ConfigValidator::validateExts($file); - ksort($file); - if (!file_put_contents(ROOT_DIR . '/config/ext.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n")) { - $this->output->writeln('Write file ext.json failed!'); - return static::FAILURE; - } - break; - case 'pkg': - $file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/pkg.json'), true); - ConfigValidator::validatePkgs($file); - ksort($file); - if (!file_put_contents(ROOT_DIR . '/config/pkg.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n")) { - $this->output->writeln('Write file pkg.json failed!'); - return static::FAILURE; - } - break; - default: - $this->output->writeln("invalid config name: {$name}"); - return 1; - } - $this->output->writeln('sort success'); - return static::SUCCESS; - } -} diff --git a/src/SPC/doctor/AsCheckItem.php b/src/SPC/doctor/AsCheckItem.php deleted file mode 100644 index 0fa7466f..00000000 --- a/src/SPC/doctor/AsCheckItem.php +++ /dev/null @@ -1,18 +0,0 @@ -message; - } - - public function getFixItem(): string - { - return $this->fix_item; - } - - public function getFixParams(): array - { - return $this->fix_params; - } - - public function isOK(): bool - { - return $this->ok; - } - - public function setFixItem(string $fix_item = '', array $fix_params = []): void - { - $this->fix_item = $fix_item; - $this->fix_params = $fix_params; - } -} diff --git a/src/SPC/doctor/DoctorHandler.php b/src/SPC/doctor/DoctorHandler.php deleted file mode 100644 index 4ae8d2fe..00000000 --- a/src/SPC/doctor/DoctorHandler.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ - public static function getValidCheckList(): iterable - { - foreach (AttributeMapper::getDoctorCheckMap() as [$item, $optional]) { - /* @var AsCheckItem $item */ - // optional check - if ($optional !== null && !call_user_func($optional)) { - continue; // skip this when the optional check is false - } - // limit_os check - if ($item->limit_os !== null && $item->limit_os !== PHP_OS_FAMILY) { - continue; - } - // skipped items by env - $skip_items = array_filter(explode(',', getenv('SPC_SKIP_DOCTOR_CHECK_ITEMS') ?: '')); - if (in_array($item->item_name, $skip_items)) { - continue; // skip this item - } - yield $item; - } - } - - /** - * Emit the fix for a given CheckResult. - * - * @param OutputInterface $output the output interface to write messages to - * @param CheckResult $result the result of the check that needs fixing - * @return bool returns true if the fix was successful, false otherwise - */ - public static function emitFix(OutputInterface $output, CheckResult $result): bool - { - keyboard_interrupt_register(function () use ($output) { - $output->writeln('You cancelled fix'); - }); - try { - $fix_result = call_user_func(AttributeMapper::getDoctorFixMap()[$result->getFixItem()], ...$result->getFixParams()); - } catch (SPCException $e) { - $output->writeln('Fix failed: ' . $e->getMessage() . ''); - return false; - } catch (\Throwable $e) { - $output->writeln('Fix failed with an unexpected error: ' . $e->getMessage() . ''); - return false; - } - keyboard_interrupt_unregister(); - return $fix_result; - } -} diff --git a/src/SPC/doctor/OptionalCheck.php b/src/SPC/doctor/OptionalCheck.php deleted file mode 100644 index 4dae938b..00000000 --- a/src/SPC/doctor/OptionalCheck.php +++ /dev/null @@ -1,11 +0,0 @@ -findCommand($cmd) === null) { - $missing[] = $cmd; - } - } - if (!empty($missing)) { - return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools-bsd', [$missing]); - } - return CheckResult::ok(); - } - - #[AsFixItem('build-tools-bsd')] - public function fixBuildTools(array $missing): bool - { - if (get_current_user() !== 'root') { - $prefix = 'sudo '; - logger()->warning('Current user is not root, using sudo for running command'); - } else { - $prefix = ''; - } - shell(true)->exec("ASSUME_ALWAYS_YES=yes {$prefix}pkg install -y " . implode(' ', $missing)); - - return true; - } -} diff --git a/src/SPC/doctor/item/LinuxMuslCheck.php b/src/SPC/doctor/item/LinuxMuslCheck.php deleted file mode 100644 index c11bd4c4..00000000 --- a/src/SPC/doctor/item/LinuxMuslCheck.php +++ /dev/null @@ -1,100 +0,0 @@ -warning('Current user is not root, using sudo for running command'); - } - // The hardcoded version here is to be consistent with the version compiled by `musl-cross-toolchain`. - $musl_version_name = 'musl-1.2.5'; - $musl_source = [ - 'type' => 'url', - 'url' => "https://musl.libc.org/releases/{$musl_version_name}.tar.gz", - ]; - logger()->info('Downloading ' . $musl_source['url']); - Downloader::downloadSource($musl_version_name, $musl_source); - FileSystem::extractSource($musl_version_name, SPC_SOURCE_ARCHIVE, DOWNLOAD_PATH . "/{$musl_version_name}.tar.gz"); - - // Apply CVE-2025-26519 patch - SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0001.patch', SOURCE_PATH . "/{$musl_version_name}"); - SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0002.patch', SOURCE_PATH . "/{$musl_version_name}"); - logger()->info('Installing musl wrapper'); - shell()->cd(SOURCE_PATH . "/{$musl_version_name}") - ->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper') - ->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j') - ->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install"); - // TODO: add path using putenv instead of editing /etc/profile - return true; - } - - #[AsFixItem('fix-musl-cross-make')] - public function fixMuslCrossMake(): bool - { - $prefix = ''; - if (get_current_user() !== 'root') { - $prefix = 'sudo '; - logger()->warning('Current user is not root, using sudo for running command'); - } - $arch = arch2gnu(php_uname('m')); - logger()->info("Downloading package musl-toolchain-{$arch}-linux"); - PackageManager::installPackage("musl-toolchain-{$arch}-linux"); - $pkg_root = PKG_ROOT_PATH . "/musl-toolchain-{$arch}-linux"; - shell()->exec("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl"); - FileSystem::removeDir($pkg_root); - return true; - } -} diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php deleted file mode 100644 index 6e4c5034..00000000 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ /dev/null @@ -1,136 +0,0 @@ - '/usr/share/perl5/FindBin.pm', - 'binutils-gold' => 'ld.gold', - 'base-devel' => 'automake', - 'gettext-devel' => 'gettextize', - 'gettext-dev' => 'gettextize', - 'perl-IPC-Cmd' => '/usr/share/perl5/vendor_perl/IPC/Cmd.pm', - 'perl-Time-Piece' => '/usr/lib64/perl5/Time/Piece.pm', - ]; - - /** @noinspection PhpUnused */ - #[AsCheckItem('if necessary tools are installed', limit_os: 'Linux', level: 999)] - public function checkCliTools(): ?CheckResult - { - $distro = SystemUtil::getOSRelease(); - - $required = match ($distro['dist']) { - 'alpine' => self::TOOLS_ALPINE, - 'redhat' => self::TOOLS_RHEL, - 'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd', 'perl-Time-Piece']), - 'arch' => self::TOOLS_ARCH, - default => self::TOOLS_DEBIAN, - }; - $missing = []; - foreach ($required as $package) { - if (self::findCommand(self::PROVIDED_COMMAND[$package] ?? $package) === null) { - $missing[] = $package; - } - } - if (!empty($missing)) { - return CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]); - } - return CheckResult::ok(); - } - - #[AsCheckItem('if cmake version >= 3.22', limit_os: 'Linux')] - public function checkCMakeVersion(): ?CheckResult - { - $ver = get_cmake_version(); - if ($ver === null) { - return CheckResult::fail('Failed to get cmake version'); - } - if (version_compare($ver, '3.22.0') < 0) { - return CheckResult::fail('cmake version is too low (' . $ver . '), please update it manually!'); - } - return CheckResult::ok($ver); - } - - /** @noinspection PhpUnused */ - #[AsCheckItem('if necessary linux headers are installed', limit_os: 'Linux')] - public function checkSystemOSPackages(): ?CheckResult - { - if (SystemUtil::isMuslDist()) { - // check linux-headers installation - if (!file_exists('/usr/include/linux/mman.h')) { - return CheckResult::fail('linux-headers not installed on your system', 'install-linux-tools', [SystemUtil::getOSRelease(), ['linux-headers']]); - } - } - return CheckResult::ok(); - } - - #[AsFixItem('install-linux-tools')] - public function fixBuildTools(array $distro, array $missing): bool - { - $install_cmd = match ($distro['dist']) { - 'ubuntu', 'debian', 'Deepin', 'neon' => 'apt-get install -y', - 'alpine' => 'apk add', - 'redhat' => 'dnf install -y', - 'centos' => 'yum install -y', - 'arch' => 'pacman -S --noconfirm', - default => throw new EnvironmentException( - "Current linux distro [{$distro['dist']}] does not have an auto-install script for packages yet.", - 'You can submit an issue to request support: https://github.com/crazywhalecc/static-php-cli/issues' - ), - }; - $prefix = ''; - if (($user = exec('whoami')) !== 'root') { - $prefix = 'sudo '; - logger()->warning('Current user (' . $user . ') is not root, using sudo for running command (may require password input)'); - } - - $is_debian = in_array($distro['dist'], ['debian', 'ubuntu', 'Deepin', 'neon']); - $to_install = $is_debian ? str_replace('xz', 'xz-utils', $missing) : $missing; - // debian, alpine libtool -> libtoolize - $to_install = str_replace('libtoolize', 'libtool', $to_install); - shell(true)->exec($prefix . $install_cmd . ' ' . implode(' ', $to_install)); - - return true; - } -} diff --git a/src/SPC/doctor/item/MacOSToolCheckList.php b/src/SPC/doctor/item/MacOSToolCheckList.php deleted file mode 100644 index 7cc9ca2a..00000000 --- a/src/SPC/doctor/item/MacOSToolCheckList.php +++ /dev/null @@ -1,109 +0,0 @@ -findCommand('brew')) === null) { - return CheckResult::fail('Homebrew is not installed', 'brew'); - } - if ($path !== '/opt/homebrew/bin/brew' && getenv('GNU_ARCH') === 'aarch64') { - return CheckResult::fail('Current homebrew (/usr/local/bin/homebrew) is not installed for M1 Mac, please re-install homebrew in /opt/homebrew/ !'); - } - return CheckResult::ok(); - } - - #[AsCheckItem('if necessary tools are installed', limit_os: 'Darwin')] - public function checkCliTools(): ?CheckResult - { - $missing = []; - foreach (self::REQUIRED_COMMANDS as $cmd) { - if ($this->findCommand($cmd) === null) { - $missing[] = $cmd; - } - } - if (!empty($missing)) { - return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools', [$missing]); - } - return CheckResult::ok(); - } - - #[AsCheckItem('if bison version is 3.0 or later', limit_os: 'Darwin')] - public function checkBisonVersion(array $command_path = []): ?CheckResult - { - // if the bison command is /usr/bin/bison, it is the system bison that may be too old - if (($bison = $this->findCommand('bison', $command_path)) === null) { - return CheckResult::fail('bison is not installed or too old', 'build-tools', [['bison']]); - } - // check version: bison (GNU Bison) x.y(.z) - $version = shell()->execWithResult("{$bison} --version", false); - if (preg_match('/bison \(GNU Bison\) (\d+)\.(\d+)(?:\.(\d+))?/', $version[1][0], $matches)) { - $major = (int) $matches[1]; - // major should be 3 or later - if ($major < 3) { - // find homebrew keg-only bison - if ($command_path !== []) { - return CheckResult::fail("Current {$bison} version is too old: " . $matches[0]); - } - return $this->checkBisonVersion(['/opt/homebrew/opt/bison/bin', '/usr/local/opt/bison/bin']); - } - return CheckResult::ok($matches[0]); - } - return CheckResult::fail('bison version cannot be determined'); - } - - #[AsFixItem('brew')] - public function fixBrew(): bool - { - shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'); - return true; - } - - #[AsFixItem('build-tools')] - public function fixBuildTools(array $missing): bool - { - $replacement = [ - 'glibtoolize' => 'libtool', - ]; - foreach ($missing as $cmd) { - if (isset($replacement[$cmd])) { - $cmd = $replacement[$cmd]; - } - shell(true)->exec('brew install --formula ' . escapeshellarg($cmd)); - } - return true; - } -} diff --git a/src/SPC/doctor/item/OSCheckList.php b/src/SPC/doctor/item/OSCheckList.php deleted file mode 100644 index 7975dde9..00000000 --- a/src/SPC/doctor/item/OSCheckList.php +++ /dev/null @@ -1,26 +0,0 @@ -execWithResult("{$pkgconf} --version", false); - if ($ret === 0) { - return CheckResult::ok(implode(' ', $output)); - } - return CheckResult::fail('pkg-config is not functional', 'install-pkgconfig'); - } - - #[AsFixItem('install-pkgconfig')] - public function installPkgConfig(): bool - { - PackageManager::installPackage('pkg-config'); - return true; - } -} diff --git a/src/SPC/doctor/item/Re2cVersionCheck.php b/src/SPC/doctor/item/Re2cVersionCheck.php deleted file mode 100644 index 1c130379..00000000 --- a/src/SPC/doctor/item/Re2cVersionCheck.php +++ /dev/null @@ -1,53 +0,0 @@ -= 1.0.3', limit_os: 'Linux', level: 20)] - #[AsCheckItem('if re2c version >= 1.0.3', limit_os: 'Darwin', level: 20)] - public function checkRe2cVersion(): ?CheckResult - { - $ver = shell(false)->execWithResult('re2c --version', false); - // match version: re2c X.X(.X) - if ($ver[0] !== 0 || !preg_match('/re2c\s+(\d+\.\d+(\.\d+)?)/', $ver[1][0], $matches)) { - return CheckResult::fail('Failed to get re2c version', 'build-re2c'); - } - $version_string = $matches[1]; - if (version_compare($version_string, '1.0.3') < 0) { - return CheckResult::fail('re2c version is too low (' . $version_string . ')', 'build-re2c'); - } - return CheckResult::ok($version_string); - } - - #[AsFixItem('build-re2c')] - public function buildRe2c(): bool - { - try { - Downloader::downloadSource('re2c'); - } catch (DownloaderException) { - logger()->warning('Failed to download re2c version, trying alternative'); - $alt = Config::getSource('re2c'); - $alt = [...$alt, ...$alt['alt'] ?? []]; - Downloader::downloadSource('re2c', $alt); - } - $builder = BuilderProvider::makeBuilderByInput(new ArgvInput([])); - $builder->proveLibs(['re2c']); - $builder->setupLibs(); - return true; - } -} diff --git a/src/SPC/doctor/item/WindowsToolCheckList.php b/src/SPC/doctor/item/WindowsToolCheckList.php deleted file mode 100644 index 7f71f10e..00000000 --- a/src/SPC/doctor/item/WindowsToolCheckList.php +++ /dev/null @@ -1,101 +0,0 @@ -execWithResult(quote($path) . ' -v', false)[1]), 'MSWin32')) { - return CheckResult::fail($path . ' is not built for msvc.', 'install-perl'); - } - return CheckResult::ok(); - } - - #[AsFixItem('install-php-sdk')] - public function installPhpSdk(): bool - { - FileSystem::removeDir(getenv('PHP_SDK_PATH')); - cmd(true)->exec('git.exe clone --depth 1 https://github.com/php/php-sdk-binary-tools.git ' . getenv('PHP_SDK_PATH')); - return true; - } - - #[AsFixItem('install-nasm')] - public function installNasm(): bool - { - PackageManager::installPackage('nasm-x86_64-win'); - return true; - } - - #[AsFixItem('install-perl')] - public function installPerl(): bool - { - $arch = arch2gnu(php_uname('m')); - PackageManager::installPackage("strawberry-perl-{$arch}-win"); - return true; - } -} diff --git a/src/SPC/doctor/item/ZigCheck.php b/src/SPC/doctor/item/ZigCheck.php deleted file mode 100644 index b201e027..00000000 --- a/src/SPC/doctor/item/ZigCheck.php +++ /dev/null @@ -1,46 +0,0 @@ - 'win', - 'Darwin' => 'macos', - 'BSD' => 'freebsd', - default => 'linux', - }; - PackageManager::installPackage("zig-{$arch}-{$os}"); - return Zig::isInstalled(); - } -} diff --git a/src/SPC/exception/BuildFailureException.php b/src/SPC/exception/BuildFailureException.php deleted file mode 100644 index f2509e61..00000000 --- a/src/SPC/exception/BuildFailureException.php +++ /dev/null @@ -1,13 +0,0 @@ -solution; - } -} diff --git a/src/SPC/exception/ExceptionHandler.php b/src/SPC/exception/ExceptionHandler.php deleted file mode 100644 index df5e4bf0..00000000 --- a/src/SPC/exception/ExceptionHandler.php +++ /dev/null @@ -1,227 +0,0 @@ - Build PHP extra info binding */ - private static array $build_php_extra_info = []; - - public static function handleSPCException(SPCException $e): void - { - // XXX error: yyy - $head_msg = match ($class = get_class($e)) { - BuildFailureException::class => "✗ Build failed: {$e->getMessage()}", - DownloaderException::class => "✗ Download failed: {$e->getMessage()}", - EnvironmentException::class => "⚠ Environment check failed: {$e->getMessage()}", - ExecutionException::class => "✗ Command execution failed: {$e->getMessage()}", - FileSystemException::class => "✗ File system error: {$e->getMessage()}", - InterruptException::class => "⚠ Build interrupted by user: {$e->getMessage()}", - PatchException::class => "✗ Patch apply failed: {$e->getMessage()}", - SPCInternalException::class => "✗ SPC internal error: {$e->getMessage()}", - ValidationException::class => "⚠ Validation failed: {$e->getMessage()}", - WrongUsageException::class => $e->getMessage(), - default => "✗ Unknown SPC exception {$class}: {$e->getMessage()}", - }; - self::logError($head_msg); - - // ---------------------------------------- - $minor_logs = in_array($class, self::MINOR_LOG_EXCEPTIONS, true); - - if ($minor_logs) { - return; - } - - self::logError("----------------------------------------\n"); - - // get the SPCException module - if ($lib_info = $e->getLibraryInfo()) { - self::logError('Failed module: ' . ConsoleColor::yellow("library {$lib_info['library_name']} builder for {$lib_info['os']}")); - } elseif ($ext_info = $e->getExtensionInfo()) { - self::logError('Failed module: ' . ConsoleColor::yellow("shared extension {$ext_info['extension_name']} builder")); - } elseif (self::$builder) { - $os = match (get_class(self::$builder)) { - WindowsBuilder::class => 'Windows', - MacOSBuilder::class => 'macOS', - LinuxBuilder::class => 'Linux', - BSDBuilder::class => 'FreeBSD', - default => 'Unknown OS', - }; - self::logError('Failed module: ' . ConsoleColor::yellow("Builder for {$os}")); - } elseif (!in_array($class, self::KNOWN_EXCEPTIONS)) { - self::logError('Failed From: ' . ConsoleColor::yellow('Unknown SPC module ' . $class)); - } - - // get command execution info - if ($e instanceof ExecutionException) { - self::logError(''); - self::logError('Failed command: ' . ConsoleColor::yellow($e->getExecutionCommand())); - if ($cd = $e->getCd()) { - self::logError('Command executed in: ' . ConsoleColor::yellow($cd)); - } - if ($env = $e->getEnv()) { - self::logError('Command inline env variables:'); - foreach ($env as $k => $v) { - self::logError(ConsoleColor::yellow("{$k}={$v}"), 4); - } - } - } - - // validation error - if ($e instanceof ValidationException) { - self::logError('Failed validation module: ' . ConsoleColor::yellow($e->getValidationModuleString())); - } - - // environment error - if ($e instanceof EnvironmentException) { - self::logError('Failed environment check: ' . ConsoleColor::yellow($e->getMessage())); - if (($solution = $e->getSolution()) !== null) { - self::logError('Solution: ' . ConsoleColor::yellow($solution)); - } - } - - // get patch info - if ($e instanceof PatchException) { - self::logError("Failed patch module: {$e->getPatchModule()}"); - } - - // get internal trace - if ($e instanceof SPCInternalException) { - self::logError('Internal trace:'); - self::logError(ConsoleColor::gray("{$e->getTraceAsString()}\n"), 4); - } - - // get the full build info if possible - if ($info = ExceptionHandler::$build_php_extra_info) { - self::logError('', output_log: defined('DEBUG_MODE')); - self::logError('Build PHP extra info:', output_log: defined('DEBUG_MODE')); - self::printArrayInfo($info); - } - - // get the full builder options if possible - if ($e->getBuildPHPInfo()) { - $info = $e->getBuildPHPInfo(); - self::logError('', output_log: defined('DEBUG_MODE')); - self::logError('Builder function: ' . ConsoleColor::yellow($info['builder_function']), output_log: defined('DEBUG_MODE')); - } - - self::logError("\n----------------------------------------\n"); - - // convert log file path if in docker - $spc_log_convert = get_display_path(SPC_OUTPUT_LOG); - $shell_log_convert = get_display_path(SPC_SHELL_LOG); - $spc_logs_dir_convert = get_display_path(SPC_LOGS_DIR); - - self::logError('⚠ The ' . ConsoleColor::cyan('console output log') . ConsoleColor::red(' is saved in ') . ConsoleColor::none($spc_log_convert)); - if (file_exists(SPC_SHELL_LOG)) { - self::logError('⚠ The ' . ConsoleColor::cyan('shell output log') . ConsoleColor::red(' is saved in ') . ConsoleColor::none($shell_log_convert)); - } - if ($e->getExtraLogFiles() !== []) { - foreach ($e->getExtraLogFiles() as $key => $file) { - self::logError("⚠ Log file [{$key}] is saved in: " . ConsoleColor::none("{$spc_logs_dir_convert}/{$file}")); - } - } - if (!defined('DEBUG_MODE')) { - self::logError('⚠ If you want to see more details in console, use `--debug` option.'); - } - } - - public static function handleDefaultException(\Throwable $e): void - { - $class = get_class($e); - $file = $e->getFile(); - $line = $e->getLine(); - self::logError("✗ Unhandled exception {$class} on {$file} line {$line}:\n\t{$e->getMessage()}\n"); - self::logError('Stack trace:'); - self::logError(ConsoleColor::gray($e->getTraceAsString()) . PHP_EOL, 4); - self::logError('⚠ Please report this exception to: https://github.com/crazywhalecc/static-php-cli/issues'); - } - - public static function bindBuilder(?BuilderBase $bind_builder): void - { - self::$builder = $bind_builder; - } - - public static function bindBuildPhpExtraInfo(array $build_php_extra_info): void - { - self::$build_php_extra_info = $build_php_extra_info; - } - - private static function logError($message, int $indent_space = 0, bool $output_log = true): void - { - $spc_log = fopen(SPC_OUTPUT_LOG, 'a'); - $msg = explode("\n", (string) $message); - foreach ($msg as $v) { - $line = str_pad($v, strlen($v) + $indent_space, ' ', STR_PAD_LEFT); - fwrite($spc_log, strip_ansi_colors($line) . PHP_EOL); - if ($output_log) { - echo ConsoleColor::red($line) . PHP_EOL; - } - } - } - - /** - * Print array info to console and log. - */ - private static function printArrayInfo(array $info): void - { - $log_output = defined('DEBUG_MODE'); - $maxlen = 0; - foreach ($info as $k => $v) { - $maxlen = max(strlen($k), $maxlen); - } - foreach ($info as $k => $v) { - if (is_string($v)) { - if ($v === '') { - self::logError($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow('""'), 4, $log_output); - } else { - self::logError($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow($v), 4, $log_output); - } - } elseif (is_array($v) && !is_assoc_array($v)) { - if ($v === []) { - self::logError($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow('[]'), 4, $log_output); - continue; - } - $first = array_shift($v); - self::logError($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow($first), 4, $log_output); - foreach ($v as $vs) { - self::logError(str_pad('', $maxlen + 2) . ConsoleColor::yellow($vs), 4, $log_output); - } - } elseif (is_bool($v) || is_null($v)) { - self::logError($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::cyan($v === true ? 'true' : ($v === false ? 'false' : 'null')), 4, $log_output); - } else { - self::logError($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow(json_encode($v, JSON_PRETTY_PRINT)), 4, $log_output); - } - } - } -} diff --git a/src/SPC/exception/ExecutionException.php b/src/SPC/exception/ExecutionException.php deleted file mode 100644 index 6a4d1b9d..00000000 --- a/src/SPC/exception/ExecutionException.php +++ /dev/null @@ -1,58 +0,0 @@ -cmd instanceof UnixShell || $this->cmd instanceof WindowsCmd) { - return $this->cmd->getLastCommand(); - } - return $this->cmd; - } - - /** - * Returns the directory in which the command was executed. - */ - public function getCd(): ?string - { - return $this->cd; - } - - /** - * Returns the environment variables that were set during the command execution. - */ - public function getEnv(): array - { - return $this->env; - } -} diff --git a/src/SPC/exception/FileSystemException.php b/src/SPC/exception/FileSystemException.php deleted file mode 100644 index 2fa3e916..00000000 --- a/src/SPC/exception/FileSystemException.php +++ /dev/null @@ -1,7 +0,0 @@ -patch_module; - } -} diff --git a/src/SPC/exception/SPCException.php b/src/SPC/exception/SPCException.php deleted file mode 100644 index e8b23361..00000000 --- a/src/SPC/exception/SPCException.php +++ /dev/null @@ -1,147 +0,0 @@ -loadStackTraceInfo(); - } - - public function bindExtensionInfo(array $extension_info): void - { - $this->extension_info = $extension_info; - } - - public function addExtraLogFile(string $key, string $filename): void - { - $this->extra_log_files[$key] = $filename; - } - - /** - * Returns an array containing information about the SPC module. - * - * This method can be overridden by subclasses to provide specific module information. - * - * @return null|array{ - * library_name: string, - * library_class: string, - * os: string, - * file: null|string, - * line: null|int, - * } an array containing module information - */ - public function getLibraryInfo(): ?array - { - return $this->library_info; - } - - /** - * Returns an array containing information about the PHP build process. - * - * @return null|array{ - * builder_function: string, - * file: null|string, - * line: null|int, - * } an array containing PHP build information - */ - public function getBuildPHPInfo(): ?array - { - return $this->build_php_info; - } - - /** - * Returns an array containing information about the SPC extension. - * - * This method can be overridden by subclasses to provide specific extension information. - * - * @return null|array{ - * extension_name: string, - * extension_class: string, - * file: null|string, - * line: null|int, - * } an array containing extension information - */ - public function getExtensionInfo(): ?array - { - return $this->extension_info; - } - - public function getExtraLogFiles(): array - { - return $this->extra_log_files; - } - - private function loadStackTraceInfo(): void - { - $trace = $this->getTrace(); - foreach ($trace as $frame) { - if (!isset($frame['class'])) { - continue; - } - - // Check if the class is a subclass of LibraryBase - if (!$this->library_info && is_a($frame['class'], LibraryBase::class, true)) { - try { - $reflection = new \ReflectionClass($frame['class']); - if ($reflection->hasConstant('NAME')) { - $name = $reflection->getConstant('NAME'); - if ($name !== 'unknown') { - $this->library_info = [ - 'library_name' => $name, - 'library_class' => $frame['class'], - 'os' => match (true) { - is_a($frame['class'], BSDLibraryBase::class, true) => 'BSD', - is_a($frame['class'], LinuxLibraryBase::class, true) => 'Linux', - is_a($frame['class'], MacOSLibraryBase::class, true) => 'macOS', - is_a($frame['class'], WindowsLibraryBase::class, true) => 'Windows', - default => 'Unknown', - }, - 'file' => $frame['file'] ?? null, - 'line' => $frame['line'] ?? null, - ]; - continue; - } - } - } catch (\ReflectionException) { - continue; - } - } - - // Check if the class is a subclass of BuilderBase and the method is buildPHP - if (!$this->build_php_info && is_a($frame['class'], BuilderBase::class, true)) { - $this->build_php_info = [ - 'builder_function' => $frame['function'], - 'file' => $frame['file'] ?? null, - 'line' => $frame['line'] ?? null, - ]; - } - } - } -} diff --git a/src/SPC/exception/SPCInternalException.php b/src/SPC/exception/SPCInternalException.php deleted file mode 100644 index f0d75d4a..00000000 --- a/src/SPC/exception/SPCInternalException.php +++ /dev/null @@ -1,12 +0,0 @@ -getTrace() as $trace) { - // Extension validate() => "Extension validator" - if (is_a($trace['class'] ?? null, Extension::class, true) && $trace['function'] === 'validate') { - $this->validation_module = 'Extension validator'; - break; - } - - // Other => "ClassName::functionName" - $this->validation_module = [ - 'class' => $trace['class'] ?? null, - 'function' => $trace['function'], - ]; - break; - } - } else { - $this->validation_module = $validation_module; - } - } - - /** - * Returns the validation module string. - */ - public function getValidationModuleString(): string - { - if ($this->validation_module === null) { - return 'Unknown'; - } - if (is_string($this->validation_module)) { - return $this->validation_module; - } - $str = $this->validation_module['class'] ?? null; - if ($str !== null) { - $str .= '::'; - } - return ($str ?? '') . $this->validation_module['function']; - } -} diff --git a/src/SPC/exception/WrongUsageException.php b/src/SPC/exception/WrongUsageException.php deleted file mode 100644 index 77c93aff..00000000 --- a/src/SPC/exception/WrongUsageException.php +++ /dev/null @@ -1,13 +0,0 @@ - ['-windows', '-win', ''], - 'Darwin' => ['-macos', '-unix', ''], - 'Linux' => ['-linux', '-unix', ''], - 'BSD' => ['-freebsd', '-bsd', '-unix', ''], - default => throw new WrongUsageException('OS ' . PHP_OS_FAMILY . ' is not supported'), - }; - foreach ($m_key as $v) { - if (isset(self::$pre_built["{$name}{$v}"])) { - return self::$pre_built["{$name}{$v}"]; - } - } - } - return self::$pre_built[$name] ?? null; - } - - /** - * Get source configuration by name - * - * @param string $name The name of the source - * @return null|array The source configuration or null if not found - */ - public static function getSource(string $name): ?array - { - if (self::$source === null) { - self::$source = FileSystem::loadConfigArray('source'); - } - return self::$source[$name] ?? null; - } - - /** - * Get package configuration by name - * - * @param string $name The name of the package - * @return null|array The package configuration or null if not found - */ - public static function getPkg(string $name): ?array - { - if (self::$pkg === null) { - self::$pkg = FileSystem::loadConfigArray('pkg'); - } - return self::$pkg[$name] ?? null; - } - - /** - * Get library configuration by name and optional key - * Supports platform-specific configurations for different operating systems - * - * @param string $name The name of the library - * @param null|string $key The configuration key (static-libs, headers, lib-depends, lib-suggests, frameworks, bin) - * @param mixed $default Default value if key not found - * @return mixed The library configuration or default value - */ - public static function getLib(string $name, ?string $key = null, mixed $default = null) - { - if (self::$lib === null) { - self::$lib = FileSystem::loadConfigArray('lib'); - } - if (!isset(self::$lib[$name])) { - throw new WrongUsageException('lib [' . $name . '] is not supported yet'); - } - $supported_sys_based = ['static-libs', 'headers', 'lib-depends', 'lib-suggests', 'frameworks', 'bin']; - if ($key !== null && in_array($key, $supported_sys_based)) { - $m_key = match (PHP_OS_FAMILY) { - 'Windows' => ['-windows', '-win', ''], - 'Darwin' => ['-macos', '-unix', ''], - 'Linux' => ['-linux', '-unix', ''], - 'BSD' => ['-freebsd', '-bsd', '-unix', ''], - default => throw new WrongUsageException('OS ' . PHP_OS_FAMILY . ' is not supported'), - }; - foreach ($m_key as $v) { - if (isset(self::$lib[$name][$key . $v])) { - return self::$lib[$name][$key . $v]; - } - } - return $default; - } - if ($key !== null) { - return self::$lib[$name][$key] ?? $default; - } - return self::$lib[$name]; - } - - /** - * Get all library configurations - * - * @return array All library configurations - */ - public static function getLibs(): array - { - if (self::$lib === null) { - self::$lib = FileSystem::loadConfigArray('lib'); - } - return self::$lib; - } - - /** - * Get extension target configuration by name - * - * @param string $name The name of the extension - * @return null|array The extension target configuration or default ['static', 'shared'] - */ - public static function getExtTarget(string $name): ?array - { - if (self::$ext === null) { - self::$ext = FileSystem::loadConfigArray('ext'); - } - if (!isset(self::$ext[$name])) { - throw new WrongUsageException('ext [' . $name . '] is not supported yet'); - } - return self::$ext[$name]['target'] ?? ['static', 'shared']; - } - - /** - * Get extension configuration by name and optional key - * Supports platform-specific configurations for different operating systems - * - * @param string $name The name of the extension - * @param null|string $key The configuration key (lib-depends, lib-suggests, ext-depends, ext-suggests, arg-type) - * @param mixed $default Default value if key not found - * @return mixed The extension configuration or default value - */ - public static function getExt(string $name, ?string $key = null, mixed $default = null) - { - if (self::$ext === null) { - self::$ext = FileSystem::loadConfigArray('ext'); - } - if (!isset(self::$ext[$name])) { - throw new WrongUsageException('ext [' . $name . '] is not supported yet'); - } - $supported_sys_based = ['lib-depends', 'lib-suggests', 'ext-depends', 'ext-suggests', 'arg-type']; - if ($key !== null && in_array($key, $supported_sys_based)) { - $m_key = match (PHP_OS_FAMILY) { - 'Windows' => ['-windows', '-win', ''], - 'Darwin' => ['-macos', '-unix', ''], - 'Linux' => ['-linux', '-unix', ''], - 'BSD' => ['-freebsd', '-bsd', '-unix', ''], - default => throw new WrongUsageException('OS ' . PHP_OS_FAMILY . ' is not supported'), - }; - foreach ($m_key as $v) { - if (isset(self::$ext[$name][$key . $v])) { - return self::$ext[$name][$key . $v]; - } - } - return $default; - } - if ($key !== null) { - return self::$ext[$name][$key] ?? $default; - } - return self::$ext[$name]; - } - - /** - * Get all extension configurations - * - * @return array All extension configurations - */ - public static function getExts(): array - { - if (self::$ext === null) { - self::$ext = FileSystem::loadConfigArray('ext'); - } - return self::$ext; - } - - /** - * Get all source configurations - * - * @return array All source configurations - */ - public static function getSources(): array - { - if (self::$source === null) { - self::$source = FileSystem::loadConfigArray('source'); - } - return self::$source; - } -} diff --git a/src/SPC/store/CurlHook.php b/src/SPC/store/CurlHook.php deleted file mode 100644 index b25ae2bf..00000000 --- a/src/SPC/store/CurlHook.php +++ /dev/null @@ -1,39 +0,0 @@ -debug('no github token found, skip'); - return; - } - if (getenv('GITHUB_USER')) { - $auth = base64_encode(getenv('GITHUB_USER') . ':' . $token); - $he = "Authorization: Basic {$auth}"; - if (!in_array($he, $headers)) { - $headers[] = $he; - } - logger()->info("using basic github token for {$method} {$url}"); - } else { - $auth = $token; - $he = "Authorization: Bearer {$auth}"; - if (!in_array($he, $headers)) { - $headers[] = $he; - } - logger()->info("using bearer github token for {$method} {$url}"); - } - } -} diff --git a/src/SPC/store/DirDiff.php b/src/SPC/store/DirDiff.php deleted file mode 100644 index 8cd5c1d4..00000000 --- a/src/SPC/store/DirDiff.php +++ /dev/null @@ -1,95 +0,0 @@ -reset(); - } - - /** - * Reset the baseline to current state. - */ - public function reset(): void - { - $this->before = FileSystem::scanDirFiles($this->dir, relative: true) ?: []; - - if ($this->track_content_changes) { - $this->before_file_hashes = []; - foreach ($this->before as $file) { - $this->before_file_hashes[$file] = md5_file($this->dir . DIRECTORY_SEPARATOR . $file); - } - } - } - - /** - * Get the list of incremented files. - * - * @param bool $relative Return relative paths or absolute paths - * @return array List of incremented files - */ - public function getIncrementFiles(bool $relative = false): array - { - $after = FileSystem::scanDirFiles($this->dir, relative: true) ?: []; - $diff = array_diff($after, $this->before); - if ($relative) { - return $diff; - } - return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $diff); - } - - /** - * Get the list of changed files (including new files). - * - * @param bool $relative Return relative paths or absolute paths - * @param bool $include_new_files Include new files as changed files - * @return array List of changed files - */ - public function getChangedFiles(bool $relative = false, bool $include_new_files = true): array - { - $after = FileSystem::scanDirFiles($this->dir, relative: true) ?: []; - $changed = []; - foreach ($after as $file) { - if (isset($this->before_file_hashes[$file])) { - $after_hash = md5_file($this->dir . DIRECTORY_SEPARATOR . $file); - if ($after_hash !== $this->before_file_hashes[$file]) { - $changed[] = $file; - } - } elseif ($include_new_files) { - // New file, consider as changed - $changed[] = $file; - } - } - if ($relative) { - return $changed; - } - return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $changed); - } - - /** - * Get the list of removed files. - * - * @param bool $relative Return relative paths or absolute paths - * @return array List of removed files - */ - public function getRemovedFiles(bool $relative = false): array - { - $after = FileSystem::scanDirFiles($this->dir, relative: true) ?: []; - $removed = array_diff($this->before, $after); - if ($relative) { - return $removed; - } - return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $removed); - } -} diff --git a/src/SPC/store/Downloader.php b/src/SPC/store/Downloader.php deleted file mode 100644 index ccf61dd8..00000000 --- a/src/SPC/store/Downloader.php +++ /dev/null @@ -1,711 +0,0 @@ - [url, filename] - */ - public static function getPIEInfo(string $name, array $source): array - { - $packagist_url = "https://repo.packagist.org/p2/{$source['repo']}.json"; - logger()->debug("Fetching {$name} source from packagist index: {$packagist_url}"); - $data = json_decode(self::curlExec( - url: $packagist_url, - retries: self::getRetryAttempts() - ), true); - if (!isset($data['packages'][$source['repo']]) || !is_array($data['packages'][$source['repo']])) { - throw new DownloaderException("failed to find {$name} repo info from packagist"); - } - // get the first version - $first = $data['packages'][$source['repo']][0] ?? []; - // check 'type' => 'php-ext' or contains 'php-ext' key - if (!isset($first['php-ext'])) { - throw new DownloaderException("failed to find {$name} php-ext info from packagist, maybe not a php extension package"); - } - // get download link from dist - $dist_url = $first['dist']['url'] ?? null; - $dist_type = $first['dist']['type'] ?? null; - if (!$dist_url || !$dist_type) { - throw new DownloaderException("failed to find {$name} dist info from packagist"); - } - $name = str_replace('/', '_', $source['repo']); - $version = $first['version'] ?? 'unknown'; - // file name use: $name-$version.$dist_type - return [$dist_url, "{$name}-{$version}.{$dist_type}"]; - } - - /** - * Get latest version from BitBucket tag - * - * @param string $name Source name - * @param array $source Source meta info: [repo] - * @return array [url, filename] - */ - public static function getLatestBitbucketTag(string $name, array $source): array - { - logger()->debug("finding {$name} source from bitbucket tag"); - $data = json_decode(self::curlExec( - url: "https://api.bitbucket.org/2.0/repositories/{$source['repo']}/refs/tags", - retries: self::getRetryAttempts() - ), true); - $ver = $data['values'][0]['name']; - if (!$ver) { - throw new DownloaderException("failed to find {$name} bitbucket source"); - } - $url = "https://bitbucket.org/{$source['repo']}/get/{$ver}.tar.gz"; - $headers = self::curlExec( - url: $url, - method: 'HEAD', - retries: self::getRetryAttempts() - ); - preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?.+\.tar\.gz)\1/im', $headers, $matches); - if ($matches) { - $filename = $matches['filename']; - } else { - $filename = "{$name}-{$data['tag_name']}.tar.gz"; - } - - return [$url, $filename]; - } - - /** - * Get latest version from GitHub tarball - * - * @param string $name Source name - * @param array $source Source meta info: [repo] - * @param string $type Type of tarball, default is 'releases' - * @return array [url, filename] - */ - 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}{$source['query']}", - hooks: [[CurlHook::class, 'setupGithubToken']], - retries: self::getRetryAttempts() - ), true, 512, JSON_THROW_ON_ERROR); - - $url = null; - foreach ($data as $rel) { - 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; - } - if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) { - $url = $rel['tarball_url']; - break; - } - } - if (!$url) { - throw new DownloaderException("failed to find {$name} source"); - } - $headers = self::curlExec( - url: $url, - method: 'HEAD', - hooks: [[CurlHook::class, 'setupGithubToken']], - retries: self::getRetryAttempts() - ); - preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?.+\.tar\.gz)\1/im', $headers, $matches); - if ($matches) { - $filename = $matches['filename']; - } else { - $filename = "{$name}-" . ($type === 'releases' ? $data['tag_name'] : $data['name']) . '.tar.gz'; - } - - return [$url, $filename]; - } - - /** - * Get latest version from GitHub release (uploaded archive) - * - * @param string $name Source name - * @param array $source Source meta info: [repo, match] - * @param bool $match_result Whether to return matched result by `match` param (default: true) - * @return array When $match_result = true, and we matched, [url, filename]. Otherwise, [{asset object}. ...] - */ - public static function getLatestGithubRelease(string $name, array $source, bool $match_result = true): array - { - logger()->debug("finding {$name} from github releases assets"); - $data = json_decode(self::curlExec( - url: "https://api.github.com/repos/{$source['repo']}/releases", - hooks: [[CurlHook::class, 'setupGithubToken']], - retries: self::getRetryAttempts() - ), true); - $url = null; - $filename = null; - foreach ($data as $release) { - if (($source['prefer-stable'] ?? false) === true && $release['prerelease'] === true) { - continue; - } - logger()->debug("Found {$release['name']} releases assets"); - if (!$match_result) { - return $release['assets']; - } - foreach ($release['assets'] as $asset) { - if (preg_match('|' . $source['match'] . '|', $asset['name'])) { - $url = "https://api.github.com/repos/{$source['repo']}/releases/assets/{$asset['id']}"; - $filename = $asset['name']; - break 2; - } - } - } - - if (!$url || !$filename) { - throw new DownloaderException("failed to find {$name} release metadata"); - } - - return [$url, $filename]; - } - - /** - * Get latest version from file list (regex based crawler) - * - * @param string $name Source name - * @param array $source Source meta info: [filelist] - * @return array [url, filename] - */ - public static function getFromFileList(string $name, array $source): array - { - logger()->debug("finding {$name} source from file list"); - $page = self::curlExec($source['url'], retries: self::getRetryAttempts()); - preg_match_all($source['regex'], $page, $matches); - if (!$matches) { - throw new DownloaderException("Failed to get {$name} version"); - } - $versions = []; - foreach ($matches['version'] as $i => $version) { - $lowerVersion = strtolower($version); - foreach ([ - 'alpha', - 'beta', - 'rc', - 'pre', - 'nightly', - 'snapshot', - 'dev', - ] as $betaVersion) { - if (str_contains($lowerVersion, $betaVersion)) { - continue 2; - } - } - $versions[$version] = $matches['file'][$i]; - } - uksort($versions, 'version_compare'); - - return [$source['url'] . end($versions), end($versions), key($versions)]; - } - - /** - * Download file from URL - * - * @param string $name Download name - * @param string $url Download URL - * @param string $filename Target filename - * @param null|string $move_path Optional move path after download - * @param int $download_as Download type constant - * @param array $headers Optional HTTP headers - * @param array $hooks Optional curl hooks - */ - public static function downloadFile(string $name, string $url, string $filename, ?string $move_path = null, int $download_as = SPC_DOWNLOAD_SOURCE, array $headers = [], array $hooks = []): void - { - logger()->debug("Downloading {$url}"); - $cancel_func = function () use ($filename) { - if (file_exists(FileSystem::convertPath(DOWNLOAD_PATH . '/' . $filename))) { - logger()->warning('Deleting download file: ' . $filename); - unlink(FileSystem::convertPath(DOWNLOAD_PATH . '/' . $filename)); - } - }; - keyboard_interrupt_register($cancel_func); - self::curlDown(url: $url, path: FileSystem::convertPath(DOWNLOAD_PATH . "/{$filename}"), headers: $headers, hooks: $hooks, retries: self::getRetryAttempts()); - keyboard_interrupt_unregister(); - logger()->debug("Locking {$filename}"); - if ($download_as === SPC_DOWNLOAD_PRE_BUILT) { - $name = self::getPreBuiltLockName($name); - } - LockFile::lockSource($name, ['source_type' => SPC_SOURCE_ARCHIVE, 'filename' => $filename, 'move_path' => $move_path, 'lock_as' => $download_as]); - } - - /** - * Download Git repository - * - * @param string $name Repository name - * @param string $url Git repository URL - * @param string $branch Branch to checkout - * @param null|array $submodules Optional submodules to initialize - * @param null|string $move_path Optional move path after download - * @param int $retries Number of retry attempts - * @param int $lock_as Lock type constant - */ - public static function downloadGit(string $name, string $url, string $branch, ?array $submodules = null, ?string $move_path = null, int $retries = 0, int $lock_as = SPC_DOWNLOAD_SOURCE): void - { - $download_path = FileSystem::convertPath(DOWNLOAD_PATH . "/{$name}"); - if (file_exists($download_path)) { - FileSystem::removeDir($download_path); - } - logger()->debug("cloning {$name} source"); - - $quiet = !defined('DEBUG_MODE') ? '-q --quiet' : ''; - $git = SPC_GIT_EXEC; - $shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : ''; - $recursive = ($submodules === null && defined('GIT_SHALLOW_CLONE')) ? '--recursive --shallow-submodules' : null; - $recursive ??= $submodules === null ? '--recursive' : ''; - - try { - self::registerCancelEvent(function () use ($download_path) { - if (is_dir($download_path)) { - logger()->warning('Removing path ' . $download_path); - FileSystem::removeDir($download_path); - } - }); - f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\""); - if ($submodules !== null) { - $depth_flag = defined('GIT_SHALLOW_CLONE') ? '--depth 1' : ''; - foreach ($submodules as $submodule) { - f_passthru("cd \"{$download_path}\" && {$git} submodule update --init {$depth_flag} " . escapeshellarg($submodule)); - } - } - } catch (SPCException $e) { - if (is_dir($download_path)) { - FileSystem::removeDir($download_path); - } - if ($e->getCode() === 2 || $e->getCode() === -1073741510) { - throw new InterruptException('Keyboard interrupted, download failed !'); - } - if ($retries > 0) { - self::downloadGit($name, $url, $branch, $submodules, $move_path, $retries - 1, $lock_as); - return; - } - throw $e; - } finally { - self::unregisterCancelEvent(); - } - // Lock - logger()->debug("Locking git source {$name}"); - LockFile::lockSource($name, ['source_type' => SPC_SOURCE_GIT, 'dirname' => $name, 'move_path' => $move_path, 'lock_as' => $lock_as]); - - /* - // 复制目录过去 - if ($path !== $download_path) { - $dst_path = FileSystem::convertPath($path); - $src_path = FileSystem::convertPath($download_path); - switch (PHP_OS_FAMILY) { - case 'Windows': - f_passthru('xcopy "' . $src_path . '" "' . $dst_path . '" /s/e/v/y/i'); - break; - case 'Linux': - case 'Darwin': - f_passthru('cp -r "' . $src_path . '" "' . $dst_path . '"'); - break; - } - }*/ - } - - /** - * @param string $name Package name - * @param null|array{ - * type: string, - * repo: ?string, - * url: ?string, - * rev: ?string, - * path: ?string, - * filename: ?string, - * match: ?string, - * prefer-stable: ?bool, - * extract-files: ?array - * } $pkg Package config - * @param bool $force Download all the time even if it exists - */ - public static function downloadPackage(string $name, ?array $pkg = null, bool $force = false): void - { - if ($pkg === null) { - $pkg = Config::getPkg($name); - } - if ($pkg === null) { - logger()->warning('Package {name} unknown. Skipping.', ['name' => $name]); - return; - } - - if (!is_dir(DOWNLOAD_PATH)) { - FileSystem::createDir(DOWNLOAD_PATH); - } - - if (self::isAlreadyDownloaded($name, $force, SPC_DOWNLOAD_PACKAGE)) { - return; - } - self::downloadByType($pkg['type'], $name, $pkg, $force, SPC_DOWNLOAD_PACKAGE); - } - - /** - * Download source - * - * @param string $name source name - * @param null|array{ - * type: string, - * repo: ?string, - * url: ?string, - * rev: ?string, - * path: ?string, - * filename: ?string, - * match: ?string, - * prefer-stable: ?bool, - * provide-pre-built: ?bool, - * license: array{ - * type: string, - * path: ?string, - * text: ?string - * } - * } $source source meta info: [type, path, rev, url, filename, regex, license] - * @param bool $force Whether to force download (default: false) - * @param int $download_as Lock source type (default: SPC_LOCK_SOURCE) - */ - public static function downloadSource(string $name, ?array $source = null, bool $force = false, int $download_as = SPC_DOWNLOAD_SOURCE): void - { - if ($source === null) { - $source = Config::getSource($name); - } - if ($source === null) { - logger()->warning('Source {name} unknown. Skipping.', ['name' => $name]); - return; - } - - if (!is_dir(DOWNLOAD_PATH)) { - FileSystem::createDir(DOWNLOAD_PATH); - } - - // load lock file - if (self::isAlreadyDownloaded($name, $force, $download_as)) { - return; - } - - self::downloadByType($source['type'], $name, $source, $force, $download_as); - } - - /** - * Use curl command to get http response - * - * @param string $url Target URL - * @param string $method HTTP method (GET, POST, etc.) - * @param array $headers HTTP headers - * @param array $hooks Curl hooks - * @param int $retries Number of retry attempts - * @return string Response body - */ - public static function curlExec(string $url, string $method = 'GET', array $headers = [], array $hooks = [], int $retries = 0): string - { - foreach ($hooks as $hook) { - $hook($method, $url, $headers); - } - - FileSystem::findCommandPath('curl'); - - $methodArg = match ($method) { - 'GET' => '', - 'HEAD' => '-I', - default => "-X \"{$method}\"", - }; - $headerArg = implode(' ', array_map(fn ($v) => '"-H' . $v . '"', $headers)); - $retry = $retries > 0 ? "--retry {$retries}" : ''; - $cmd = SPC_CURL_EXEC . " -sfSL {$retry} {$methodArg} {$headerArg} \"{$url}\""; - if (getenv('CACHE_API_EXEC') === 'yes') { - if (!file_exists(FileSystem::convertPath(DOWNLOAD_PATH . '/.curl_exec_cache'))) { - $cache = []; - } else { - $cache = json_decode(file_get_contents(FileSystem::convertPath(DOWNLOAD_PATH . '/.curl_exec_cache')), true); - } - if (isset($cache[$cmd]) && $cache[$cmd]['expire'] >= time()) { - return $cache[$cmd]['cache']; - } - f_exec($cmd, $output, $ret); - if ($ret === 2 || $ret === -1073741510) { - throw new InterruptException(sprintf('Canceled fetching "%s"', $url)); - } - if ($ret !== 0) { - throw new DownloaderException(sprintf('Failed to fetch "%s"', $url)); - } - $cache[$cmd]['cache'] = implode("\n", $output); - $cache[$cmd]['expire'] = time() + 3600; - file_put_contents(FileSystem::convertPath(DOWNLOAD_PATH . '/.curl_exec_cache'), json_encode($cache)); - return $cache[$cmd]['cache']; - } - f_exec($cmd, $output, $ret); - if ($ret === 2 || $ret === -1073741510) { - throw new InterruptException(sprintf('Canceled fetching "%s"', $url)); - } - if ($ret !== 0) { - throw new DownloaderException(sprintf('Failed to fetch "%s"', $url)); - } - return implode("\n", $output); - } - - /** - * Use curl to download sources from url - * - * @param string $url Download URL - * @param string $path Target file path - * @param string $method HTTP method - * @param array $headers HTTP headers - * @param array $hooks Curl hooks - * @param int $retries Number of retry attempts - */ - public static function curlDown(string $url, string $path, string $method = 'GET', array $headers = [], array $hooks = [], int $retries = 0): void - { - $used_headers = $headers; - foreach ($hooks as $hook) { - $hook($method, $url, $used_headers); - } - - $methodArg = match ($method) { - 'GET' => '', - 'HEAD' => '-I', - default => "-X \"{$method}\"", - }; - $headerArg = implode(' ', array_map(fn ($v) => '"-H' . $v . '"', $used_headers)); - $check = !defined('DEBUG_MODE') ? 's' : '#'; - $retry = $retries > 0 ? "--retry {$retries}" : ''; - $cmd = SPC_CURL_EXEC . " -{$check}fSL {$retry} -o \"{$path}\" {$methodArg} {$headerArg} \"{$url}\""; - try { - f_passthru($cmd); - } catch (\Throwable $e) { - if ($e->getCode() === 2 || $e->getCode() === -1073741510) { - throw new InterruptException('Keyboard interrupted, download failed !'); - } - throw $e; - } - } - - /** - * Get pre-built lock name from source - * - * @param string $source Source name - * @return string Lock name - */ - public static function getPreBuiltLockName(string $source): string - { - $os_family = PHP_OS_FAMILY; - $gnu_arch = getenv('GNU_ARCH') ?: 'unknown'; - $libc = SPCTarget::getLibc(); - $libc_version = SPCTarget::getLibcVersion() ?? 'default'; - - return "{$source}-{$os_family}-{$gnu_arch}-{$libc}-{$libc_version}"; - } - - /** - * Get default alternative source - * - * @param string $source_name Source name - * @return array Alternative source configuration - */ - public static function getDefaultAlternativeSource(string $source_name): array - { - return [ - 'type' => 'custom', - 'func' => function (bool $force, array $source, int $download_as) use ($source_name) { - logger()->debug("Fetching alternative source for {$source_name}"); - // get from dl.static-php.dev - $url = "https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/{$source_name}/?format=json"; - $json = json_decode(Downloader::curlExec(url: $url, retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0)), true); - if (!is_array($json)) { - throw new DownloaderException('failed http fetch'); - } - $item = $json[0] ?? null; - if ($item === null) { - throw new DownloaderException('failed to parse json'); - } - $full_url = 'https://dl.static-php.dev' . $item['full_path']; - $filename = basename($item['full_path']); - Downloader::downloadFile($source_name, $full_url, $filename, $source['path'] ?? null, $download_as); - }, - ]; - } - - /** - * Register CTRL+C event for different OS. - * - * @param callable $callback callback function - */ - private static function registerCancelEvent(callable $callback): void - { - if (PHP_OS_FAMILY === 'Windows') { - sapi_windows_set_ctrl_handler($callback); - } elseif (extension_loaded('pcntl')) { - pcntl_signal(2, $callback); - } else { - logger()->debug('You have not enabled `pcntl` extension, cannot prevent download file corruption when Ctrl+C'); - } - } - - /** - * Unegister CTRL+C event for different OS. - */ - private static function unregisterCancelEvent(): void - { - if (PHP_OS_FAMILY === 'Windows') { - sapi_windows_set_ctrl_handler(null); - } elseif (extension_loaded('pcntl')) { - pcntl_signal(2, SIG_IGN); - } - } - - private static function getRetryAttempts(): int - { - return intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0); - } - - private static function isAlreadyDownloaded(string $name, bool $force, int $download_as = SPC_DOWNLOAD_SOURCE): bool - { - // If the lock file exists, skip downloading for source mode - $lock_item = LockFile::get($name); - if (!$force && $download_as === SPC_DOWNLOAD_SOURCE && $lock_item !== null) { - if (file_exists($path = LockFile::getLockFullPath($lock_item))) { - logger()->notice("Source [{$name}] already downloaded: {$path}"); - return true; - } - } - $lock_name = self::getPreBuiltLockName($name); - $lock_item = LockFile::get($lock_name); - if (!$force && $download_as === SPC_DOWNLOAD_PRE_BUILT && $lock_item !== null) { - // lock name with env - if (file_exists($path = LockFile::getLockFullPath($lock_item))) { - logger()->notice("Pre-built content [{$name}] already downloaded: {$path}"); - return true; - } - } - if (!$force && $download_as === SPC_DOWNLOAD_PACKAGE && $lock_item !== null) { - if (file_exists($path = LockFile::getLockFullPath($lock_item))) { - logger()->notice("Source [{$name}] already downloaded: {$path}"); - return true; - } - } - return false; - } - - /** - * Download by type. - * - * @param string $type Types - * @param string $name Download item name - * @param array{ - * url?: string, - * repo?: string, - * rev?: string, - * path?: string, - * filename?: string, - * dirname?: string, - * match?: string, - * prefer-stable?: bool, - * extract?: string, - * submodules?: array, - * provide-pre-built?: bool, - * func?: ?callable, - * license?: array - * } $conf Download item config - * @param bool $force Force download - * @param int $download_as Lock source type - */ - private static function downloadByType(string $type, string $name, array $conf, bool $force, int $download_as): void - { - try { - switch ($type) { - case 'pie': // Packagist - [$url, $filename] = self::getPIEInfo($name, $conf); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]); - break; - case 'bitbuckettag': // BitBucket Tag - [$url, $filename] = self::getLatestBitbucketTag($name, $conf); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as); - break; - case 'ghtar': // GitHub Release (tar) - [$url, $filename] = self::getLatestGithubTarball($name, $conf); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]); - break; - case 'ghtagtar': // GitHub Tag (tar) - [$url, $filename] = self::getLatestGithubTarball($name, $conf, 'tags'); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]); - break; - case 'ghrel': // GitHub Release (uploaded) - [$url, $filename] = self::getLatestGithubRelease($name, $conf); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, ['Accept: application/octet-stream'], [[CurlHook::class, 'setupGithubToken']]); - break; - case 'filelist': // Basic File List (regex based crawler) - [$url, $filename] = self::getFromFileList($name, $conf); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as); - break; - case 'url': // Direct download URL - $url = $conf['url']; - $filename = $conf['filename'] ?? basename($conf['url']); - self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as); - break; - case 'git': // Git repo - self::downloadGit($name, $conf['url'], $conf['rev'], $conf['submodules'] ?? null, $conf['path'] ?? $conf['extract'] ?? null, self::getRetryAttempts(), $download_as); - break; - case 'local': // Local directory, do nothing, just lock it - LockFile::lockSource($name, [ - 'source_type' => SPC_SOURCE_LOCAL, - 'dirname' => $conf['dirname'], - 'move_path' => $conf['path'] ?? $conf['extract'] ?? null, - 'lock_as' => $download_as, - ]); - break; - case 'custom': // Custom download method, like API-based download or other - if (isset($conf['func'])) { - $conf['name'] = $name; - $conf['func']($force, $conf, $download_as); - break; - } - $classes = [ - ...FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\store\source'), - ...FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg'), - ]; - foreach ($classes as $class) { - if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) { - (new $class())->fetch($force, $conf, $download_as); - break; - } - if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) { - $cls = new $class(); - if (in_array($name, $cls->getSupportName())) { - (new $class())->fetch($name, $force, $conf); - break; - } - } - } - break; - default: - throw new DownloaderException("Unknown download type: {$type}"); - } - } catch (\Throwable $e) { - // Because sometimes files downloaded through the command line are not automatically deleted after a failure. - // Here we need to manually delete the file if it is detected to exist. - if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) { - logger()->warning("Deleting download file: {$filename}"); - unlink(DOWNLOAD_PATH . '/' . $filename); - } - throw new DownloaderException("Download failed: {$e->getMessage()}"); - } - } -} diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php deleted file mode 100644 index d2d44b51..00000000 --- a/src/SPC/store/FileSystem.php +++ /dev/null @@ -1,761 +0,0 @@ -debug('Reading file: ' . $filename); - $r = file_get_contents(self::convertPath($filename)); - if ($r === false) { - throw new FileSystemException('Reading file ' . $filename . ' failed'); - } - return $r; - } - - /** - * Replace string content in file - * - * @param string $filename The file path - * @param mixed $search The search string - * @param mixed $replace The replacement string - * @return false|int Number of replacements or false on failure - */ - public static function replaceFileStr(string $filename, mixed $search = null, mixed $replace = null): false|int - { - return self::replaceFile($filename, REPLACE_FILE_STR, $search, $replace); - } - - /** - * Replace content in file using regex - * - * @param string $filename The file path - * @param mixed $search The regex pattern - * @param mixed $replace The replacement string - * @return false|int Number of replacements or false on failure - */ - public static function replaceFileRegex(string $filename, mixed $search = null, mixed $replace = null): false|int - { - return self::replaceFile($filename, REPLACE_FILE_PREG, $search, $replace); - } - - /** - * Replace content in file using custom callback - * - * @param string $filename The file path - * @param mixed $callback The callback function - * @return false|int Number of replacements or false on failure - */ - public static function replaceFileUser(string $filename, mixed $callback = null): false|int - { - return self::replaceFile($filename, REPLACE_FILE_USER, $callback); - } - - /** - * Get file extension from filename - * - * @param string $fn The filename - * @return string The file extension (without dot) - */ - public static function extname(string $fn): string - { - $parts = explode('.', basename($fn)); - if (count($parts) < 2) { - return ''; - } - return array_pop($parts); - } - - /** - * Find command path in system PATH (similar to which command) - * - * @param string $name The command name - * @param array $paths Optional array of paths to search - * @return null|string The full path to the command or null if not found - */ - public static function findCommandPath(string $name, array $paths = []): ?string - { - if (!$paths) { - $paths = explode(PATH_SEPARATOR, getenv('PATH')); - } - if (PHP_OS_FAMILY === 'Windows') { - foreach ($paths as $path) { - foreach (['.exe', '.bat', '.cmd'] as $suffix) { - if (file_exists($path . DIRECTORY_SEPARATOR . $name . $suffix)) { - return $path . DIRECTORY_SEPARATOR . $name . $suffix; - } - } - } - return null; - } - foreach ($paths as $path) { - if (file_exists($path . DIRECTORY_SEPARATOR . $name)) { - return $path . DIRECTORY_SEPARATOR . $name; - } - } - return null; - } - - /** - * Copy directory recursively - * - * @param string $from Source directory path - * @param string $to Destination directory path - */ - public static function copyDir(string $from, string $to): void - { - logger()->debug("Copying directory from {$from} to {$to}"); - $dst_path = FileSystem::convertPath($to); - $src_path = FileSystem::convertPath($from); - switch (PHP_OS_FAMILY) { - case 'Windows': - f_passthru('xcopy "' . $src_path . '" "' . $dst_path . '" /s/e/y/i'); - break; - case 'Linux': - case 'Darwin': - case 'BSD': - f_passthru('cp -r "' . $src_path . '" "' . $dst_path . '"'); - break; - } - } - - /** - * Copy file from one location to another. - * This method will throw an exception if the copy operation fails. - * - * @param string $from Source file path - * @param string $to Destination file path - */ - public static function copy(string $from, string $to): void - { - logger()->debug("Copying file from {$from} to {$to}"); - $dst_path = FileSystem::convertPath($to); - $src_path = FileSystem::convertPath($from); - if ($src_path === $dst_path) { - return; - } - if (!copy($src_path, $dst_path)) { - throw new FileSystemException('Cannot copy file from ' . $src_path . ' to ' . $dst_path); - } - } - - /** - * Extract package archive to specified directory - * - * @param string $name Package name - * @param string $source_type Archive type (tar.gz, zip, etc.) - * @param string $filename Archive filename - * @param null|string $extract_path Optional extraction path - */ - public static function extractPackage(string $name, string $source_type, string $filename, ?string $extract_path = null): void - { - if ($extract_path !== null) { - // replace - $extract_path = self::replacePathVariable($extract_path); - $extract_path = self::isRelativePath($extract_path) ? (WORKING_DIR . '/' . $extract_path) : $extract_path; - } else { - $extract_path = PKG_ROOT_PATH . '/' . $name; - } - logger()->info("Extracting {$name} package to {$extract_path} ..."); - $target = self::convertPath($extract_path); - - if (!is_dir($dir = dirname($target))) { - self::createDir($dir); - } - try { - // extract wrapper command - self::extractWithType($source_type, $filename, $extract_path); - } catch (SPCException $e) { - if (PHP_OS_FAMILY === 'Windows') { - f_passthru('rmdir /s /q ' . $target); - } else { - f_passthru('rm -rf ' . $target); - } - throw new FileSystemException("Cannot extract package {$name}", $e->getCode(), $e); - } - } - - /** - * Extract source archive to source directory - * - * @param string $name Source name - * @param string $source_type Archive type (tar.gz, zip, etc.) - * @param string $filename Archive filename - * @param null|string $move_path Optional move path - */ - public static function extractSource(string $name, string $source_type, string $filename, ?string $move_path = null): void - { - // if source hook is empty, load it - if (self::$_extract_hook === []) { - SourcePatcher::init(); - } - $move_path = match ($move_path) { - null => SOURCE_PATH . '/' . $name, - default => self::isRelativePath($move_path) ? (SOURCE_PATH . '/' . $move_path) : $move_path, - }; - $target = self::convertPath($move_path); - logger()->info("Extracting {$name} source to {$target}" . ' ...'); - if (!is_dir($dir = dirname($target))) { - self::createDir($dir); - } - try { - self::extractWithType($source_type, $filename, $move_path); - self::emitSourceExtractHook($name, $target); - } catch (SPCException $e) { - if (PHP_OS_FAMILY === 'Windows') { - f_passthru('rmdir /s /q ' . $target); - } else { - f_passthru('rm -rf ' . $target); - } - throw new FileSystemException('Cannot extract source ' . $name . ': ' . $e->getMessage(), $e->getCode(), $e); - } - } - - /** - * Convert path to system-specific format - * - * @param string $path The path to convert - * @return string The converted path - */ - public static function convertPath(string $path): string - { - if (str_starts_with($path, 'phar://')) { - return $path; - } - return str_replace('/', DIRECTORY_SEPARATOR, $path); - } - - /** - * Convert Windows path to MinGW format - * - * @param string $path The Windows path - * @return string The MinGW format path - */ - public static function convertWinPathToMinGW(string $path): string - { - if (preg_match('/^[A-Za-z]:/', $path)) { - $path = '/' . strtolower($path[0]) . '/' . str_replace('\\', '/', substr($path, 2)); - } - return $path; - } - - /** - * Scan directory files recursively - * - * @param string $dir Directory to scan - * @param bool $recursive Whether to scan recursively - * @param bool|string $relative Whether to return relative paths - * @param bool $include_dir Whether to include directories in result - * @return array|false Array of files or false on failure - */ - public static function scanDirFiles(string $dir, bool $recursive = true, bool|string $relative = false, bool $include_dir = false): array|false - { - $dir = self::convertPath($dir); - if (!is_dir($dir)) { - return false; - } - logger()->debug('scanning directory ' . $dir); - $scan_list = scandir($dir); - if ($scan_list === false) { - logger()->warning('Scan dir failed, cannot scan directory: ' . $dir); - return false; - } - $list = []; - // 将 relative 置为相对目录的前缀 - if ($relative === true) { - $relative = $dir; - } - // 遍历目录 - foreach ($scan_list as $v) { - // Unix 系统排除这俩目录 - if ($v == '.' || $v == '..') { - continue; - } - $sub_file = self::convertPath($dir . '/' . $v); - if (is_dir($sub_file) && $recursive) { - # 如果是 目录 且 递推 , 则递推添加下级文件 - $sub_list = self::scanDirFiles($sub_file, $recursive, $relative); - if (is_array($sub_list)) { - foreach ($sub_list as $item) { - $list[] = $item; - } - } - } elseif (is_file($sub_file) || (is_dir($sub_file) && !$recursive && $include_dir)) { - # 如果是 文件 或 (是 目录 且 不递推 且 包含目录) - if (is_string($relative) && mb_strpos($sub_file, $relative) === 0) { - $list[] = ltrim(mb_substr($sub_file, mb_strlen($relative)), '/\\'); - } elseif ($relative === false) { - $list[] = $sub_file; - } - } - } - return $list; - } - - /** - * Get PSR-4 classes from directory - * - * @param string $dir Directory to scan - * @param string $base_namespace Base namespace - * @param mixed $rule Optional filtering rule - * @param bool|string $return_path_value Whether to return path as value - * @return array Array of class names or class=>path pairs - */ - public static function getClassesPsr4(string $dir, string $base_namespace, mixed $rule = null, bool|string $return_path_value = false): array - { - $classes = []; - $files = FileSystem::scanDirFiles($dir, true, true); - if ($files === false) { - throw new FileSystemException('Cannot scan dir files during get classes psr-4 from dir: ' . $dir); - } - foreach ($files as $v) { - $pathinfo = pathinfo($v); - if (($pathinfo['extension'] ?? '') == 'php') { - if ($rule === null) { - if (file_exists($dir . '/' . $pathinfo['basename'] . '.ignore')) { - continue; - } - if (mb_substr($pathinfo['basename'], 0, 7) == 'global_' || mb_substr($pathinfo['basename'], 0, 7) == 'script_') { - continue; - } - } elseif (is_callable($rule) && !$rule($dir, $pathinfo)) { - continue; - } - $dirname = $pathinfo['dirname'] == '.' ? '' : (str_replace('/', '\\', $pathinfo['dirname']) . '\\'); - $class_name = $base_namespace . '\\' . $dirname . $pathinfo['filename']; - if (is_string($return_path_value)) { - $classes[$class_name] = $return_path_value . '/' . $v; - } else { - $classes[] = $class_name; - } - } - } - return $classes; - } - - /** - * Remove directory recursively - * - * @param string $dir Directory to remove - * @return bool Success status - */ - public static function removeDir(string $dir): bool - { - $dir = FileSystem::convertPath($dir); - logger()->debug('Removing path recursively: "' . $dir . '"'); - if (!file_exists($dir)) { - logger()->debug('Scan dir failed, no such file or directory.'); - return false; - } - if (!is_dir($dir)) { - logger()->warning('Scan dir failed, not directory.'); - return false; - } - logger()->debug('scanning directory ' . $dir); - // 套上 zm_dir - $scan_list = scandir($dir); - if ($scan_list === false) { - logger()->warning('Scan dir failed, cannot scan directory: ' . $dir); - return false; - } - // 遍历目录 - foreach ($scan_list as $v) { - // Unix 系统排除这俩目录 - if ($v == '.' || $v == '..') { - continue; - } - $sub_file = self::convertPath($dir . '/' . $v); - if (is_link($sub_file) || is_file($sub_file)) { - if (!unlink($sub_file)) { - return false; - } - } elseif (is_dir($sub_file)) { - # 如果是 目录 且 递推 , 则递推添加下级文件 - if (!self::removeDir($sub_file)) { - return false; - } - } - } - if (is_link($dir)) { - return unlink($dir); - } - return rmdir($dir); - } - - /** - * Create directory recursively - * - * @param string $path Directory path to create - */ - public static function createDir(string $path): void - { - if (!is_dir($path) && !f_mkdir($path, 0755, true) && !is_dir($path)) { - throw new FileSystemException(sprintf('Unable to create dir: %s', $path)); - } - } - - /** - * Write content to file - * - * @param string $path File path - * @param mixed $content Content to write - * @param mixed ...$args Additional arguments passed to file_put_contents - * @return bool|int|string Result of file writing operation - */ - public static function writeFile(string $path, mixed $content, ...$args): bool|int|string - { - $dir = pathinfo(self::convertPath($path), PATHINFO_DIRNAME); - if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) { - throw new FileSystemException('Write file failed, cannot create parent directory: ' . $dir); - } - return file_put_contents($path, $content, ...$args); - } - - /** - * Reset directory by removing and recreating it - * - * @param string $dir_name Directory name - */ - public static function resetDir(string $dir_name): void - { - $dir_name = self::convertPath($dir_name); - if (is_dir($dir_name)) { - self::removeDir($dir_name); - } - self::createDir($dir_name); - } - - /** - * Add source extraction hook - * - * @param string $name Source name - * @param callable $callback Callback function - */ - public static function addSourceExtractHook(string $name, callable $callback): void - { - self::$_extract_hook[$name][] = $callback; - } - - /** - * Check if path is relative - * - * @param string $path Path to check - * @return bool True if path is relative - */ - public static function isRelativePath(string $path): bool - { - if (DIRECTORY_SEPARATOR === '\\') { - return !(strlen($path) > 2 && ctype_alpha($path[0]) && $path[1] === ':'); - } - return strlen($path) > 0 && $path[0] !== '/'; - } - - /** - * Replace path variables with actual values - * - * @param string $path Path with variables - * @return string Path with replaced variables - */ - public static function replacePathVariable(string $path): string - { - $replacement = [ - '{pkg_root_path}' => PKG_ROOT_PATH, - '{php_sdk_path}' => getenv('PHP_SDK_PATH') ? getenv('PHP_SDK_PATH') : WORKING_DIR . '/php-sdk-binary-tools', - '{working_dir}' => WORKING_DIR, - '{download_path}' => DOWNLOAD_PATH, - '{source_path}' => SOURCE_PATH, - ]; - return str_replace(array_keys($replacement), array_values($replacement), $path); - } - - /** - * Create backup of file - * - * @param string $path File path - * @return string Backup file path - */ - public static function backupFile(string $path): string - { - copy($path, $path . '.bak'); - return $path . '.bak'; - } - - /** - * Restore file from backup - * - * @param string $path Original file path - */ - public static function restoreBackupFile(string $path): void - { - if (!file_exists($path . '.bak')) { - throw new FileSystemException("Backup restore failed: Cannot find bak file for {$path}"); - } - copy($path . '.bak', $path); - unlink($path . '.bak'); - } - - /** - * Remove file if it exists - * - * @param string $string File path - */ - public static function removeFileIfExists(string $string): void - { - $string = self::convertPath($string); - if (file_exists($string)) { - unlink($string); - } - } - - /** - * Replace line in file that contains specific string - * - * @param string $file File path - * @param string $find String to find in line - * @param string $line New line content - * @return false|int Number of replacements or false on failure - */ - public static function replaceFileLineContainsString(string $file, string $find, string $line): false|int - { - $lines = file($file); - if ($lines === false) { - throw new FileSystemException('Cannot read file: ' . $file); - } - foreach ($lines as $key => $value) { - if (str_contains($value, $find)) { - $lines[$key] = $line . PHP_EOL; - } - } - 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 - if (f_mkdir(directory: $target, recursive: true) !== true) { - throw new FileSystemException('create ' . $target . ' dir failed'); - } - if (!file_exists($filename)) { - throw new FileSystemException('File not exists'); - } - - if (in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD'])) { - match (self::extname($filename)) { - 'tar', 'xz', 'txz' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"), - 'tgz', 'gz' => f_passthru("tar -xzf {$filename} -C {$target} --strip-components 1"), - 'bz2' => f_passthru("tar -xjf {$filename} -C {$target} --strip-components 1"), - 'zip' => self::unzipWithStrip($filename, $target), - default => throw new FileSystemException('unknown archive format: ' . $filename), - }; - } elseif (PHP_OS_FAMILY === 'Windows') { - // use php-sdk-binary-tools/bin/7za.exe - $_7z = self::convertPath(getenv('PHP_SDK_PATH') . '/bin/7za.exe'); - - // Windows notes: I hate windows tar....... - // When extracting .tar.gz like libxml2, it shows a symlink error and returns code[1]. - // Related posts: https://answers.microsoft.com/en-us/windows/forum/all/tar-on-windows-fails-to-extract-archive-containing/0ee9a7ea-9b1f-4fef-86a9-5d9dc35cea2f - // And MinGW tar.exe cannot work on temporarily storage ??? (GitHub Actions hosted runner) - // Yeah, I will be an MS HATER ! - match (self::extname($filename)) { - 'tar' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"), - 'xz', 'txz', 'gz', 'tgz', 'bz2' => cmd()->execWithResult("\"{$_7z}\" x -so {$filename} | tar -f - -x -C \"{$target}\" --strip-components 1"), - 'zip' => self::unzipWithStrip($filename, $target), - default => throw new FileSystemException("unknown archive format: {$filename}"), - }; - } - } - - 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); - $file = self::readFile($filename); - switch ($replace_type) { - case REPLACE_FILE_STR: - default: - $file = str_replace($callback_or_search, $to_replace, $file); - break; - case REPLACE_FILE_PREG: - $file = preg_replace($callback_or_search, $to_replace, $file); - break; - case REPLACE_FILE_USER: - $file = $callback_or_search($file); - break; - } - return file_put_contents($filename, $file); - } - - private static function emitSourceExtractHook(string $name, string $target): void - { - foreach ((self::$_extract_hook[$name] ?? []) as $hook) { - if ($hook($name, $target) === true) { - logger()->info('Patched source [' . $name . '] after extracted'); - } - } - } - - private static function extractWithType(string $source_type, string $filename, string $extract_path): void - { - logger()->debug("Extracting source [{$source_type}]: {$filename}"); - /* @phpstan-ignore-next-line */ - match ($source_type) { - SPC_SOURCE_ARCHIVE => self::extractArchive($filename, $extract_path), - SPC_SOURCE_GIT => self::copyDir(self::convertPath($filename), $extract_path), - // soft link to the local source - SPC_SOURCE_LOCAL => symlink(self::convertPath($filename), $extract_path), - }; - } - - /** - * Unzip file with stripping top-level directory - */ - private static function unzipWithStrip(string $zip_file, string $extract_path): void - { - $temp_dir = self::convertPath(sys_get_temp_dir() . '/spc_unzip_' . bin2hex(random_bytes(16))); - $zip_file = self::convertPath($zip_file); - $extract_path = self::convertPath($extract_path); - - // extract to temp dir - self::createDir($temp_dir); - - if (PHP_OS_FAMILY === 'Windows') { - $mute = defined('DEBUG_MODE') ? '' : ' > NUL'; - // use php-sdk-binary-tools/bin/7za.exe - $_7z = self::convertPath(getenv('PHP_SDK_PATH') . '/bin/7za.exe'); - f_passthru("\"{$_7z}\" x {$zip_file} -o{$temp_dir} -y{$mute}"); - } else { - $mute = defined('DEBUG_MODE') ? '' : ' > /dev/null'; - f_passthru("unzip \"{$zip_file}\" -d \"{$temp_dir}\"{$mute}"); - } - // scan first level dirs (relative, not recursive, include dirs) - $contents = self::scanDirFiles($temp_dir, false, true, true); - if ($contents === false) { - throw new FileSystemException('Cannot scan unzip temp dir: ' . $temp_dir); - } - // if extract path already exists, remove it - if (is_dir($extract_path)) { - self::removeDir($extract_path); - } - // if only one dir, move its contents to extract_path - $subdir = self::convertPath("{$temp_dir}/{$contents[0]}"); - if (count($contents) === 1 && is_dir($subdir)) { - self::moveFileOrDir($subdir, $extract_path); - } else { - // else, if it contains only one dir, strip dir and copy other files - $dircount = 0; - $dir = []; - $top_files = []; - foreach ($contents as $item) { - if (is_dir(self::convertPath("{$temp_dir}/{$item}"))) { - ++$dircount; - $dir[] = $item; - } else { - $top_files[] = $item; - } - } - // extract dir contents to extract_path - self::createDir($extract_path); - // extract move dir - if ($dircount === 1) { - $sub_contents = self::scanDirFiles("{$temp_dir}/{$dir[0]}", false, true, true); - if ($sub_contents === false) { - throw new FileSystemException("Cannot scan unzip temp sub-dir: {$dir[0]}"); - } - foreach ($sub_contents as $sub_item) { - self::moveFileOrDir(self::convertPath("{$temp_dir}/{$dir[0]}/{$sub_item}"), self::convertPath("{$extract_path}/{$sub_item}")); - } - } else { - foreach ($dir as $item) { - self::moveFileOrDir(self::convertPath("{$temp_dir}/{$item}"), self::convertPath("{$extract_path}/{$item}")); - } - } - // move top-level files to extract_path - foreach ($top_files as $top_file) { - self::moveFileOrDir(self::convertPath("{$temp_dir}/{$top_file}"), self::convertPath("{$extract_path}/{$top_file}")); - } - } - - // Clean up temp directory - self::removeDir($temp_dir); - } -} diff --git a/src/SPC/store/LockFile.php b/src/SPC/store/LockFile.php deleted file mode 100644 index 88ecd6cb..00000000 --- a/src/SPC/store/LockFile.php +++ /dev/null @@ -1,215 +0,0 @@ -warning("Lock entry for '{$lock_name}' has 'source_type' set to 'dir', which is deprecated. Please re-download your dependencies."); - $result['source_type'] = SPC_SOURCE_GIT; - } - - return $result; - } - - /** - * Check if a lock file exists for a given lock name. - * - * @param string $lock_name Lock name to check - */ - public static function isLockFileExists(string $lock_name): bool - { - return match (self::get($lock_name)['source_type'] ?? null) { - SPC_SOURCE_ARCHIVE => file_exists(DOWNLOAD_PATH . '/' . (self::get($lock_name)['filename'] ?? '.never-exist-file')), - SPC_SOURCE_GIT, SPC_SOURCE_LOCAL => is_dir(DOWNLOAD_PATH . '/' . (self::get($lock_name)['dirname'] ?? '.never-exist-dir')), - default => false, - }; - } - - /** - * Put a lock entry into the lock file. - * - * @param string $lock_name Lock name to set or remove - * @param null|array $lock_content lock content to set, or null to remove the lock entry - */ - public static function put(string $lock_name, ?array $lock_content): void - { - self::init(); - - if ($lock_content === null && isset(self::$lock_file_content[$lock_name])) { - self::removeLockFileIfExists(self::$lock_file_content[$lock_name]); - unset(self::$lock_file_content[$lock_name]); - } else { - self::$lock_file_content[$lock_name] = $lock_content; - } - - // Write the updated lock data back to the file - FileSystem::createDir(dirname(self::LOCK_FILE)); - file_put_contents(self::LOCK_FILE, json_encode(self::$lock_file_content, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); - } - - /** - * Get the full path of a lock file or directory based on the lock options. - * - * @param array $lock_options lock item options, must contain 'source_type', 'filename' or 'dirname' - * @return string the absolute path to the lock file or directory - */ - public static function getLockFullPath(array $lock_options): string - { - return match ($lock_options['source_type']) { - SPC_SOURCE_ARCHIVE => FileSystem::isRelativePath($lock_options['filename']) ? (DOWNLOAD_PATH . '/' . $lock_options['filename']) : $lock_options['filename'], - SPC_SOURCE_GIT, SPC_SOURCE_LOCAL => FileSystem::isRelativePath($lock_options['dirname']) ? (DOWNLOAD_PATH . '/' . $lock_options['dirname']) : $lock_options['dirname'], - default => throw new WrongUsageException("Unknown source type: {$lock_options['source_type']}"), - }; - } - - public static function getExtractPath(string $lock_name, string $default_path): ?string - { - $lock = self::get($lock_name); - if ($lock === null) { - return null; - } - - // If move_path is set, use it; otherwise, use the default extract directory - if (isset($lock['move_path'])) { - if (FileSystem::isRelativePath($lock['move_path'])) { - // If move_path is relative, prepend the default extract directory - return match ($lock['lock_as']) { - SPC_DOWNLOAD_SOURCE, SPC_DOWNLOAD_PRE_BUILT => FileSystem::convertPath(SOURCE_PATH . '/' . $lock['move_path']), - SPC_DOWNLOAD_PACKAGE => FileSystem::convertPath(PKG_ROOT_PATH . '/' . $lock['move_path']), - default => throw new WrongUsageException("Unknown lock type: {$lock['lock_as']}"), - }; - } - return FileSystem::convertPath($lock['move_path']); - } - return FileSystem::convertPath($default_path); - } - - /** - * Get the hash of the lock source based on the lock options. - * - * @param array $lock_options Lock options - * @return string Hash of the lock source - */ - public static function getLockSourceHash(array $lock_options): string - { - $result = match ($lock_options['source_type']) { - SPC_SOURCE_ARCHIVE => sha1_file(DOWNLOAD_PATH . '/' . $lock_options['filename']), - SPC_SOURCE_GIT => exec('cd ' . escapeshellarg(DOWNLOAD_PATH . '/' . $lock_options['dirname']) . ' && ' . SPC_GIT_EXEC . ' rev-parse HEAD'), - SPC_SOURCE_LOCAL => 'LOCAL HASH IS ALWAYS DIFFERENT', - default => filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN) ? '' : throw new SPCInternalException("Unknown source type: {$lock_options['source_type']}"), - }; - if ($result === false && !filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN)) { - throw new SPCInternalException("Failed to get hash for source: {$lock_options['source_type']}"); - } - return $result ?: ''; - } - - /** - * @param array $lock_options Lock options - * @param string $destination Target directory - */ - public static function putLockSourceHash(array $lock_options, string $destination): void - { - $hash = LockFile::getLockSourceHash($lock_options); - if ($lock_options['source_type'] === SPC_SOURCE_LOCAL) { - logger()->debug("Source [{$lock_options['dirname']}] is local, no hash will be written."); - return; - } - FileSystem::writeFile("{$destination}/.spc-hash", $hash); - } - - /** - * Try to lock source with hash. - * - * @param string $name Source name - * @param array{ - * source_type: string, - * dirname?: ?string, - * filename?: ?string, - * move_path: ?string, - * lock_as: int - * } $data Source data - */ - public static function lockSource(string $name, array $data): void - { - // calculate hash - $hash = LockFile::getLockSourceHash($data); - $data['hash'] = $hash; - self::put($name, $data); - } - - private static function init(): void - { - if (self::$lock_file_content === null) { - // Initialize the lock file content if it hasn't been loaded yet - if (!file_exists(self::LOCK_FILE)) { - logger()->debug('Lock file does not exist: ' . self::LOCK_FILE . ', initializing empty lock file.'); - self::$lock_file_content = []; - file_put_contents(self::LOCK_FILE, json_encode(self::$lock_file_content, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); - } else { - $file_content = file_get_contents(self::LOCK_FILE); - self::$lock_file_content = json_decode($file_content, true); - if (self::$lock_file_content === null) { - throw new SPCInternalException('Failed to decode lock file: ' . self::LOCK_FILE); - } - } - } - } - - /** - * Remove the lock file or directory if it exists. - * - * @param array $lock_options lock item options, must contain 'source_type', 'filename' or 'dirname' - */ - private static function removeLockFileIfExists(array $lock_options): void - { - if ($lock_options['source_type'] === SPC_SOURCE_ARCHIVE) { - $path = self::getLockFullPath($lock_options); - if (file_exists($path)) { - logger()->info('Removing file ' . $path); - unlink($path); - } else { - logger()->debug("Lock file [{$lock_options['filename']}] not found, skip removing file."); - } - } else { - $path = self::getLockFullPath($lock_options); - if (is_dir($path)) { - logger()->info('Removing directory ' . $path); - FileSystem::removeDir($path); - } else { - logger()->debug("Lock directory [{$lock_options['dirname']}] not found, skip removing directory."); - } - } - } -} diff --git a/src/SPC/store/PackageManager.php b/src/SPC/store/PackageManager.php deleted file mode 100644 index dc662a5b..00000000 --- a/src/SPC/store/PackageManager.php +++ /dev/null @@ -1,110 +0,0 @@ - 'linux', - 'Windows' => 'win', - 'BSD' => 'freebsd', - 'Darwin' => 'macos', - default => throw new WrongUsageException('Unsupported OS!'), - }; - $config = Config::getPkg("{$pkg_name}-{$arch}-{$os}"); - $pkg_name = "{$pkg_name}-{$arch}-{$os}"; - } - if ($config === null) { - throw new WrongUsageException("Package [{$pkg_name}] does not exist, please check the name and correct it !"); - } - - // Download package - try { - Downloader::downloadPackage($pkg_name, $config, $force); - } catch (\Throwable $e) { - if (!$allow_alt) { - throw new DownloaderException("Download package {$pkg_name} failed: " . $e->getMessage()); - } - // if download failed, we will try to download alternative packages - logger()->warning("Download package {$pkg_name} failed: " . $e->getMessage()); - $alt = $config['alt'] ?? null; - if ($alt === null) { - logger()->warning("No alternative package found for {$pkg_name}, using default mirror."); - $alt_config = array_merge($config, Downloader::getDefaultAlternativeSource($pkg_name)); - } elseif ($alt === false) { - logger()->error("No alternative package found for {$pkg_name}."); - throw $e; - } else { - logger()->notice("Trying alternative package for {$pkg_name}."); - $alt_config = array_merge($config, $alt); - } - Downloader::downloadPackage($pkg_name, $alt_config, $force); - } - if (!$extract) { - logger()->info("Package [{$pkg_name}] downloaded, but extraction is skipped."); - return; - } - if (Config::getPkg($pkg_name)['type'] === 'custom') { - // Custom extract function - $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg'); - foreach ($classes as $class) { - if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) { - $cls = new $class(); - if (in_array($pkg_name, $cls->getSupportName())) { - (new $class())->extract($pkg_name); - break; - } - } - } - return; - } - // After download, read lock file name - $lock = LockFile::get($pkg_name); - $source_type = $lock['source_type']; - $filename = LockFile::getLockFullPath($lock); - $extract = LockFile::getExtractPath($pkg_name, PKG_ROOT_PATH . '/' . $pkg_name); - - FileSystem::extractPackage($pkg_name, $source_type, $filename, $extract); - - // if contains extract-files, we just move this file to destination, and remove extract dir - if (is_array($config['extract-files'] ?? null) && is_assoc_array($config['extract-files'])) { - $scandir = FileSystem::scanDirFiles($extract, true, true); - foreach ($config['extract-files'] as $file => $target) { - $target = FileSystem::convertPath(FileSystem::replacePathVariable($target)); - if (!is_dir($dir = dirname($target))) { - f_mkdir($dir, 0755, true); - } - logger()->debug("Moving package [{$pkg_name}] file {$file} to {$target}"); - // match pattern, needs to scan dir - $file = FileSystem::convertPath($file); - $found = false; - foreach ($scandir as $item) { - if (match_pattern($file, $item)) { - $file = $item; - $found = true; - break; - } - } - if ($found === false) { - throw new FileSystemException('Unable to find extract-files item: ' . $file); - } - rename(FileSystem::convertPath($extract . '/' . $file), $target); - } - FileSystem::removeDir($extract); - } - } -} diff --git a/src/SPC/store/SourceManager.php b/src/SPC/store/SourceManager.php deleted file mode 100644 index 35728e22..00000000 --- a/src/SPC/store/SourceManager.php +++ /dev/null @@ -1,97 +0,0 @@ - $item) { - if (Config::getSource($source) === null) { - throw new WrongUsageException("Source [{$source}] does not exist, please check the name and correct it !"); - } - // check source downloaded - $pre_built_name = Downloader::getPreBuiltLockName($source); - if ($source_only || LockFile::get($pre_built_name) === null) { - if (LockFile::get($source) === null) { - throw new WrongUsageException("Source [{$source}] not downloaded or not locked, you should download it first !"); - } - $lock_name = $source; - } else { - $lock_name = $pre_built_name; - } - - $lock_content = LockFile::get($lock_name); - - // check source dir exist - $check = LockFile::getExtractPath($lock_name, SOURCE_PATH . '/' . $source); - // $check = $lock[$lock_name]['move_path'] === null ? (SOURCE_PATH . '/' . $source) : (SOURCE_PATH . '/' . $lock[$lock_name]['move_path']); - if (!is_dir($check)) { - logger()->debug("Extracting source [{$source}] to {$check} ..."); - $filename = LockFile::getLockFullPath($lock_content); - FileSystem::extractSource($source, $lock_content['source_type'], $filename, $check); - LockFile::putLockSourceHash($lock_content, $check); - continue; - } - // if a lock file does not have hash, calculate with the current source (backward compatibility) - if (!isset($lock_content['hash'])) { - $hash = LockFile::getLockSourceHash($lock_content); - } else { - $hash = $lock_content['hash']; - } - - // when source already extracted, detect if the extracted source hash is the same as the lock file one - if (file_exists("{$check}/.spc-hash") && FileSystem::readFile("{$check}/.spc-hash") === $hash) { - logger()->debug("Source [{$source}] already extracted in {$check}, skip !"); - continue; - } - - // ext imap was included in php < 8.4 which we should not extract, - // but since it's not simple to compare php version, for now we just skip it - if ($source === 'ext-imap') { - logger()->debug("Source [ext-imap] already extracted in {$check}, skip !"); - continue; - } - - // if not, remove the source dir and extract again - logger()->notice("Source [{$source}] hash mismatch, removing old source dir and extracting again ..."); - FileSystem::removeDir($check); - $filename = LockFile::getLockFullPath($lock_content); - $move_path = LockFile::getExtractPath($lock_name, SOURCE_PATH . '/' . $source); - FileSystem::extractSource($source, $lock_content['source_type'], $filename, $move_path); - LockFile::putLockSourceHash($lock_content, $check); - } - } -} diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php deleted file mode 100644 index 43b750c4..00000000 --- a/src/SPC/store/SourcePatcher.php +++ /dev/null @@ -1,685 +0,0 @@ -getExts() as $ext) { - if ($ext->patchBeforeBuildconf() === true) { - logger()->info("Extension [{$ext->getName()}] patched before buildconf"); - } - } - foreach ($builder->getLibs() as $lib) { - if ($lib->patchBeforeBuildconf() === true) { - logger()->info("Library [{$lib->getName()}] patched before buildconf"); - } - } - // patch windows php 8.1 bug - if (PHP_OS_FAMILY === 'Windows' && $builder->getPHPVersionID() >= 80100 && $builder->getPHPVersionID() < 80200) { - logger()->info('Patching PHP 8.1 windows Fiber bug'); - FileSystem::replaceFileStr( - SOURCE_PATH . '\php-src\win32\build\config.w32', - "ADD_FLAG('LDFLAGS', '$(BUILD_DIR)\\\\Zend\\\\jump_' + FIBER_ASM_ARCH + '_ms_pe_masm.obj');", - "ADD_FLAG('ASM_OBJS', '$(BUILD_DIR)\\\\Zend\\\\jump_' + FIBER_ASM_ARCH + '_ms_pe_masm.obj $(BUILD_DIR)\\\\Zend\\\\make_' + FIBER_ASM_ARCH + '_ms_pe_masm.obj');" - ); - FileSystem::replaceFileStr( - SOURCE_PATH . '\php-src\win32\build\config.w32', - "ADD_FLAG('LDFLAGS', '$(BUILD_DIR)\\\\Zend\\\\make_' + FIBER_ASM_ARCH + '_ms_pe_masm.obj');", - '' - ); - } - - // Fix PHP VS version - if ($builder instanceof WindowsBuilder) { - // get vs version - $vc = \SPC\builder\windows\SystemUtil::findVisualStudio(); - $vc_matches = match ($vc['version']) { - 'vs17' => ['VS17', 'Visual C++ 2022'], - 'vs16' => ['VS16', 'Visual C++ 2019'], - default => ['unknown', 'unknown'], - }; - // patch php-src/win32/build/confutils.js - FileSystem::replaceFileStr( - SOURCE_PATH . '\php-src\win32\build\confutils.js', - 'var name = "unknown";', - "var name = short ? \"{$vc_matches[0]}\" : \"{$vc_matches[1]}\";return name;" - ); - } - - // patch configure.ac - $musl = SPCTarget::getLibc() === 'musl'; - FileSystem::backupFile(SOURCE_PATH . '/php-src/configure.ac'); - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/configure.ac', - 'if command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1', - 'if ' . ($musl ? 'true' : 'false') - ); - if (getenv('SPC_LIBC') === false && ($libc = SPCTarget::getLibc()) !== null) { - putenv("SPC_LIBC={$libc}"); - } - - // patch php-src/build/php.m4 PKG_CHECK_MODULES -> PKG_CHECK_MODULES_STATIC - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/build/php.m4', 'PKG_CHECK_MODULES(', 'PKG_CHECK_MODULES_STATIC('); - - if ($builder->getOption('enable-micro-win32')) { - self::patchMicroWin32(); - } else { - self::unpatchMicroWin32(); - } - } - - /** - * Source patcher runner before configure - * - * @param BuilderBase $builder Builder - */ - public static function patchBeforeConfigure(BuilderBase $builder): void - { - foreach ($builder->getExts() as $ext) { - $patch = $builder instanceof WindowsBuilder ? $ext->patchBeforeWindowsConfigure() : $ext->patchBeforeConfigure(); - if ($patch === true) { - logger()->info("Extension [{$ext->getName()}] patched before configure"); - } - } - foreach ($builder->getLibs() as $lib) { - if ($lib->patchBeforeConfigure() === true) { - logger()->info("Library [{$lib->getName()}] patched before configure"); - } - } - // patch capstone - if (is_unix()) { - FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"'); - } - - if (file_exists(SOURCE_PATH . '/php-src/configure.ac.bak')) { - // restore configure.ac - FileSystem::restoreBackupFile(SOURCE_PATH . '/php-src/configure.ac'); - } - } - - public static function patchMicro(?array $items = null): bool - { - if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) { - return false; - } - $ver_file = SOURCE_PATH . '/php-src/main/php_version.h'; - if (!file_exists($ver_file)) { - throw new FileSystemException('Patch failed, cannot find php source files'); - } - $version_h = FileSystem::readFile(SOURCE_PATH . '/php-src/main/php_version.h'); - preg_match('/#\s*define\s+PHP_MAJOR_VERSION\s+(\d+)\s+#\s*define\s+PHP_MINOR_VERSION\s+(\d+)\s+/m', $version_h, $match); - // $ver = "{$match[1]}.{$match[2]}"; - - $major_ver = $match[1] . $match[2]; - if ($major_ver === '74') { - return false; - } - // $check = !defined('DEBUG_MODE') ? ' -q' : ''; - // f_passthru('cd ' . SOURCE_PATH . '/php-src && git checkout' . $check . ' HEAD'); - - if ($items !== null) { - $spc_micro_patches = $items; - } else { - $spc_micro_patches = getenv('SPC_MICRO_PATCHES'); - $spc_micro_patches = $spc_micro_patches === false ? [] : explode(',', $spc_micro_patches); - } - $spc_micro_patches = array_filter($spc_micro_patches, fn ($item) => trim((string) $item) !== ''); - $patch_list = $spc_micro_patches; - $patches = []; - $serial = ['80', '81', '82', '83', '84', '85']; - foreach ($patch_list as $patchName) { - if (file_exists(SOURCE_PATH . "/php-src/sapi/micro/patches/{$patchName}.patch")) { - $patches[] = "sapi/micro/patches/{$patchName}.patch"; - continue; - } - for ($i = array_search($major_ver, $serial, true); $i >= 0; --$i) { - $tryMajMin = $serial[$i]; - if (!file_exists(SOURCE_PATH . "/php-src/sapi/micro/patches/{$patchName}_{$tryMajMin}.patch")) { - continue; - } - $patches[] = "sapi/micro/patches/{$patchName}_{$tryMajMin}.patch"; - continue 2; - } - throw new PatchException('phpmicro patches', "Failed finding patch file or versioned file {$patchName} !"); - } - - foreach ($patches as $patch) { - logger()->info("Patching micro with {$patch}"); - self::patchFile(SOURCE_PATH . "/php-src/{$patch}", SOURCE_PATH . '/php-src'); - } - - return true; - } - - /** - * Use existing patch file for patching - * - * @param string $patch_name Patch file name in src/globals/patch/ or absolute path - * @param string $cwd Working directory for patch command - * @param bool $reverse Reverse patches (default: False) - */ - public static function patchFile(string $patch_name, string $cwd, bool $reverse = false): bool - { - try { - if (FileSystem::isRelativePath($patch_name)) { - $patch_file = ROOT_DIR . "/src/globals/patch/{$patch_name}"; - } else { - $patch_file = $patch_name; - } - if (!file_exists($patch_file)) { - return false; - } - - $patch_str = FileSystem::convertPath($patch_file); - if (!file_exists($patch_str)) { - throw new PatchException($patch_name, "Patch file [{$patch_str}] does not exist"); - } - - // Copy patch from phar - if (str_starts_with($patch_str, 'phar://')) { - $filename = pathinfo($patch_file, PATHINFO_BASENAME); - file_put_contents(SOURCE_PATH . "/{$filename}", file_get_contents($patch_file)); - $patch_str = FileSystem::convertPath(SOURCE_PATH . "/{$filename}"); - } - - // detect - $detect_reverse = !$reverse; - $detect_cmd = 'cd ' . escapeshellarg($cwd) . ' && ' - . (PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . escapeshellarg($patch_str) - . ' | patch --dry-run -p1 -s -f ' . ($detect_reverse ? '-R' : '') - . ' > ' . (PHP_OS_FAMILY === 'Windows' ? 'NUL' : '/dev/null') . ' 2>&1'; - exec($detect_cmd, $output, $detect_status); - - if ($detect_status === 0) { - return true; - } - - // apply patch - $apply_cmd = 'cd ' . escapeshellarg($cwd) . ' && ' - . (PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . escapeshellarg($patch_str) - . ' | patch -p1 ' . ($reverse ? '-R' : ''); - - f_passthru($apply_cmd); - return true; - } catch (ExecutionException $e) { - // If patch failed, throw exception - throw new PatchException($patch_name, "Patch file [{$patch_name}] failed to apply", previous: $e); - } - } - - public static function patchOpenssl11Darwin(): bool - { - if (PHP_OS_FAMILY === 'Darwin' && !file_exists(SOURCE_PATH . '/openssl/VERSION.dat') && file_exists(SOURCE_PATH . '/openssl/test/v3ext.c')) { - FileSystem::replaceFileStr(SOURCE_PATH . '/openssl/test/v3ext.c', '#include ', '#include ' . PHP_EOL . '#include '); - return true; - } - return false; - } - - public static function patchSwoole(): bool - { - // swoole hook needs pdo/pdo.h - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/swoole/config.m4', - 'PHP_ADD_INCLUDE([$ext_srcdir])', - "PHP_ADD_INCLUDE( [\$ext_srcdir] )\n PHP_ADD_INCLUDE([\$abs_srcdir/ext])" - ); - - // swoole 5.1.3 build fix - // get swoole version first - $file = SOURCE_PATH . '/php-src/ext/swoole/include/swoole_version.h'; - // Match #define SWOOLE_VERSION "5.1.3" - $pattern = '/#define SWOOLE_VERSION "(.+)"/'; - if (preg_match($pattern, file_get_contents($file), $matches)) { - $version = $matches[1]; - } else { - $version = '1.0.0'; - } - if ($version === '5.1.3') { - self::patchFile('spc_fix_swoole_50513.patch', SOURCE_PATH . '/php-src/ext/swoole'); - } - if (version_compare($version, '6.0.0', '>=') && version_compare($version, '6.1.0', '<')) { - // remove when https://github.com/swoole/swoole-src/pull/5848 is merged - self::patchFile('swoole_fix_date_time.patch', SOURCE_PATH . '/php-src/ext/swoole'); - // remove when https://github.com/swoole/swoole-src/pull/5847 is merged - self::patchFile('swoole_fix_odbclibs.patch', SOURCE_PATH . '/php-src/ext/swoole'); - } - return true; - } - - public static function patchBeforeMake(BuilderBase $builder): void - { - if ($builder instanceof UnixBuilderBase) { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'install-micro', ''); - } - if (!SPCTarget::isStatic() && SPCTarget::getLibc() === 'musl') { - // we need to patch the symbol to global visibility, otherwise extensions with `initial-exec` TLS model will fail to load - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/TSRM/TSRM.h', - '#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;', - '#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS __attribute__((visibility("default"))) void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;', - ); - } else { - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/TSRM/TSRM.h', - '#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS __attribute__((visibility("default"))) void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;', - '#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;', - ); - } - - // no asan - // if (strpos(file_get_contents(SOURCE_PATH . '/php-src/Makefile'), 'CFLAGS_CLEAN = -g') === false) { - // FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'CFLAGS_CLEAN = ', 'CFLAGS_CLEAN = -g -fsanitize=address '); - // } - - // call extension patch before make - foreach ($builder->getExts() as $ext) { - if ($ext->patchBeforeMake() === true) { - logger()->info("Extension [{$ext->getName()}] patched before make"); - } - } - foreach ($builder->getLibs() as $lib) { - if ($lib->patchBeforeMake() === true) { - logger()->info("Library [{$lib->getName()}] patched before make"); - } - } - - if (str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), '-release')) { - FileSystem::replaceFileLineContainsString( - SOURCE_PATH . '/php-src/ext/standard/info.c', - '#ifdef CONFIGURE_COMMAND', - '#ifdef NO_CONFIGURE_COMMAND', - ); - } else { - FileSystem::replaceFileLineContainsString( - SOURCE_PATH . '/php-src/ext/standard/info.c', - '#ifdef NO_CONFIGURE_COMMAND', - '#ifdef CONFIGURE_COMMAND', - ); - } - } - - public static function patchHardcodedINI(array $ini = []): bool - { - $cli_c = SOURCE_PATH . '/php-src/sapi/cli/php_cli.c'; - $cli_c_bak = SOURCE_PATH . '/php-src/sapi/cli/php_cli.c.bak'; - $micro_c = SOURCE_PATH . '/php-src/sapi/micro/php_micro.c'; - $micro_c_bak = SOURCE_PATH . '/php-src/sapi/micro/php_micro.c.bak'; - $embed_c = SOURCE_PATH . '/php-src/sapi/embed/php_embed.c'; - $embed_c_bak = SOURCE_PATH . '/php-src/sapi/embed/php_embed.c.bak'; - - // Try to reverse backup file - $find_str = 'const char HARDCODED_INI[] ='; - $patch_str = ''; - foreach ($ini as $key => $value) { - $patch_str .= "\"{$key}={$value}\\n\"\n"; - } - $patch_str = "const char HARDCODED_INI[] =\n{$patch_str}"; - - // Detect backup, if we have backup, it means we need to reverse first - if (file_exists($cli_c_bak) || file_exists($micro_c_bak) || file_exists($embed_c_bak)) { - self::unpatchHardcodedINI(); - } - - // Backup it - $result = file_put_contents($cli_c_bak, file_get_contents($cli_c)); - $result = $result && file_put_contents($micro_c_bak, file_get_contents($micro_c)); - $result = $result && file_put_contents($embed_c_bak, file_get_contents($embed_c)); - if ($result === false) { - return false; - } - - // Patch it - FileSystem::replaceFileStr($cli_c, $find_str, $patch_str); - FileSystem::replaceFileStr($micro_c, $find_str, $patch_str); - FileSystem::replaceFileStr($embed_c, $find_str, $patch_str); - return true; - } - - public static function unpatchHardcodedINI(): bool - { - $cli_c = SOURCE_PATH . '/php-src/sapi/cli/php_cli.c'; - $cli_c_bak = SOURCE_PATH . '/php-src/sapi/cli/php_cli.c.bak'; - $micro_c = SOURCE_PATH . '/php-src/sapi/micro/php_micro.c'; - $micro_c_bak = SOURCE_PATH . '/php-src/sapi/micro/php_micro.c.bak'; - $embed_c = SOURCE_PATH . '/php-src/sapi/embed/php_embed.c'; - $embed_c_bak = SOURCE_PATH . '/php-src/sapi/embed/php_embed.c.bak'; - if (!file_exists($cli_c_bak) && !file_exists($micro_c_bak) && !file_exists($embed_c_bak)) { - return false; - } - $result = file_put_contents($cli_c, file_get_contents($cli_c_bak)); - $result = $result && file_put_contents($micro_c, file_get_contents($micro_c_bak)); - $result = $result && file_put_contents($embed_c, file_get_contents($embed_c_bak)); - @unlink($cli_c_bak); - @unlink($micro_c_bak); - @unlink($embed_c_bak); - return $result; - } - - public static function patchMicroPhar(int $version_id): void - { - FileSystem::backupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c'); - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/phar/phar.c', - 'static zend_op_array *phar_compile_file', - "char *micro_get_filename(void);\n\nstatic zend_op_array *phar_compile_file" - ); - if ($version_id < 80100) { - // PHP 8.0.x - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/phar/phar.c', - 'if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, "://")) {', - 'if ((strstr(file_handle->filename, micro_get_filename()) || strstr(file_handle->filename, ".phar")) && !strstr(file_handle->filename, "://")) {' - ); - } else { - // PHP >= 8.1 - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/ext/phar/phar.c', - 'if (strstr(ZSTR_VAL(file_handle->filename), ".phar") && !strstr(ZSTR_VAL(file_handle->filename), "://")) {', - 'if ((strstr(ZSTR_VAL(file_handle->filename), micro_get_filename()) || strstr(ZSTR_VAL(file_handle->filename), ".phar")) && !strstr(ZSTR_VAL(file_handle->filename), "://")) {' - ); - } - } - - public static function unpatchMicroPhar(): void - { - FileSystem::restoreBackupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c'); - } - - /** - * Fix the compilation issue of sqlsrv and pdo_sqlsrv on Windows (/sdl check is too strict and will cause Zend compilation to fail) - */ - public static function patchSQLSRVWin32(string $source_name): bool - { - $source_name = preg_replace('/[^a-z_]/', '', $source_name); - if (file_exists(SOURCE_PATH . '/php-src/ext/' . $source_name . '/config.w32')) { - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/' . $source_name . '/config.w32', '/sdl', ''); - return true; - } - return false; - } - - /** - * 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'"); - return true; - } - - public static function patchLibYaml(string $name, string $target): bool - { - if (!file_exists("{$target}/cmake/config.h.in")) { - FileSystem::createDir("{$target}/cmake"); - copy(ROOT_DIR . '/src/globals/extra/libyaml_config.h.in', "{$target}/cmake/config.h.in"); - } - if (!file_exists("{$target}/YamlConfig.cmake.in")) { - copy(ROOT_DIR . '/src/globals/extra/libyaml_yamlConfig.cmake.in', "{$target}/yamlConfig.cmake.in"); - } - return true; - } - - /** - * Patch imap license file for PHP < 8.4 - */ - public static function patchImapLicense(): bool - { - if (!file_exists(SOURCE_PATH . '/php-src/ext/imap/LICENSE') && is_dir(SOURCE_PATH . '/php-src/ext/imap')) { - file_put_contents(SOURCE_PATH . '/php-src/ext/imap/LICENSE', file_get_contents(ROOT_DIR . '/src/globals/extra/Apache_LICENSE')); - return true; - } - return false; - } - - /** - * Patch imagick for PHP 8.4 - */ - public static function patchImagickWith84(): bool - { - // match imagick version id - $file = SOURCE_PATH . '/php-src/ext/imagick/php_imagick.h'; - if (!file_exists($file)) { - return false; - } - $content = file_get_contents($file); - if (preg_match('/#define PHP_IMAGICK_EXTNUM\s+(\d+)/', $content, $match) === 0) { - return false; - } - $extnum = intval($match[1]); - if ($extnum < 30800) { - self::patchFile('imagick_php84_before_30800.patch', SOURCE_PATH . '/php-src/ext/imagick'); - return true; - } - return false; - } - - public static function patchFfiCentos7FixO3strncmp(): bool - { - if (!($ver = SPCTarget::getLibcVersion()) || version_compare($ver, '2.17', '>')) { - return false; - } - if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) { - return false; - } - $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); - if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0 && intval($match[1]) < 80316) { - return false; - } - self::patchFile('ffi_centos7_fix_O3_strncmp.patch', SOURCE_PATH . '/php-src'); - return true; - } - - public static function patchPkgConfigForGcc15(): bool - { - self::patchFile('pkg-config_gcc15.patch', SOURCE_PATH . '/pkg-config'); - return true; - } - - public static function patchLibaomForAlpine(): bool - { - if (PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist()) { - self::patchFile('libaom_posix_implict.patch', SOURCE_PATH . '/libaom'); - return true; - } - return false; - } - - public static function patchAttrForAlpine(): bool - { - if (PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist() || PHP_OS_FAMILY === 'Darwin') { - self::patchFile('attr_alpine_gethostname.patch', SOURCE_PATH . '/attr'); - return true; - } - return false; - } - - /** - * Patch cli SAPI Makefile for Windows. - */ - public static function patchWindowsCLITarget(): void - { - // search Makefile code line contains "$(BUILD_DIR)\php.exe:" - $content = FileSystem::readFile(SOURCE_PATH . '/php-src/Makefile'); - $lines = explode("\r\n", $content); - $line_num = 0; - $found = false; - foreach ($lines as $v) { - if (str_contains($v, '$(BUILD_DIR)\php.exe:')) { - $found = $line_num; - break; - } - ++$line_num; - } - if ($found === false) { - throw new PatchException('Windows Makefile patching for php.exe target', 'Cannot patch windows CLI Makefile, Makefile does not contain "$(BUILD_DIR)\php.exe:" line'); - } - $lines[$line_num] = '$(BUILD_DIR)\php.exe: generated_files $(DEPS_CLI) $(PHP_GLOBAL_OBJS) $(CLI_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(ASM_OBJS) $(BUILD_DIR)\php.exe.res $(BUILD_DIR)\php.exe.manifest'; - $lines[$line_num + 1] = "\t" . '"$(LINK)" /nologo $(PHP_GLOBAL_OBJS_RESP) $(CLI_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(STATIC_EXT_LIBS) $(ASM_OBJS) $(LIBS) $(LIBS_CLI) $(BUILD_DIR)\php.exe.res /out:$(BUILD_DIR)\php.exe $(LDFLAGS) $(LDFLAGS_CLI) /ltcg /nodefaultlib:msvcrt /nodefaultlib:msvcrtd /ignore:4286'; - FileSystem::writeFile(SOURCE_PATH . '/php-src/Makefile', implode("\r\n", $lines)); - } - - /** - * Patch cgi SAPI Makefile for Windows. - */ - public static function patchWindowsCGITarget(): void - { - // search Makefile code line contains "$(BUILD_DIR)\php-cgi.exe:" - $content = FileSystem::readFile(SOURCE_PATH . '/php-src/Makefile'); - $lines = explode("\r\n", $content); - $line_num = 0; - $found = false; - foreach ($lines as $v) { - if (str_contains($v, '$(BUILD_DIR)\php-cgi.exe:')) { - $found = $line_num; - break; - } - ++$line_num; - } - if ($found === false) { - throw new PatchException('Windows Makefile patching for php-cgi.exe target', 'Cannot patch windows CGI Makefile, Makefile does not contain "$(BUILD_DIR)\php-cgi.exe:" line'); - } - // cli: $(BUILD_DIR)\php.exe: $(DEPS_CLI) $(CLI_GLOBAL_OBJS) $(BUILD_DIR)\$(PHPLIB) $(BUILD_DIR)\php.exe.res $(BUILD_DIR)\php.exe.manifest - // $lines[$line_num] = '$(BUILD_DIR)\php.exe: generated_files $(DEPS_CLI) $(CLI_GLOBAL_OBJS) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(ASM_OBJS) $(BUILD_DIR)\php.exe.res $(BUILD_DIR)\php.exe.manifest'; - // cgi: $(BUILD_DIR)\php-cgi.exe: $(DEPS_CGI) $(CGI_GLOBAL_OBJS) $(BUILD_DIR)\$(PHPLIB) $(BUILD_DIR)\php-cgi.exe.res $(BUILD_DIR)\php-cgi.exe.manifest - $lines[$line_num] = '$(BUILD_DIR)\php-cgi.exe: $(DEPS_CGI) $(CGI_GLOBAL_OBJS) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(ASM_OBJS) $(BUILD_DIR)\php-cgi.exe.res $(BUILD_DIR)\php-cgi.exe.manifest'; - - // cli: @"$(LINK)" /nologo $(CGI_GLOBAL_OBJS_RESP) $(BUILD_DIR)\$(PHPLIB) $(LIBS_CGI) $(BUILD_DIR)\php-cgi.exe.res /out:$(BUILD_DIR)\php-cgi.exe $(LDFLAGS) $(LDFLAGS_CGI) - $lines[$line_num + 1] = "\t" . '@"$(LINK)" /nologo $(PHP_GLOBAL_OBJS_RESP) $(CGI_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(STATIC_EXT_LIBS) $(ASM_OBJS) $(LIBS) $(LIBS_CGI) $(BUILD_DIR)\php-cgi.exe.res /out:$(BUILD_DIR)\php-cgi.exe $(LDFLAGS) $(LDFLAGS_CGI) /ltcg /nodefaultlib:msvcrt /nodefaultlib:msvcrtd /ignore:4286'; - FileSystem::writeFile(SOURCE_PATH . '/php-src/Makefile', implode("\r\n", $lines)); - - // Patch cgi-static, comment ZEND_TSRMLS_CACHE_DEFINE() - FileSystem::replaceFileRegex(SOURCE_PATH . '\php-src\sapi\cgi\cgi_main.c', '/^ZEND_TSRMLS_CACHE_DEFINE\(\)/m', '// ZEND_TSRMLS_CACHE_DEFINE()'); - } - - public static function patchPhpLibxml212(): bool - { - $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); - if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0) { - $ver_id = intval($match[1]); - if ($ver_id < 80000) { - self::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src'); - return true; - } - if ($ver_id < 80100) { - self::patchFile('spc_fix_libxml2_12_php80.patch', SOURCE_PATH . '/php-src'); - self::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src'); - return true; - } - if ($ver_id < 80200) { - // self::patchFile('spc_fix_libxml2_12_php81.patch', SOURCE_PATH . '/php-src'); - self::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src'); - return true; - } - return false; - } - return false; - } - - public static function patchGDWin32(): bool - { - $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); - if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0) { - $ver_id = intval($match[1]); - if ($ver_id < 80200) { - // see: https://github.com/php/php-src/commit/243966177e39eb71822935042c3f13fa6c5b9eed - FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gd/libgd/gdft.c', '#ifndef MSWIN32', '#ifndef _WIN32'); - } - // custom config.w32, because official config.w32 is hard-coded many things - if ($ver_id >= 80500) { - $origin = file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_85.w32'); - } elseif ($ver_id >= 80100) { - $origin = file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_81.w32'); - } else { - $origin = file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_80.w32'); - } - file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32.bak', file_get_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32')); - return file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32', $origin) !== false; - } - return false; - } - - /** - * Add additional `static-php-cli.version` ini value for PHP source. - */ - public static function patchSPCVersionToPHP(string $version = 'unknown'): void - { - // detect patch (remove this when 8.3 deprecated) - $file = FileSystem::readFile(SOURCE_PATH . '/php-src/main/main.c'); - if (!str_contains($file, 'static-php-cli.version')) { - logger()->debug('Inserting static-php-cli.version to php-src'); - $file = str_replace('PHP_INI_BEGIN()', "PHP_INI_BEGIN()\n\tPHP_INI_ENTRY(\"static-php-cli.version\",\t\"{$version}\",\tPHP_INI_ALL,\tNULL)", $file); - FileSystem::writeFile(SOURCE_PATH . '/php-src/main/main.c', $file); - } - } - - public static function patchMicroWin32(): void - { - // patch micro win32 - if (!file_exists(SOURCE_PATH . '\php-src\sapi\micro\php_micro.c.win32bak')) { - copy(SOURCE_PATH . '\php-src\sapi\micro\php_micro.c', SOURCE_PATH . '\php-src\sapi\micro\php_micro.c.win32bak'); - FileSystem::replaceFileStr(SOURCE_PATH . '\php-src\sapi\micro\php_micro.c', '#include "php_variables.h"', '#include "php_variables.h"' . "\n#define PHP_MICRO_WIN32_NO_CONSOLE 1"); - } - } - - public static function unpatchMicroWin32(): void - { - if (file_exists(SOURCE_PATH . '\php-src\sapi\micro\php_micro.c.win32bak')) { - rename(SOURCE_PATH . '\php-src\sapi\micro\php_micro.c.win32bak', SOURCE_PATH . '\php-src\sapi\micro\php_micro.c'); - } - } - - public static function patchGMSSL(): void - { - FileSystem::replaceFileStr(SOURCE_PATH . '/gmssl/src/hex.c', 'unsigned char *OPENSSL_hexstr2buf(const char *str, size_t *len)', 'unsigned char *GMSSL_hexstr2buf(const char *str, size_t *len)'); - FileSystem::replaceFileStr(SOURCE_PATH . '/gmssl/src/hex.c', 'OPENSSL_hexchar2int', 'GMSSL_hexchar2int'); - } -} diff --git a/src/SPC/store/pkg/CustomPackage.php b/src/SPC/store/pkg/CustomPackage.php deleted file mode 100644 index eb972d74..00000000 --- a/src/SPC/store/pkg/CustomPackage.php +++ /dev/null @@ -1,49 +0,0 @@ - 'amd64', - 'aarch64' => 'arm64', - default => throw new \InvalidArgumentException('Unsupported architecture: ' . $name), - }; - $os = match (explode('-', $name)[3]) { - 'linux' => 'linux', - 'macos' => 'darwin', - default => throw new \InvalidArgumentException('Unsupported OS: ' . $name), - }; - [$go_version] = explode("\n", Downloader::curlExec('https://go.dev/VERSION?m=text')); - $config = [ - 'type' => 'url', - 'url' => "https://go.dev/dl/{$go_version}.{$os}-{$arch}.tar.gz", - ]; - Downloader::downloadPackage($name, $config, $force); - } - - public function extract(string $name): void - { - $pkgroot = PKG_ROOT_PATH; - $go_exec = "{$pkgroot}/go-xcaddy/bin/go"; - $xcaddy_exec = "{$pkgroot}/go-xcaddy/bin/xcaddy"; - if (file_exists($go_exec) && file_exists($xcaddy_exec)) { - return; - } - $lock = json_decode(FileSystem::readFile(LockFile::LOCK_FILE), true); - $source_type = $lock[$name]['source_type']; - $filename = DOWNLOAD_PATH . '/' . ($lock[$name]['filename'] ?? $lock[$name]['dirname']); - $extract = $lock[$name]['move_path'] ?? "{$pkgroot}/go-xcaddy"; - - FileSystem::extractPackage($name, $source_type, $filename, $extract); - - $sanitizedPath = getenv('PATH'); - if (PHP_OS_FAMILY === 'Linux' && !SystemUtil::isMuslDist()) { - $sanitizedPath = preg_replace('#(:?/?[^:]*musl[^:]*)#', '', $sanitizedPath); - $sanitizedPath = preg_replace('#^:|:$|::#', ':', $sanitizedPath); // clean up colons - } - - // install xcaddy without using musl tools, xcaddy build requires dynamic linking - shell() - ->appendEnv([ - 'PATH' => "{$pkgroot}/go-xcaddy/bin:" . $sanitizedPath, - 'GOROOT' => "{$pkgroot}/go-xcaddy", - 'GOBIN' => "{$pkgroot}/go-xcaddy/bin", - 'GOPATH' => "{$pkgroot}/go", - ]) - ->exec('CC=cc go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest'); - } - - public static function getEnvironment(): array - { - $packageName = 'go-xcaddy'; - $pkgroot = PKG_ROOT_PATH; - return [ - 'GOROOT' => "{$pkgroot}/{$packageName}", - 'GOBIN' => "{$pkgroot}/{$packageName}/bin", - 'GOPATH' => "{$pkgroot}/go", - ]; - } - - public static function getPath(): ?string - { - return PKG_ROOT_PATH . '/go-xcaddy/bin'; - } -} diff --git a/src/SPC/store/pkg/Zig.php b/src/SPC/store/pkg/Zig.php deleted file mode 100644 index c2a81c0d..00000000 --- a/src/SPC/store/pkg/Zig.php +++ /dev/null @@ -1,163 +0,0 @@ - "{$pkgroot}/{$name}/zig.exe", - default => "{$pkgroot}/{$name}/zig", - }; - - if ($force) { - FileSystem::removeDir("{$pkgroot}/{$name}"); - } - - if (file_exists($zig_exec)) { - return; - } - - $parts = explode('-', $name); - $arch = $parts[1]; - $os = $parts[2]; - - $zig_arch = match ($arch) { - 'x86_64', 'aarch64' => $arch, - default => throw new WrongUsageException('Unsupported architecture: ' . $arch), - }; - - $zig_os = match ($os) { - 'linux' => 'linux', - 'macos' => 'macos', - 'win' => 'windows', - default => throw new WrongUsageException('Unsupported OS: ' . $os), - }; - - $index_json = json_decode(Downloader::curlExec('https://ziglang.org/download/index.json', hooks: [[CurlHook::class, 'setupGithubToken']]), true); - - $latest_version = null; - foreach ($index_json as $version => $data) { - // Skip the master branch, get the latest stable release - if ($version !== 'master') { - $latest_version = $version; - break; - } - } - - if (!$latest_version) { - throw new DownloaderException('Could not determine latest Zig version'); - } - - logger()->info("Installing Zig version {$latest_version}"); - - $platform_key = "{$zig_arch}-{$zig_os}"; - if (!isset($index_json[$latest_version][$platform_key])) { - throw new DownloaderException("No download available for {$platform_key} in Zig version {$latest_version}"); - } - - $download_info = $index_json[$latest_version][$platform_key]; - $url = $download_info['tarball']; - $filename = basename($url); - - $pkg = [ - 'type' => 'url', - 'url' => $url, - 'filename' => $filename, - ]; - - Downloader::downloadPackage($name, $pkg, $force); - } - - public function extract(string $name): void - { - $pkgroot = PKG_ROOT_PATH; - $zig_bin_dir = "{$pkgroot}/zig"; - - $files = ['zig', 'zig-cc', 'zig-c++', 'zig-ar', 'zig-ld.lld', 'zig-ranlib', 'zig-objcopy']; - $all_exist = true; - foreach ($files as $file) { - if (!file_exists("{$zig_bin_dir}/{$file}")) { - $all_exist = false; - break; - } - } - if ($all_exist) { - return; - } - - $lock = json_decode(FileSystem::readFile(LockFile::LOCK_FILE), true); - $source_type = $lock[$name]['source_type']; - $filename = DOWNLOAD_PATH . '/' . ($lock[$name]['filename'] ?? $lock[$name]['dirname']); - $extract = "{$pkgroot}/zig"; - - FileSystem::extractPackage($name, $source_type, $filename, $extract); - - $this->createZigCcScript($zig_bin_dir); - } - - public static function getEnvironment(): array - { - return []; - } - - public static function getPath(): ?string - { - return PKG_ROOT_PATH . '/zig'; - } - - private function createZigCcScript(string $bin_dir): void - { - $script_path = __DIR__ . '/../scripts/zig-cc.sh'; - $script_content = file_get_contents($script_path); - - file_put_contents("{$bin_dir}/zig-cc", $script_content); - chmod("{$bin_dir}/zig-cc", 0755); - - $script_content = str_replace('zig cc', 'zig c++', $script_content); - file_put_contents("{$bin_dir}/zig-c++", $script_content); - file_put_contents("{$bin_dir}/zig-ar", "#!/usr/bin/env bash\nexec zig ar $@"); - file_put_contents("{$bin_dir}/zig-ld.lld", "#!/usr/bin/env bash\nexec zig ld.lld $@"); - file_put_contents("{$bin_dir}/zig-ranlib", "#!/usr/bin/env bash\nexec zig ranlib $@"); - file_put_contents("{$bin_dir}/zig-objcopy", "#!/usr/bin/env bash\nexec zig objcopy $@"); - chmod("{$bin_dir}/zig-c++", 0755); - chmod("{$bin_dir}/zig-ar", 0755); - chmod("{$bin_dir}/zig-ld.lld", 0755); - chmod("{$bin_dir}/zig-ranlib", 0755); - chmod("{$bin_dir}/zig-objcopy", 0755); - } -} diff --git a/src/SPC/store/scripts/zig-cc.sh b/src/SPC/store/scripts/zig-cc.sh deleted file mode 100644 index 6b340bc1..00000000 --- a/src/SPC/store/scripts/zig-cc.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash - -SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" -BUILDROOT_ABS="$(realpath "$SCRIPT_DIR/../../../buildroot/include" 2>/dev/null || true)" -PARSED_ARGS=() - -while [[ $# -gt 0 ]]; do - case "$1" in - -isystem) - shift - ARG="$1" - shift - ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)" - [[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem" "$ARG") - ;; - -isystem*) - ARG="${1#-isystem}" - shift - ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)" - [[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG") - ;; - -march=*|-mcpu=*) - OPT_NAME="${1%%=*}" - OPT_VALUE="${1#*=}" - # Skip armv8- flags entirely as Zig doesn't support them - if [[ "$OPT_VALUE" == armv8-* ]]; then - shift - continue - fi - # replace -march=x86-64 with -march=x86_64 - OPT_VALUE="${OPT_VALUE//-/_}" - PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}") - shift - ;; - *) - PARSED_ARGS+=("$1") - shift - ;; - esac -done - -[[ -n "$SPC_TARGET" ]] && TARGET="-target $SPC_TARGET" || TARGET="" - -if [[ "$SPC_TARGET" =~ \.[0-9]+\.[0-9]+ ]]; then - output=$(zig cc $TARGET $SPC_COMPILER_EXTRA "${PARSED_ARGS[@]}" 2>&1) - status=$? - - if [[ $status -eq 0 ]]; then - echo "$output" - exit 0 - fi - - if echo "$output" | grep -qE "version '.*' in target triple"; then - filtered_output=$(echo "$output" | grep -vE "version '.*' in target triple") - echo "$filtered_output" - exit 0 - fi -fi - -exec zig cc $TARGET $SPC_COMPILER_EXTRA "${PARSED_ARGS[@]}" diff --git a/src/SPC/store/source/CustomSourceBase.php b/src/SPC/store/source/CustomSourceBase.php deleted file mode 100644 index 2f02fa7d..00000000 --- a/src/SPC/store/source/CustomSourceBase.php +++ /dev/null @@ -1,28 +0,0 @@ - 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force); - } else { - Downloader::downloadSource('php-src', $this->getLatestPHPInfo($major), $force); - } - } - - /** - * 获取 PHP x.y 的具体版本号,例如通过 8.1 来获取 8.1.10 - */ - #[ArrayShape(['type' => 'string', 'path' => 'string', 'rev' => 'string', 'url' => 'string'])] - public function getLatestPHPInfo(string $major_version): array - { - foreach (self::WEB_PHP_DOMAINS as $domain) { - try { - $info = json_decode(Downloader::curlExec( - url: "{$domain}/releases/index.php?json&version={$major_version}", - retries: (int) getenv('SPC_DOWNLOAD_RETRIES') ?: 0 - ), true); - if (!isset($info['version'])) { - throw new DownloaderException("Version {$major_version} not found."); - } - $version = $info['version']; - return [ - 'type' => 'url', - 'url' => "{$domain}/distributions/php-{$version}.tar.xz", - ]; - } catch (SPCException) { - logger()->warning('Failed to fetch latest PHP version for major version {$major_version} from {$domain}, trying next mirror if available.'); - continue; - } - } - // exception if all mirrors failed - throw new DownloaderException("Failed to fetch latest PHP version for major version {$major_version} from all tried mirrors."); - } -} diff --git a/src/SPC/store/source/PostgreSQLSource.php b/src/SPC/store/source/PostgreSQLSource.php deleted file mode 100644 index ec1d3357..00000000 --- a/src/SPC/store/source/PostgreSQLSource.php +++ /dev/null @@ -1,29 +0,0 @@ - 'https://www.postgresql.org/ftp/source/', - 'regex' => '/href="(?v(?[^"]+)\/)"/', - ]); - return [ - 'type' => 'url', - 'url' => "https://ftp.postgresql.org/pub/source/{$filename}postgresql-{$version}.tar.gz", - ]; - } -} diff --git a/src/SPC/toolchain/ClangNativeToolchain.php b/src/SPC/toolchain/ClangNativeToolchain.php deleted file mode 100644 index a57b2e8b..00000000 --- a/src/SPC/toolchain/ClangNativeToolchain.php +++ /dev/null @@ -1,53 +0,0 @@ - LinuxSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."), - 'Darwin' => MacOSSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."), - 'BSD' => FreeBSDSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."), - default => throw new EnvironmentException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'), - }; - } - } - - public function getCompilerInfo(): ?string - { - $compiler = getenv('CC') ?: 'clang'; - $version = shell(false)->execWithResult("{$compiler} --version", false); - $head = pathinfo($compiler, PATHINFO_BASENAME); - if ($version[0] === 0 && preg_match('/clang version (\d+\.\d+\.\d+)/', $version[1][0], $match)) { - return "{$head} {$match[1]}"; - } - return $head; - } -} diff --git a/src/SPC/toolchain/GccNativeToolchain.php b/src/SPC/toolchain/GccNativeToolchain.php deleted file mode 100644 index d8eb8d1a..00000000 --- a/src/SPC/toolchain/GccNativeToolchain.php +++ /dev/null @@ -1,50 +0,0 @@ - LinuxSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."), - 'Darwin' => MacOSSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."), - 'BSD' => FreeBSDSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."), - default => throw new EnvironmentException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'), - }; - } - } - - public function getCompilerInfo(): ?string - { - $compiler = getenv('CC') ?: 'gcc'; - $version = shell(false)->execWithResult("{$compiler} --version", false); - $head = pathinfo($compiler, PATHINFO_BASENAME); - if ($version[0] === 0 && preg_match('/gcc.*?(\d+\.\d+\.\d+)/', $version[1][0], $match)) { - return "{$head} {$match[1]}"; - } - return $head; - } -} diff --git a/src/SPC/toolchain/MSVCToolchain.php b/src/SPC/toolchain/MSVCToolchain.php deleted file mode 100644 index 55559e8a..00000000 --- a/src/SPC/toolchain/MSVCToolchain.php +++ /dev/null @@ -1,17 +0,0 @@ -execWithResult("{$compiler} --version", false); - $head = pathinfo($compiler, PATHINFO_BASENAME); - if ($version[0] === 0 && preg_match('/linux-musl-cc.*(\d+.\d+.\d+)/', $version[1][0], $match)) { - return "{$head} {$match[1]}"; - } - return $head; - } -} diff --git a/src/SPC/toolchain/ToolchainInterface.php b/src/SPC/toolchain/ToolchainInterface.php deleted file mode 100644 index a08fb869..00000000 --- a/src/SPC/toolchain/ToolchainInterface.php +++ /dev/null @@ -1,38 +0,0 @@ - ZigToolchain::class, - 'Windows' => MSVCToolchain::class, - 'Darwin' => ClangNativeToolchain::class, - 'BSD' => ClangNativeToolchain::class, - ]; - - public static function getToolchainClass(): string - { - if ($tc = getenv('SPC_TOOLCHAIN')) { - return $tc; - } - $libc = getenv('SPC_LIBC'); - if ($libc && !getenv('SPC_TARGET')) { - // trigger_error('Setting SPC_LIBC is deprecated, please use SPC_TARGET instead.', E_USER_DEPRECATED); - return match ($libc) { - 'musl' => SystemUtil::isMuslDist() ? GccNativeToolchain::class : MuslToolchain::class, - 'glibc' => !SystemUtil::isMuslDist() ? GccNativeToolchain::class : throw new WrongUsageException('SPC_LIBC must be musl for musl dist.'), - default => throw new WrongUsageException('Unsupported SPC_LIBC value: ' . $libc), - }; - } - - return self::OS_DEFAULT_TOOLCHAIN[PHP_OS_FAMILY]; - } - - public static function initToolchain(): void - { - $toolchainClass = self::getToolchainClass(); - /* @var ToolchainInterface $toolchainClass */ - (new $toolchainClass())->initEnv(); - GlobalEnvManager::putenv("SPC_TOOLCHAIN={$toolchainClass}"); - } - - public static function afterInitToolchain(): void - { - if (!getenv('SPC_TOOLCHAIN')) { - throw new WrongUsageException('SPC_TOOLCHAIN was not properly set. Please contact the developers.'); - } - $musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m')); - if (SPCTarget::getLibc() === 'musl' && !SPCTarget::isStatic() && !file_exists($musl_wrapper_lib)) { - throw new WrongUsageException('You are linking against musl libc dynamically, but musl libc is not installed. Please use `bin/spc doctor` to install it.'); - } - if (SPCTarget::getLibc() === 'glibc' && SystemUtil::isMuslDist()) { - throw new WrongUsageException('You are linking against glibc dynamically, which is only supported on glibc distros.'); - } - - // init pkg-config for unix - if (is_unix()) { - if (($found = PkgConfigUtil::findPkgConfig()) === null) { - throw new WrongUsageException('Cannot find pkg-config executable. Please run `doctor` to fix this.'); - } - GlobalEnvManager::putenv("PKG_CONFIG={$found}"); - } - - $toolchain = getenv('SPC_TOOLCHAIN'); - /* @var ToolchainInterface $toolchain */ - $instance = new $toolchain(); - $instance->afterInit(); - if (getenv('PHP_BUILD_COMPILER') === false && ($compiler_info = $instance->getCompilerInfo())) { - GlobalEnvManager::putenv("PHP_BUILD_COMPILER={$compiler_info}"); - } - } -} diff --git a/src/SPC/toolchain/ZigToolchain.php b/src/SPC/toolchain/ZigToolchain.php deleted file mode 100644 index 1b7cc70d..00000000 --- a/src/SPC/toolchain/ZigToolchain.php +++ /dev/null @@ -1,80 +0,0 @@ -/dev/null | grep -v '/32/' | head -n 1"); - $line = trim((string) $output); - if ($line !== '') { - $located = $line; - break; - } - } - if ($located) { - $found[] = $located; - } - } - GlobalEnvManager::putenv('SPC_EXTRA_RUNTIME_OBJECTS=' . implode(' ', $found)); - } - - public function afterInit(): void - { - if (!Zig::isInstalled()) { - throw new EnvironmentException('You are building with zig, but zig is not installed, please install zig first. (You can use `doctor` command to install it)'); - } - GlobalEnvManager::addPathIfNotExists(Zig::getPath()); - f_passthru('ulimit -n 2048'); // zig opens extra file descriptors, so when a lot of extensions are built statically, 1024 is not enough - $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: ''; - $cxxflags = getenv('SPC_DEFAULT_CXX_FLAGS') ?: ''; - $extraCflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') ?: ''; - $cflags = trim($cflags . ' -Wno-date-time'); - $cxxflags = trim($cxxflags . ' -Wno-date-time'); - $extraCflags = trim($extraCflags . ' -Wno-date-time'); - GlobalEnvManager::putenv("SPC_DEFAULT_C_FLAGS={$cflags}"); - GlobalEnvManager::putenv("SPC_DEFAULT_CXX_FLAGS={$cxxflags}"); - GlobalEnvManager::putenv("SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS={$extraCflags}"); - GlobalEnvManager::putenv('RANLIB=zig-ranlib'); - GlobalEnvManager::putenv('OBJCOPY=zig-objcopy'); - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - if (!str_contains($extra_libs, '-lunwind')) { - // Add unwind library if not already present - $extra_libs = trim($extra_libs . ' -lunwind'); - GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}"); - } - $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; - $has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); - if (!$has_avx512) { - $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}"); - } - } - - public function getCompilerInfo(): ?string - { - $version = shell(false)->execWithResult('zig version', false)[1][0] ?? ''; - return trim("zig {$version}"); - } -} diff --git a/src/SPC/util/AttributeMapper.php b/src/SPC/util/AttributeMapper.php deleted file mode 100644 index 4eafc6dd..00000000 --- a/src/SPC/util/AttributeMapper.php +++ /dev/null @@ -1,133 +0,0 @@ - $extensions The mapping of extension names to their classes */ - private static array $ext_attr_map = []; - - /** @var array> $doctor_map The mapping of doctor modules */ - private static array $doctor_map = [ - 'check' => [], - 'fix' => [], - ]; - - public static function init(): void - { - // Load CustomExt attributes from extension classes - self::loadExtensionAttributes(); - - // Load doctor check items - self::loadDoctorAttributes(); - - // TODO: 3.0, refactor library loader and vendor loader here - } - - /** - * Get the class name of an extension by its attributed name. - * - * @param string $name The name of the extension (attributed name) - * @return null|string Returns the class name of the extension if it exists, otherwise null - */ - public static function getExtensionClassByName(string $name): ?string - { - return self::$ext_attr_map[$name] ?? null; - } - - /** - * @internal - */ - public static function getDoctorCheckMap(): array - { - return self::$doctor_map['check']; - } - - /** - * @internal - */ - public static function getDoctorFixMap(): array - { - return self::$doctor_map['fix']; - } - - private static function loadExtensionAttributes(): void - { - $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/builder/extension', 'SPC\builder\extension'); - foreach ($classes as $class) { - $reflection = new \ReflectionClass($class); - foreach ($reflection->getAttributes(CustomExt::class) as $attribute) { - /** @var CustomExt $instance */ - $instance = $attribute->newInstance(); - self::$ext_attr_map[$instance->ext_name] = $class; - } - } - } - - private static function loadDoctorAttributes(): void - { - $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/doctor/item', 'SPC\doctor\item'); - foreach ($classes as $class) { - $optional_passthrough = null; - $ref = new \ReflectionClass($class); - // #[OptionalCheck] - $optional = $ref->getAttributes(OptionalCheck::class)[0] ?? null; - if ($optional !== null) { - /** @var OptionalCheck $instance */ - $instance = $optional->newInstance(); - if (is_callable($instance->check)) { - $optional_passthrough = $instance->check; - } - } - $check_items = []; - $fix_items = []; - // load check items and fix items - foreach ($ref->getMethods() as $method) { - $optional_passthrough_single = $optional_passthrough ?? null; - // #[OptionalCheck] - foreach ($method->getAttributes(OptionalCheck::class) as $method_attr) { - $optional_check = $method_attr->newInstance(); - if (is_callable($optional_check->check)) { - $optional_passthrough_single = $optional_check->check; - } - } - // #[AsCheckItem] - foreach ($method->getAttributes(AsCheckItem::class) as $method_attr) { - // [{AsCheckItem object}, {OptionalCheck callable or null}] - $obj = $method_attr->newInstance(); - $obj->callback = [new $class(), $method->getName()]; - $check_items[] = [$obj, $optional_passthrough_single]; - } - // #[AsFixItem] - $fix_item = $method->getAttributes(AsFixItem::class)[0] ?? null; - if ($fix_item !== null) { - // [{AsFixItem object}, {OptionalCheck callable or null}] - $obj = $fix_item->newInstance(); - $fix_items[$obj->name] = [new $class(), $method->getName()]; - } - } - - // add to doctor map - self::$doctor_map['check'] = array_merge(self::$doctor_map['check'], $check_items); - self::$doctor_map['fix'] = array_merge(self::$doctor_map['fix'], $fix_items); - } - - // sort check items by level - usort(self::$doctor_map['check'], fn (array $a, array $b) => $a[0]->level > $b[0]->level ? -1 : ($a[0]->level == $b[0]->level ? 0 : 1)); - } -} diff --git a/src/SPC/util/ConfigValidator.php b/src/SPC/util/ConfigValidator.php deleted file mode 100644 index d9f751ef..00000000 --- a/src/SPC/util/ConfigValidator.php +++ /dev/null @@ -1,688 +0,0 @@ - 'string', // url - 'regex' => 'string', // regex pattern - 'rev' => 'string', // revision/branch - 'repo' => 'string', // repository name - 'match' => 'string', // match pattern (aaa*bbb) - 'filename' => 'string', // filename - 'path' => 'string', // copy path - 'extract' => 'string', // copy path (alias of path) - 'dirname' => 'string', // directory name for local source - 'source' => 'string', // the source name that this item uses - 'match-pattern-linux' => 'string', // pre-built match pattern for linux - 'match-pattern-macos' => 'string', // pre-built match pattern for macos - 'match-pattern-windows' => 'string', // pre-built match pattern for windows - - // Boolean fields - 'prefer-stable' => 'bool', // prefer stable releases - 'provide-pre-built' => 'bool', // provide pre-built binaries - 'notes' => 'bool', // whether to show notes in docs - 'cpp-library' => 'bool', // whether this is a C++ library - 'cpp-extension' => 'bool', // whether this is a C++ extension - 'build-with-php' => 'bool', // whether if this extension can be built to shared with PHP source together - 'zend-extension' => 'bool', // whether this is a zend extension - 'unix-only' => 'bool', // whether this extension is only for unix-like systems - - // Array fields - 'submodules' => 'array', // git submodules list (for git source type) - 'lib-depends' => 'list', - 'lib-suggests' => 'list', - 'ext-depends' => 'list', - 'ext-suggests' => 'list', - 'static-libs' => 'list', - 'pkg-configs' => 'list', // required pkg-config files without suffix (e.g. [libwebp]) - 'headers' => 'list', // required header files - 'bin' => 'list', // required binary files - 'frameworks' => 'list', // shared library frameworks (macOS) - - // Object/assoc array fields - 'support' => 'object', // extension OS support docs - 'extract-files' => 'object', // pkg.json extract files mapping with match pattern - 'alt' => 'object|bool', // alternative source/package - 'license' => 'object|array', // license information - 'target' => 'array', // extension build targets (default: [static], alternate: [shared] or both) - - // Special/mixed fields - 'func' => 'callable', // custom download function for custom source/package type - 'type' => 'string', // type field (validated separately) - ]; - - /** - * Source/Package download type validation rules - * Maps type names to [required_props, optional_props] - */ - private const array SOURCE_TYPE_FIELDS = [ - 'filelist' => [['url', 'regex'], []], - 'git' => [['url', 'rev'], ['path', 'extract', 'submodules']], - 'ghtagtar' => [['repo'], ['path', 'extract', 'prefer-stable', 'match']], - 'ghtar' => [['repo'], ['path', 'extract', 'prefer-stable', 'match']], - 'ghrel' => [['repo', 'match'], ['path', 'extract', 'prefer-stable']], - 'url' => [['url'], ['filename', 'path', 'extract']], - 'bitbuckettag' => [['repo'], ['path', 'extract']], - 'local' => [['dirname'], ['path', 'extract']], - 'pie' => [['repo'], ['path']], - 'custom' => [[], ['func']], - ]; - - /** - * Source.json specific fields [field_name => required] - * Note: 'type' is validated separately in validateSourceTypeConfig - * Field types are defined in FIELD_TYPES constant - */ - private const array SOURCE_FIELDS = [ - 'type' => true, // source type (must be SOURCE_TYPE_FIELDS key) - 'provide-pre-built' => false, // whether to provide pre-built binaries - 'alt' => false, // alternative source configuration - 'license' => false, // license information for source - // ... other fields are validated based on source type - ]; - - /** - * Lib.json specific fields [field_name => required] - * Field types are defined in FIELD_TYPES constant - */ - private const array LIB_FIELDS = [ - 'type' => false, // lib type (lib/package/target/root) - 'source' => false, // the source name that this lib uses - 'lib-depends' => false, // required libraries - 'lib-suggests' => false, // suggested libraries - 'static-libs' => false, // Generated static libraries - 'pkg-configs' => false, // Generated pkg-config files - 'cpp-library' => false, // whether this is a C++ library - 'headers' => false, // Generated header files - 'bin' => false, // Generated binary files - 'frameworks' => false, // Used shared library frameworks (macOS) - ]; - - /** - * Ext.json specific fields [field_name => required] - * Field types are defined in FIELD_TYPES constant - */ - private const array EXT_FIELDS = [ - 'type' => true, // extension type (builtin/external/addon/wip) - 'source' => false, // the source name that this extension uses - 'support' => false, // extension OS support docs - 'notes' => false, // whether to show notes in docs - 'cpp-extension' => false, // whether this is a C++ extension - 'build-with-php' => false, // whether if this extension can be built to shared with PHP source together - 'target' => false, // extension build targets (default: [static], alternate: [shared] or both) - 'lib-depends' => false, - 'lib-suggests' => false, - 'ext-depends' => false, - 'ext-suggests' => false, - 'frameworks' => false, - 'zend-extension' => false, // whether this is a zend extension - 'unix-only' => false, // whether this extension is only for unix-like systems - ]; - - /** - * Pkg.json specific fields [field_name => required] - * Field types are defined in FIELD_TYPES constant - */ - private const array PKG_FIELDS = [ - 'type' => true, // package type (same as source type) - 'extract-files' => false, // files to extract mapping (source pattern => target path) - ]; - - /** - * Pre-built.json specific fields [field_name => required] - * Field types are defined in FIELD_TYPES constant - */ - private const array PRE_BUILT_FIELDS = [ - 'repo' => true, // repository name for pre-built binaries - 'prefer-stable' => false, // prefer stable releases - 'match-pattern-linux' => false, // pre-built match pattern for linux - 'match-pattern-macos' => false, // pre-built match pattern for macos - 'match-pattern-windows' => false, // pre-built match pattern for windows - ]; - - /** - * Validate source.json - * - * @param array $data source.json data array - */ - public static function validateSource(array $data): void - { - foreach ($data as $name => $src) { - // Validate basic source type configuration - self::validateSourceTypeConfig($src, $name, 'source'); - - // Validate all source-specific fields using unified method - self::validateConfigFields($src, $name, 'source', self::SOURCE_FIELDS); - - // Check for unknown fields - self::validateAllowedFields($src, $name, 'source', self::SOURCE_FIELDS); - - // check if alt is valid - if (isset($src['alt']) && is_assoc_array($src['alt'])) { - // validate alt source recursively - self::validateSource([$name . '_alt' => $src['alt']]); - } - - // check if license is valid - if (isset($src['license'])) { - if (is_assoc_array($src['license'])) { - self::checkSingleLicense($src['license'], $name); - } elseif (is_list_array($src['license'])) { - foreach ($src['license'] as $license) { - if (!is_assoc_array($license)) { - throw new ValidationException("source {$name} license must be an object or array"); - } - self::checkSingleLicense($license, $name); - } - } - } - } - } - - public static function validateLibs(mixed $data, array $source_data = []): void - { - // check if it is an array - if (!is_array($data)) { - throw new ValidationException('lib.json is broken'); - } - - foreach ($data as $name => $lib) { - if (!is_assoc_array($lib)) { - throw new ValidationException("lib {$name} is not an object"); - } - // check if lib has valid type - if (!in_array($lib['type'] ?? 'lib', ['lib', 'package', 'target', 'root'])) { - throw new ValidationException("lib {$name} type is invalid"); - } - // check if lib and package has source - if (in_array($lib['type'] ?? 'lib', ['lib', 'package']) && !isset($lib['source'])) { - throw new ValidationException("lib {$name} does not assign any source"); - } - // check if source is valid - if (isset($lib['source']) && !empty($source_data) && !isset($source_data[$lib['source']])) { - throw new ValidationException("lib {$name} assigns an invalid source: {$lib['source']}"); - } - - // Validate basic fields using unified method - self::validateConfigFields($lib, $name, 'lib', self::LIB_FIELDS); - - // Validate list array fields with suffixes - $suffixes = ['', '-windows', '-unix', '-macos', '-linux']; - $fields = ['lib-depends', 'lib-suggests', 'static-libs', 'pkg-configs', 'headers', 'bin']; - self::validateListArrayFields($lib, $name, 'lib', $fields, $suffixes); - - // Validate frameworks (special case without suffix) - if (isset($lib['frameworks'])) { - self::validateFieldType('frameworks', $lib['frameworks'], $name, 'lib'); - } - - // Check for unknown fields - self::validateAllowedFields($lib, $name, 'lib', self::LIB_FIELDS); - } - } - - public static function validateExts(mixed $data): void - { - if (!is_array($data)) { - throw new ValidationException('ext.json is broken'); - } - - foreach ($data as $name => $ext) { - if (!is_assoc_array($ext)) { - throw new ValidationException("ext {$name} is not an object"); - } - - if (!in_array($ext['type'] ?? '', ['builtin', 'external', 'addon', 'wip'])) { - throw new ValidationException("ext {$name} type is invalid"); - } - - // Check source field requirement - if (($ext['type'] ?? '') === 'external' && !isset($ext['source'])) { - throw new ValidationException("ext {$name} does not assign any source"); - } - - // Validate basic fields using unified method - self::validateConfigFields($ext, $name, 'ext', self::EXT_FIELDS); - - // Validate list array fields with suffixes - $suffixes = ['', '-windows', '-unix', '-macos', '-linux']; - $fields = ['lib-depends', 'lib-suggests', 'ext-depends', 'ext-suggests']; - self::validateListArrayFields($ext, $name, 'ext', $fields, $suffixes); - - // Validate arg-type fields - self::validateArgTypeFields($ext, $name, $suffixes); - - // Check for unknown fields - self::validateAllowedFields($ext, $name, 'ext', self::EXT_FIELDS); - } - } - - public static function validatePkgs(mixed $data): void - { - if (!is_array($data)) { - throw new ValidationException('pkg.json is broken'); - } - // check each package - foreach ($data as $name => $pkg) { - // check if pkg is an assoc array - if (!is_assoc_array($pkg)) { - throw new ValidationException("pkg {$name} is not an object"); - } - - // Validate basic source type configuration (reuse from source validation) - self::validateSourceTypeConfig($pkg, $name, 'pkg'); - - // Validate all pkg-specific fields using unified method - self::validateConfigFields($pkg, $name, 'pkg', self::PKG_FIELDS); - - // Validate extract-files content (object validation is done by validateFieldType) - if (isset($pkg['extract-files'])) { - // check each extract file mapping - foreach ($pkg['extract-files'] as $source => $target) { - if (!is_string($source) || !is_string($target)) { - throw new ValidationException("pkg {$name} extract-files mapping must be string to string"); - } - } - } - - // Check for unknown fields - self::validateAllowedFields($pkg, $name, 'pkg', self::PKG_FIELDS); - } - } - - /** - * Validate pre-built.json configuration - * - * @param mixed $data pre-built.json loaded data - */ - public static function validatePreBuilt(mixed $data): void - { - if (!is_array($data)) { - throw new ValidationException('pre-built.json is broken'); - } - - // Validate all fields using unified method - self::validateConfigFields($data, 'pre-built', 'pre-built', self::PRE_BUILT_FIELDS); - - // Check for unknown fields - self::validateAllowedFields($data, 'pre-built', 'pre-built', self::PRE_BUILT_FIELDS); - - // Check match pattern fields (at least one must exist) - $pattern_fields = ['match-pattern-linux', 'match-pattern-macos', 'match-pattern-windows']; - $has_pattern = false; - - foreach ($pattern_fields as $field) { - if (isset($data[$field])) { - $has_pattern = true; - // Validate pattern contains required placeholders - if (!str_contains($data[$field], '{name}')) { - throw new ValidationException("pre-built.json [{$field}] must contain {name} placeholder"); - } - if (!str_contains($data[$field], '{arch}')) { - throw new ValidationException("pre-built.json [{$field}] must contain {arch} placeholder"); - } - if (!str_contains($data[$field], '{os}')) { - throw new ValidationException("pre-built.json [{$field}] must contain {os} placeholder"); - } - - // Linux pattern should have libc-related placeholders - if ($field === 'match-pattern-linux') { - if (!str_contains($data[$field], '{libc}')) { - throw new ValidationException('pre-built.json [match-pattern-linux] must contain {libc} placeholder'); - } - if (!str_contains($data[$field], '{libcver}')) { - throw new ValidationException('pre-built.json [match-pattern-linux] must contain {libcver} placeholder'); - } - } - } - } - - if (!$has_pattern) { - throw new ValidationException('pre-built.json must have at least one match-pattern field'); - } - } - - /** - * @param mixed $craft_file craft.yml path - * @param Command $command craft command instance - * @return array{ - * php-version?: string, - * extensions: array, - * shared-extensions?: array, - * libs?: array, - * sapi: array, - * debug?: bool, - * clean-build?: bool, - * build-options?: array, - * download-options?: array, - * extra-env?: array, - * craft-options?: array{ - * doctor?: bool, - * download?: bool, - * build?: bool - * } - * } - */ - public static function validateAndParseCraftFile(mixed $craft_file, Command $command): array - { - $build_options = $command->getApplication()->find('build')->getDefinition()->getOptions(); - $download_options = $command->getApplication()->find('download')->getDefinition()->getOptions(); - - try { - $craft = Yaml::parse(file_get_contents($craft_file)); - } catch (ParseException $e) { - throw new ValidationException('Craft file is broken: ' . $e->getMessage()); - } - if (!is_assoc_array($craft)) { - throw new ValidationException('Craft file is broken'); - } - // check php-version - if (isset($craft['php-version'])) { - // validate version, accept 8.x, 7.x, 8.x.x, 7.x.x, 8, 7 - $version = strval($craft['php-version']); - if (!preg_match('/^(\d+)(\.\d+)?(\.\d+)?$/', $version, $matches)) { - throw new ValidationException('Craft file php-version is invalid'); - } - } - // check extensions - if (!isset($craft['extensions'])) { - throw new ValidationException('Craft file must have extensions'); - } - if (is_string($craft['extensions'])) { - $craft['extensions'] = array_filter(array_map(fn ($x) => trim($x), explode(',', $craft['extensions']))); - } - if (!isset($craft['shared-extensions'])) { - $craft['shared-extensions'] = []; - } - if (is_string($craft['shared-extensions'] ?? [])) { - $craft['shared-extensions'] = array_filter(array_map(fn ($x) => trim($x), explode(',', $craft['shared-extensions']))); - } - // check libs - if (isset($craft['libs']) && is_string($craft['libs'])) { - $craft['libs'] = array_filter(array_map(fn ($x) => trim($x), explode(',', $craft['libs']))); - } elseif (!isset($craft['libs'])) { - $craft['libs'] = []; - } - // check sapi - if (!isset($craft['sapi'])) { - throw new ValidationException('Craft file must have sapi'); - } - if (is_string($craft['sapi'])) { - $craft['sapi'] = array_filter(array_map(fn ($x) => trim($x), explode(',', $craft['sapi']))); - } - // debug as boolean - if (isset($craft['debug'])) { - $craft['debug'] = filter_var($craft['debug'], FILTER_VALIDATE_BOOLEAN); - } else { - $craft['debug'] = false; - } - // check clean-build - $craft['clean-build'] ??= false; - // check build-options - if (isset($craft['build-options'])) { - if (!is_assoc_array($craft['build-options'])) { - throw new ValidationException('Craft file build-options must be an object'); - } - foreach ($craft['build-options'] as $key => $value) { - if (!isset($build_options[$key])) { - throw new ValidationException("Craft file build-options {$key} is invalid"); - } - // check an array - if ($build_options[$key]->isArray() && !is_array($value)) { - throw new ValidationException("Craft file build-options {$key} must be an array"); - } - } - } else { - $craft['build-options'] = []; - } - // check download options - if (isset($craft['download-options'])) { - if (!is_assoc_array($craft['download-options'])) { - throw new ValidationException('Craft file download-options must be an object'); - } - foreach ($craft['download-options'] as $key => $value) { - if (!isset($download_options[$key])) { - throw new ValidationException("Craft file download-options {$key} is invalid"); - } - // check an array - if ($download_options[$key]->isArray() && !is_array($value)) { - throw new ValidationException("Craft file download-options {$key} must be an array"); - } - } - } else { - $craft['download-options'] = []; - } - // check extra-env - if (isset($craft['extra-env'])) { - if (!is_assoc_array($craft['extra-env'])) { - throw new ValidationException('Craft file extra-env must be an object'); - } - } else { - $craft['extra-env'] = []; - } - // check craft-options - $craft['craft-options']['doctor'] ??= true; - $craft['craft-options']['download'] ??= true; - $craft['craft-options']['build'] ??= true; - return $craft; - } - - /** - * Validate a field based on its global type definition - * - * @param string $field Field name - * @param mixed $value Field value - * @param string $name Item name (for error messages) - * @param string $type Item type (for error messages) - * @return bool Returns true if validation passes - */ - private static function validateFieldType(string $field, mixed $value, string $name, string $type): bool - { - // Check if field exists in FIELD_TYPES - if (!isset(self::FIELD_TYPES[$field])) { - // Try to strip suffix and check base field name - $suffixes = ['-windows', '-unix', '-macos', '-linux']; - $base_field = $field; - foreach ($suffixes as $suffix) { - if (str_ends_with($field, $suffix)) { - $base_field = substr($field, 0, -strlen($suffix)); - break; - } - } - - if (!isset(self::FIELD_TYPES[$base_field])) { - // Unknown field is not allowed - strict validation - throw new ValidationException("{$type} {$name} has unknown field [{$field}]"); - } - - // Use base field type for validation - $expected_type = self::FIELD_TYPES[$base_field]; - } else { - $expected_type = self::FIELD_TYPES[$field]; - } - - return match ($expected_type) { - 'string' => is_string($value) ?: throw new ValidationException("{$type} {$name} [{$field}] must be string"), - 'bool' => is_bool($value) ?: throw new ValidationException("{$type} {$name} [{$field}] must be boolean"), - 'array' => is_array($value) ?: throw new ValidationException("{$type} {$name} [{$field}] must be array"), - 'list' => is_list_array($value) ?: throw new ValidationException("{$type} {$name} [{$field}] must be a list"), - 'object' => is_assoc_array($value) ?: throw new ValidationException("{$type} {$name} [{$field}] must be an object"), - 'object|bool' => (is_assoc_array($value) || is_bool($value)) ?: throw new ValidationException("{$type} {$name} [{$field}] must be object or boolean"), - 'object|array' => is_array($value) ?: throw new ValidationException("{$type} {$name} [{$field}] must be an object or array"), - 'callable' => true, // Skip validation for callable - }; - } - - private static function checkSingleLicense(array $license, string $name): void - { - if (!is_assoc_array($license)) { - throw new ValidationException("source {$name} license must be an object"); - } - if (!isset($license['type'])) { - throw new ValidationException("source {$name} license must have type"); - } - if (!in_array($license['type'], ['file', 'text'])) { - throw new ValidationException("source {$name} license type is invalid"); - } - if ($license['type'] === 'file' && !isset($license['path'])) { - throw new ValidationException("source {$name} license file must have path"); - } - if ($license['type'] === 'text' && !isset($license['text'])) { - throw new ValidationException("source {$name} license text must have text"); - } - } - - /** - * Validate source type configuration (shared between source.json and pkg.json) - * - * @param array $item The source/package item to validate - * @param string $name The name of the item for error messages - * @param string $config_type The type of config file ("source" or "pkg") - */ - private static function validateSourceTypeConfig(array $item, string $name, string $config_type): void - { - if (!isset($item['type'])) { - throw new ValidationException("{$config_type} {$name} must have prop: [type]"); - } - if (!is_string($item['type'])) { - throw new ValidationException("{$config_type} {$name} type prop must be string"); - } - - if (!isset(self::SOURCE_TYPE_FIELDS[$item['type']])) { - throw new ValidationException("{$config_type} {$name} type [{$item['type']}] is invalid"); - } - - [$required, $optional] = self::SOURCE_TYPE_FIELDS[$item['type']]; - - // Check required fields exist - foreach ($required as $prop) { - if (!isset($item[$prop])) { - $props = implode('] and [', $required); - throw new ValidationException("{$config_type} {$name} needs [{$props}] props"); - } - } - - // Validate field types using global field type definitions - foreach (array_merge($required, $optional) as $prop) { - if (isset($item[$prop])) { - self::validateFieldType($prop, $item[$prop], $name, $config_type); - } - } - } - - /** - * Validate that fields with suffixes are list arrays - */ - private static function validateListArrayFields(array $item, string $name, string $type, array $fields, array $suffixes): void - { - foreach ($fields as $field) { - foreach ($suffixes as $suffix) { - $key = $field . $suffix; - if (isset($item[$key])) { - self::validateFieldType($key, $item[$key], $name, $type); - } - } - } - } - - /** - * Validate arg-type fields with suffixes - */ - private static function validateArgTypeFields(array $item, string $name, array $suffixes): void - { - $valid_arg_types = ['enable', 'with', 'with-path', 'custom', 'none', 'enable-path']; - - foreach (array_merge([''], $suffixes) as $suffix) { - $key = 'arg-type' . $suffix; - if (isset($item[$key]) && !in_array($item[$key], $valid_arg_types)) { - throw new ValidationException("ext {$name} {$key} is invalid"); - } - } - } - - /** - * Unified method to validate config fields based on field definitions - * - * @param array $item Item data to validate - * @param string $name Item name for error messages - * @param string $type Config type (source, lib, ext, pkg, pre-built) - * @param array $field_definitions Field definitions [field_name => required (bool)] - */ - private static function validateConfigFields(array $item, string $name, string $type, array $field_definitions): void - { - foreach ($field_definitions as $field => $required) { - if ($required && !isset($item[$field])) { - throw new ValidationException("{$type} {$name} must have [{$field}] field"); - } - - if (isset($item[$field])) { - self::validateFieldType($field, $item[$field], $name, $type); - } - } - } - - /** - * Validate that item only contains allowed fields - * This method checks for unknown fields based on the config type - * - * @param array $item Item data to validate - * @param string $name Item name for error messages - * @param string $type Config type (source, lib, ext, pkg, pre-built) - * @param array $field_definitions Field definitions [field_name => required (bool)] - */ - private static function validateAllowedFields(array $item, string $name, string $type, array $field_definitions): void - { - // For source and pkg types, we need to check SOURCE_TYPE_FIELDS as well - $allowed_fields = array_keys($field_definitions); - - // For source/pkg, add allowed fields from SOURCE_TYPE_FIELDS based on the type - if (in_array($type, ['source', 'pkg']) && isset($item['type'], self::SOURCE_TYPE_FIELDS[$item['type']])) { - [$required, $optional] = self::SOURCE_TYPE_FIELDS[$item['type']]; - $allowed_fields = array_merge($allowed_fields, $required, $optional); - } - - // For lib and ext types, add fields with suffixes - if (in_array($type, ['lib', 'ext'])) { - $suffixes = ['-windows', '-unix', '-macos', '-linux']; - $base_fields = ['lib-depends', 'lib-suggests', 'static-libs', 'pkg-configs', 'headers', 'bin']; - if ($type === 'ext') { - $base_fields = ['lib-depends', 'lib-suggests', 'ext-depends', 'ext-suggests']; - // Add arg-type fields - foreach (array_merge([''], $suffixes) as $suffix) { - $allowed_fields[] = 'arg-type' . $suffix; - } - } - foreach ($base_fields as $field) { - foreach ($suffixes as $suffix) { - $allowed_fields[] = $field . $suffix; - } - } - // frameworks is lib-only - if ($type === 'lib') { - $allowed_fields[] = 'frameworks'; - } - } - - // Check each field in item - foreach (array_keys($item) as $field) { - if (!in_array($field, $allowed_fields)) { - throw new ValidationException("{$type} {$name} has unknown field [{$field}]"); - } - } - } -} diff --git a/src/SPC/util/CustomExt.php b/src/SPC/util/CustomExt.php deleted file mode 100644 index 04cc645f..00000000 --- a/src/SPC/util/CustomExt.php +++ /dev/null @@ -1,24 +0,0 @@ -, suggests: array}> - */ - public static function platExtToLibs(): array - { - $exts = Config::getExts(); - $libs = Config::getLibs(); - $dep_list = []; - foreach ($exts as $ext_name => $ext) { - // convert ext-depends value to ext@xxx - $ext_depends = Config::getExt($ext_name, 'ext-depends', []); - $ext_depends = array_map(fn ($x) => "ext@{$x}", $ext_depends); - // convert ext-suggests value to ext@xxx - $ext_suggests = Config::getExt($ext_name, 'ext-suggests', []); - $ext_suggests = array_map(fn ($x) => "ext@{$x}", $ext_suggests); - // merge ext-depends with lib-depends - $lib_depends = Config::getExt($ext_name, 'lib-depends', []); - $depends = array_merge($ext_depends, $lib_depends, ['php']); - // merge ext-suggests with lib-suggests - $lib_suggests = Config::getExt($ext_name, 'lib-suggests', []); - $suggests = array_merge($ext_suggests, $lib_suggests); - $dep_list["ext@{$ext_name}"] = [ - 'depends' => $depends, - 'suggests' => $suggests, - ]; - } - foreach ($libs as $lib_name => $lib) { - $dep_list[$lib_name] = [ - 'depends' => array_merge(Config::getLib($lib_name, 'lib-depends', []), ['lib-base']), - 'suggests' => Config::getLib($lib_name, 'lib-suggests', []), - ]; - } - // here is an array that only contains dependency map - return $dep_list; - } - - /** - * Get library dependencies in correct order - * - * @param array $libs Array of library names - * @return array Ordered array of library names - */ - public static function getLibs(array $libs, bool $include_suggested_libs = false): array - { - $dep_list = self::platExtToLibs(); - - if ($include_suggested_libs) { - foreach ($dep_list as $name => $obj) { - $del_list = []; - foreach ($obj['suggests'] as $id => $suggest) { - if (!str_starts_with($suggest, 'ext@')) { - $dep_list[$name]['depends'][] = $suggest; - $del_list[] = $id; - } - } - foreach ($del_list as $id) { - unset($dep_list[$name]['suggests'][$id]); - } - $dep_list[$name]['suggests'] = array_values($dep_list[$name]['suggests']); - } - } - - $final = self::doVisitPlat($libs, $dep_list); - - $libs_final = []; - foreach ($final as $item) { - if (!str_starts_with($item, 'ext@')) { - $libs_final[] = $item; - } - } - return $libs_final; - } - - /** - * Get extension dependencies in correct order - * - * @param array $exts Array of extension names - * @param array $additional_libs Array of additional libraries - * @return array Ordered array of extension names - */ - public static function getExtsAndLibs(array $exts, array $additional_libs = [], bool $include_suggested_exts = false, bool $include_suggested_libs = false): array - { - $dep_list = self::platExtToLibs(); - - // include suggested extensions - if ($include_suggested_exts) { - // check every deps suggests contains ext@ - foreach ($dep_list as $name => $obj) { - $del_list = []; - foreach ($obj['suggests'] as $id => $suggest) { - if (str_starts_with($suggest, 'ext@')) { - $dep_list[$name]['depends'][] = $suggest; - $del_list[] = $id; - } - } - foreach ($del_list as $id) { - unset($dep_list[$name]['suggests'][$id]); - } - $dep_list[$name]['suggests'] = array_values($dep_list[$name]['suggests']); - } - } - - // include suggested libraries - if ($include_suggested_libs) { - // check every deps suggests - foreach ($dep_list as $name => $obj) { - $del_list = []; - foreach ($obj['suggests'] as $id => $suggest) { - if (!str_starts_with($suggest, 'ext@')) { - $dep_list[$name]['depends'][] = $suggest; - $del_list[] = $id; - } - } - foreach ($del_list as $id) { - unset($dep_list[$name]['suggests'][$id]); - } - $dep_list[$name]['suggests'] = array_values($dep_list[$name]['suggests']); - } - } - - // convert ext_name to ext@ext_name - $origin_exts = $exts; - $exts = array_map(fn ($x) => "ext@{$x}", $exts); - $exts = array_merge($exts, $additional_libs); - - $final = self::doVisitPlat($exts, $dep_list); - - // revert array - $exts_final = []; - $libs_final = []; - $not_included_final = []; - foreach ($final as $item) { - if (str_starts_with($item, 'ext@')) { - $tmp = substr($item, 4); - if (!in_array($tmp, $origin_exts)) { - $not_included_final[] = $tmp; - } - $exts_final[] = $tmp; - } else { - $libs_final[] = $item; - } - } - return [$exts_final, $libs_final, $not_included_final]; - } - - private static function doVisitPlat(array $deps, array $dep_list): array - { - // default: get extension exts and libs sorted by dep_list - $sorted = []; - $visited = []; - foreach ($deps as $ext_name) { - if (!isset($dep_list[$ext_name])) { - $ext_name = str_starts_with($ext_name, 'ext@') ? ('Extension [' . substr($ext_name, 4) . ']') : ('Library [' . $ext_name . ']'); - throw new WrongUsageException("{$ext_name} not exist !"); - } - if (!isset($visited[$ext_name])) { - self::visitPlatDeps($ext_name, $dep_list, $visited, $sorted); - } - } - $sorted_suggests = []; - $visited_suggests = []; - $final = []; - foreach ($deps as $ext_name) { - if (!isset($visited_suggests[$ext_name])) { - self::visitPlatAllDeps($ext_name, $dep_list, $visited_suggests, $sorted_suggests); - } - } - foreach ($sorted_suggests as $suggest) { - if (in_array($suggest, $sorted)) { - $final[] = $suggest; - } - } - return $final; - } - - private static function visitPlatAllDeps(string $lib_name, array $dep_list, array &$visited, array &$sorted): void - { - // 如果已经识别到了,那就不管 - if (isset($visited[$lib_name])) { - return; - } - $visited[$lib_name] = true; - // 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常) - foreach (array_merge($dep_list[$lib_name]['depends'], $dep_list[$lib_name]['suggests']) as $dep) { - self::visitPlatAllDeps($dep, $dep_list, $visited, $sorted); - } - $sorted[] = $lib_name; - } - - private static function visitPlatDeps(string $lib_name, array $dep_list, array &$visited, array &$sorted): void - { - // 如果已经识别到了,那就不管 - if (isset($visited[$lib_name])) { - return; - } - $visited[$lib_name] = true; - // 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常) - if (!isset($dep_list[$lib_name])) { - throw new WrongUsageException("{$lib_name} not exist !"); - } - foreach ($dep_list[$lib_name]['depends'] as $dep) { - self::visitPlatDeps($dep, $dep_list, $visited, $sorted); - } - $sorted[] = $lib_name; - } -} diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php deleted file mode 100644 index 4ce3384d..00000000 --- a/src/SPC/util/GlobalEnvManager.php +++ /dev/null @@ -1,177 +0,0 @@ - $v) { - if (getenv($k) === false) { - $default_put_list[$k] = $v; - self::putenv("{$k}={$v}"); - } - } - $os_ini = match (PHP_OS_FAMILY) { - 'Windows' => $ini['windows'] ?? [], - 'Darwin' => $ini['macos'] ?? [], - 'Linux' => $ini['linux'] ?? [], - 'BSD' => $ini['freebsd'] ?? [], - default => [], - }; - foreach ($os_ini as $k => $v) { - if (getenv($k) === false) { - $default_put_list[$k] = $v; - self::putenv("{$k}={$v}"); - } - } - - ToolchainManager::initToolchain(); - - // apply second time - $ini2 = self::readIniFile(); - - foreach ($ini2['global'] as $k => $v) { - if (isset($default_put_list[$k]) && $default_put_list[$k] !== $v) { - self::putenv("{$k}={$v}"); - } - } - $os_ini2 = match (PHP_OS_FAMILY) { - 'Windows' => $ini2['windows'] ?? [], - 'Darwin' => $ini2['macos'] ?? [], - 'Linux' => $ini2['linux'] ?? [], - 'BSD' => $ini2['freebsd'] ?? [], - default => [], - }; - foreach ($os_ini2 as $k => $v) { - if (isset($default_put_list[$k]) && $default_put_list[$k] !== $v) { - self::putenv("{$k}={$v}"); - } - } - self::$initialized = true; - } - - public static function putenv(string $val): void - { - f_putenv($val); - self::$env_cache[] = $val; - } - - public static function addPathIfNotExists(string $path): void - { - if (is_unix() && !str_contains(getenv('PATH'), $path)) { - self::putenv("PATH={$path}:" . getenv('PATH')); - } - } - - /** - * Initialize the toolchain after the environment variables are set. - * The toolchain or environment availability check is done here. - */ - public static function afterInit(): void - { - if (!filter_var(getenv('SPC_SKIP_TOOLCHAIN_CHECK'), FILTER_VALIDATE_BOOL)) { - ToolchainManager::afterInitToolchain(); - } - // test bison - if (PHP_OS_FAMILY === 'Darwin') { - if ($bison = SystemUtil::findCommand('bison', ['/opt/homebrew/opt/bison/bin', '/usr/local/opt/bison/bin'])) { - self::putenv("BISON={$bison}"); - } - if ($yacc = SystemUtil::findCommand('yacc', ['/opt/homebrew/opt/bison/bin', '/usr/local/opt/bison/bin'])) { - self::putenv("YACC={$yacc}"); - } - } - } - - private static function readIniFile(): array - { - // Init env.ini file, read order: - // WORKING_DIR/config/env.ini - // ROOT_DIR/config/env.ini - $ini_files = [ - WORKING_DIR . '/config/env.ini', - ROOT_DIR . '/config/env.ini', - ]; - $ini_custom = [ - WORKING_DIR . '/config/env.custom.ini', - ROOT_DIR . '/config/env.custom.ini', - ]; - $ini = null; - foreach ($ini_files as $ini_file) { - if (file_exists($ini_file)) { - $ini = parse_ini_file($ini_file, true); - break; - } - } - if ($ini === null) { - throw new WrongUsageException('env.ini not found'); - } - if ($ini === false || !isset($ini['global'])) { - throw new WrongUsageException('Failed to parse ' . $ini_file); - } - // apply custom env - foreach ($ini_custom as $ini_file) { - if (file_exists($ini_file)) { - $ini_custom = parse_ini_file($ini_file, true); - if ($ini_custom !== false) { - $ini['global'] = array_merge($ini['global'], $ini_custom['global'] ?? []); - match (PHP_OS_FAMILY) { - 'Windows' => $ini['windows'] = array_merge($ini['windows'], $ini_custom['windows'] ?? []), - 'Darwin' => $ini['macos'] = array_merge($ini['macos'], $ini_custom['macos'] ?? []), - 'Linux' => $ini['linux'] = array_merge($ini['linux'], $ini_custom['linux'] ?? []), - 'BSD' => $ini['freebsd'] = array_merge($ini['freebsd'], $ini_custom['freebsd'] ?? []), - default => null, - }; - } - break; - } - } - return $ini; - } -} diff --git a/src/SPC/util/GlobalValueTrait.php b/src/SPC/util/GlobalValueTrait.php deleted file mode 100644 index d815b1f0..00000000 --- a/src/SPC/util/GlobalValueTrait.php +++ /dev/null @@ -1,28 +0,0 @@ -exts = array_merge($exts, $this->exts); - return $this; - } - - public function addLibs(array $libs): LicenseDumper - { - $this->libs = array_merge($libs, $this->libs); - return $this; - } - - public function addSources(array $sources): LicenseDumper - { - $this->sources = array_merge($sources, $this->sources); - return $this; - } - - /** - * Dump source licenses to target directory - * - * @param string $target_dir Target directory - * @return bool Success or not - */ - public function dump(string $target_dir): bool - { - // mkdir first - if (is_dir($target_dir) && !FileSystem::removeDir($target_dir)) { - logger()->warning('Target dump directory is not empty, be aware!'); - } - FileSystem::createDir($target_dir); - foreach ($this->exts as $ext) { - if (Config::getExt($ext, 'type') !== 'external') { - continue; - } - - $source_name = Config::getExt($ext, 'source'); - foreach ($this->getSourceLicenses($source_name) as $index => $license) { - $result = file_put_contents("{$target_dir}/ext_{$ext}_{$index}.txt", $license); - if ($result === false) { - return false; - } - } - } - - foreach ($this->libs as $lib) { - if (Config::getLib($lib, 'type', 'lib') !== 'lib') { - continue; - } - $source_name = Config::getLib($lib, 'source'); - foreach ($this->getSourceLicenses($source_name) as $index => $license) { - $result = file_put_contents("{$target_dir}/lib_{$lib}_{$index}.txt", $license); - if ($result === false) { - return false; - } - } - } - - foreach ($this->sources as $source) { - foreach ($this->getSourceLicenses($source) as $index => $license) { - $result = file_put_contents("{$target_dir}/src_{$source}_{$index}.txt", $license); - if ($result === false) { - return false; - } - } - } - return true; - } - - /** - * Returns an iterable of source licenses for a given source name. - * - * @param string $source_name Source name - * @return string[] String iterable of source licenses - */ - private function getSourceLicenses(string $source_name): iterable - { - $licenses = Config::getSource($source_name)['license'] ?? []; - if ($licenses === []) { - throw new SPCInternalException("source [{$source_name}] license meta not exist"); - } - - if (!array_is_list($licenses)) { - $licenses = [$licenses]; - } - - foreach ($licenses as $index => $license) { - yield $index => match ($license['type']) { - 'text' => $license['text'], - 'file' => $this->loadSourceFile($source_name, $index, $license['path'], Config::getSource($source_name)['path'] ?? null), - default => throw new SPCInternalException("source [{$source_name}] license type is not allowed"), - }; - } - } - - /** - * Loads a source license file from the specified path. - */ - private function loadSourceFile(string $source_name, int $index, array|string|null $in_path, ?string $custom_base_path = null): string - { - if (is_null($in_path)) { - throw new SPCInternalException("source [{$source_name}] license file is not set, please check config/source.json"); - } - - if (!is_array($in_path)) { - $in_path = [$in_path]; - } - - foreach ($in_path as $item) { - if (file_exists(SOURCE_PATH . '/' . ($custom_base_path ?? $source_name) . '/' . $item)) { - return file_get_contents(SOURCE_PATH . '/' . ($custom_base_path ?? $source_name) . '/' . $item); - } - } - - if (file_exists(BUILD_ROOT_PATH . '/source-licenses/' . $source_name . '/' . $index . '.txt')) { - return file_get_contents(BUILD_ROOT_PATH . '/source-licenses/' . $source_name . '/' . $index . '.txt'); - } - - throw new SPCInternalException("Cannot find any license file in source [{$source_name}] directory!"); - } -} diff --git a/src/SPC/util/PkgConfigUtil.php b/src/SPC/util/PkgConfigUtil.php deleted file mode 100644 index 25e0e1f2..00000000 --- a/src/SPC/util/PkgConfigUtil.php +++ /dev/null @@ -1,124 +0,0 @@ -builder = $builder; // BuilderProvider::makeBuilderByInput($input ?? new ArgvInput()); - } - $this->no_php = $options['no_php'] ?? false; - $this->libs_only_deps = $options['libs_only_deps'] ?? false; - $this->absolute_libs = $options['absolute_libs'] ?? false; - } - - /** - * Generate configuration for building PHP extensions. - * - * @param array $extensions Extension name list - * @param array $libraries Additional library name list - * @param bool $include_suggest_ext Include suggested extensions - * @param bool $include_suggest_lib Include suggested libraries - * @return array{ - * cflags: string, - * ldflags: string, - * libs: string - * } - */ - public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array - { - logger()->debug('config extensions: ' . implode(',', $extensions)); - logger()->debug('config libs: ' . implode(',', $libraries)); - logger()->debug('config suggest for [ext, lib]: ' . ($include_suggest_ext ? 'true' : 'false') . ',' . ($include_suggest_lib ? 'true' : 'false')); - $extra_exts = []; - foreach ($extensions as $ext) { - $extra_exts = array_merge($extra_exts, Config::getExt($ext, 'ext-suggests', [])); - } - foreach ($extra_exts as $ext) { - if ($this->builder?->getExt($ext) && !in_array($ext, $extensions)) { - $extensions[] = $ext; - } - } - [$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); - - ob_start(); - if ($this->builder === null) { - $this->builder = BuilderProvider::makeBuilderByInput(new ArgvInput()); - $this->builder->proveLibs($libraries); - $this->builder->proveExts($extensions, skip_extract: true); - } - ob_get_clean(); - $ldflags = $this->getLdflagsString(); - $cflags = $this->getIncludesString($libraries); - $libs = $this->getLibsString($libraries, !$this->absolute_libs); - - // additional OS-specific libraries (e.g. macOS -lresolv) - if ($extra_libs = SPCTarget::getRuntimeLibs()) { - $libs .= " {$extra_libs}"; - } - $extra_env = getenv('SPC_EXTRA_LIBS'); - if (is_string($extra_env) && !empty($extra_env)) { - $libs .= " {$extra_env}"; - } - // extension frameworks - if (SPCTarget::getTargetOS() === 'Darwin') { - $libs .= " {$this->getFrameworksString($extensions)}"; - } - if ($this->hasCpp($extensions, $libraries)) { - $libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++'; - $libs = str_replace($libcpp, '', $libs) . " {$libcpp}"; - } - - if ($this->libs_only_deps) { - // mimalloc must come first - if ($this->builder->getLib('mimalloc') && file_exists(BUILD_LIB_PATH . '/libmimalloc.a')) { - $libs = BUILD_LIB_PATH . '/libmimalloc.a ' . str_replace([BUILD_LIB_PATH . '/libmimalloc.a', '-lmimalloc'], ['', ''], $libs); - } - return [ - 'cflags' => clean_spaces(getenv('CFLAGS') . ' ' . $cflags), - 'ldflags' => clean_spaces(getenv('LDFLAGS') . ' ' . $ldflags), - 'libs' => clean_spaces(getenv('LIBS') . ' ' . $libs), - ]; - } - - // embed - if (!$this->no_php) { - $libs = "-lphp {$libs} -lc"; - } - - $allLibs = getenv('LIBS') . ' ' . $libs; - - // mimalloc must come first - if ($this->builder->getLib('mimalloc') && file_exists(BUILD_LIB_PATH . '/libmimalloc.a')) { - $allLibs = BUILD_LIB_PATH . '/libmimalloc.a ' . str_replace([BUILD_LIB_PATH . '/libmimalloc.a', '-lmimalloc'], ['', ''], $allLibs); - } - - return [ - 'cflags' => clean_spaces(getenv('CFLAGS') . ' ' . $cflags), - 'ldflags' => clean_spaces(getenv('LDFLAGS') . ' ' . $ldflags), - 'libs' => clean_spaces($allLibs), - ]; - } - - /** - * [Helper function] - * Get configuration for a specific extension(s) dependencies. - * - * @param Extension|Extension[] $extension Extension instance or list - * @param bool $include_suggest_ext Whether to include suggested extensions - * @param bool $include_suggest_lib Whether to include suggested libraries - * @return array{ - * cflags: string, - * ldflags: string, - * libs: string - * } - */ - public function getExtensionConfig(array|Extension $extension, bool $include_suggest_ext = false, bool $include_suggest_lib = false): array - { - if (!is_array($extension)) { - $extension = [$extension]; - } - $libs = array_map(fn ($y) => $y->getName(), array_merge(...array_map(fn ($x) => $x->getLibraryDependencies(true), $extension))); - return $this->config( - extensions: array_map(fn ($x) => $x->getName(), $extension), - libraries: $libs, - include_suggest_ext: $include_suggest_ext ?: $this->builder?->getOption('with-suggested-exts') ?? false, - include_suggest_lib: $include_suggest_lib ?: $this->builder?->getOption('with-suggested-libs') ?? false, - ); - } - - /** - * [Helper function] - * Get configuration for a specific library(s) dependencies. - * - * @param LibraryBase|LibraryBase[] $lib Library instance or list - * @param bool $include_suggest_lib Whether to include suggested libraries - * @return array{ - * cflags: string, - * ldflags: string, - * libs: string - * } - */ - public function getLibraryConfig(array|LibraryBase $lib, bool $include_suggest_lib = false): array - { - if (!is_array($lib)) { - $lib = [$lib]; - } - $save_no_php = $this->no_php; - $this->no_php = true; - $save_libs_only_deps = $this->libs_only_deps; - $this->libs_only_deps = true; - $ret = $this->config( - libraries: array_map(fn ($x) => $x->getName(), $lib), - include_suggest_lib: $include_suggest_lib ?: $this->builder?->getOption('with-suggested-libs') ?? false, - ); - $this->no_php = $save_no_php; - $this->libs_only_deps = $save_libs_only_deps; - return $ret; - } - - private function hasCpp(array $extensions, array $libraries): bool - { - // judge cpp-extension - $builderExtNames = array_keys($this->builder->getExts(false)); - $exts = array_unique([...$builderExtNames, ...$extensions]); - - foreach ($exts as $ext) { - if (Config::getExt($ext, 'cpp-extension', false) === true) { - return true; - } - } - $builderLibNames = array_keys($this->builder->getLibs()); - $libs = array_unique([...$builderLibNames, ...$libraries]); - foreach ($libs as $lib) { - if (Config::getLib($lib, 'cpp-library', false) === true) { - return true; - } - } - return false; - } - - private function getIncludesString(array $libraries): string - { - $base = BUILD_INCLUDE_PATH; - $includes = ["-I{$base}"]; - - // link with libphp - if (!$this->no_php) { - $includes = [ - ...$includes, - "-I{$base}/php", - "-I{$base}/php/main", - "-I{$base}/php/TSRM", - "-I{$base}/php/Zend", - "-I{$base}/php/ext", - ]; - } - - // 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) { - $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); - if ($pc_cflags !== '' && ($pc_cflags = PkgConfigUtil::getCflags($pc_cflags)) !== '') { - $arr = explode(' ', $pc_cflags); - $arr = array_unique($arr); - $arr = array_filter($arr, fn ($x) => !str_starts_with($x, 'SHELL:-Xarch_')); - $pc_cflags = implode(' ', $arr); - $includes[] = $pc_cflags; - } - } - $includes = array_unique($includes); - return implode(' ', $includes); - } - - private function getLdflagsString(): string - { - return '-L' . BUILD_LIB_PATH; - } - - private function getLibsString(array $libraries, bool $use_short_libs = true): string - { - $lib_names = []; - $frameworks = []; - - foreach ($libraries as $library) { - // add pkg-configs libs - $pkg_configs = Config::getLib($library, 'pkg-configs', []); - $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); - if ($pkg_configs !== '') { - // static libs with dependencies come in reverse order, so reverse this too - $pc_libs = array_reverse(PkgConfigUtil::getLibsArray($pkg_configs)); - $lib_names = [...$lib_names, ...$pc_libs]; - } - // convert all static-libs to short names - $libs = array_reverse(Config::getLib($library, 'static-libs', [])); - foreach ($libs as $lib) { - // check file existence - if (!file_exists(BUILD_LIB_PATH . "/{$lib}")) { - throw new WrongUsageException("Library file '{$lib}' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "'. Please build it first."); - } - $lib_names[] = $this->getShortLibName($lib); - } - // add frameworks for macOS - if (SPCTarget::getTargetOS() === 'Darwin') { - $frameworks = array_merge($frameworks, Config::getLib($library, 'frameworks', [])); - } - } - - // post-process - $lib_names = array_filter($lib_names, fn ($x) => $x !== ''); - $lib_names = array_reverse(array_unique($lib_names)); - $frameworks = array_unique($frameworks); - - // process frameworks to short_name - if (SPCTarget::getTargetOS() === 'Darwin') { - foreach ($frameworks as $fw) { - $ks = '-framework ' . $fw; - if (!in_array($ks, $lib_names)) { - $lib_names[] = $ks; - } - } - } - - if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') { - $lib_names[] = '-lcrypt'; - } - if (!$use_short_libs) { - $lib_names = array_map(fn ($l) => $this->getFullLibName($l), $lib_names); - } - return implode(' ', $lib_names); - } - - private function getShortLibName(string $lib): string - { - if (!str_starts_with($lib, 'lib') || !str_ends_with($lib, '.a')) { - return BUILD_LIB_PATH . '/' . $lib; - } - // get short name - return '-l' . substr($lib, 3, -2); - } - - private function getFullLibName(string $lib) - { - if (!str_starts_with($lib, '-l')) { - return $lib; - } - $libname = substr($lib, 2); - $staticLib = BUILD_LIB_PATH . '/' . "lib{$libname}.a"; - if (file_exists($staticLib)) { - return $staticLib; - } - return $lib; - } - - private function getFrameworksString(array $extensions): string - { - $list = []; - foreach ($extensions as $extension) { - foreach (Config::getExt($extension, 'frameworks', []) as $fw) { - $ks = '-framework ' . $fw; - if (!in_array($ks, $list)) { - $list[] = $ks; - } - } - } - return implode(' ', $list); - } -} diff --git a/src/SPC/util/SPCTarget.php b/src/SPC/util/SPCTarget.php deleted file mode 100644 index 037c6d8c..00000000 --- a/src/SPC/util/SPCTarget.php +++ /dev/null @@ -1,130 +0,0 @@ - 'Linux', - str_contains($target, '-macos') => 'Darwin', - str_contains($target, '-windows') => 'Windows', - str_contains($target, '-native') => PHP_OS_FAMILY, - default => PHP_OS_FAMILY, - }; - } -} diff --git a/src/SPC/util/executor/Executor.php b/src/SPC/util/executor/Executor.php deleted file mode 100644 index 05bb408c..00000000 --- a/src/SPC/util/executor/Executor.php +++ /dev/null @@ -1,20 +0,0 @@ -initShell(); - $this->configure_args = $this->getDefaultConfigureArgs(); - } - - /** - * Run ./configure - */ - public function configure(...$args): static - { - $args = array_merge($args, $this->configure_args); - $configure_args = implode(' ', $args); - - return $this->seekLogFileOnException(fn () => $this->shell->exec("./configure {$configure_args}")); - } - - /** - * Run make - * - * @param string $target Build target - * @param false|string $with_install Run `make install` after building, or false to skip - * @param bool $with_clean Whether to clean before building - * @param array $after_env_vars Environment variables postfix - */ - public function make(string $target = '', false|string $with_install = 'install', bool $with_clean = true, array $after_env_vars = [], ?string $dir = null): static - { - return $this->seekLogFileOnException(function () use ($target, $with_install, $with_clean, $after_env_vars, $dir) { - $shell = $this->shell; - if ($dir) { - $shell = $shell->cd($dir); - } - if ($with_clean) { - $shell->exec('make clean'); - } - $after_env_vars_str = $after_env_vars !== [] ? shell()->setEnv($after_env_vars)->getEnvString() : ''; - $shell->exec("make -j{$this->library->getBuilder()->concurrency} {$target} {$after_env_vars_str}"); - if ($with_install !== false) { - $shell->exec("make {$with_install}"); - } - return $shell; - }); - } - - public function exec(string $cmd): static - { - $this->shell->exec($cmd); - return $this; - } - - /** - * Add optional library configuration. - * This method checks if a library is available and adds the corresponding arguments to the CMake configuration. - * - * @param string $name library name to check - * @param \Closure|string $true_args arguments to use if the library is available (allow closure, returns string) - * @param string $false_args arguments to use if the library is not available - * @return $this - */ - public function optionalLib(string $name, \Closure|string $true_args, string $false_args = ''): static - { - if ($get = $this->library->getBuilder()->getLib($name)) { - logger()->info("Building library [{$this->library->getName()}] with {$name} support"); - $args = $true_args instanceof \Closure ? $true_args($get) : $true_args; - } else { - logger()->info("Building library [{$this->library->getName()}] without {$name} support"); - $args = $false_args; - } - $this->addConfigureArgs($args); - return $this; - } - - /** - * Add configure args. - */ - public function addConfigureArgs(...$args): static - { - $this->configure_args = [...$this->configure_args, ...$args]; - return $this; - } - - /** - * Remove some configure args, to bypass the configure option checking for some libs. - */ - public function removeConfigureArgs(...$args): static - { - $this->configure_args = array_diff($this->configure_args, $args); - return $this; - } - - public function setEnv(array $env): static - { - $this->shell->setEnv($env); - return $this; - } - - public function appendEnv(array $env): static - { - $this->shell->appendEnv($env); - return $this; - } - - /** - * Returns the default autoconf ./configure arguments - */ - private function getDefaultConfigureArgs(): array - { - return [ - '--enable-static', - '--disable-shared', - "--prefix={$this->library->getBuildRootPath()}", - '--with-pic', - '--enable-pic', - ]; - } - - /** - * Initialize UnixShell class. - */ - private function initShell(): void - { - $this->shell = shell()->cd($this->library->getSourceDir())->initializeEnv($this->library)->appendEnv([ - 'CFLAGS' => "-I{$this->library->getIncludeDir()}", - 'CXXFLAGS' => "-I{$this->library->getIncludeDir()}", - 'LDFLAGS' => "-L{$this->library->getLibDir()}", - ]); - } - - /** - * When an exception occurs, this method will check if the config log file exists. - */ - private function seekLogFileOnException(mixed $callable): static - { - try { - $callable(); - return $this; - } catch (SPCException $e) { - if (file_exists("{$this->library->getSourceDir()}/config.log")) { - logger()->debug("Config log file found: {$this->library->getSourceDir()}/config.log"); - $log_file = "lib.{$this->library->getName()}.console.log"; - logger()->debug('Saved config log file to: ' . SPC_LOGS_DIR . "/{$log_file}"); - $e->addExtraLogFile("{$this->library->getName()} library config.log", $log_file); - copy("{$this->library->getSourceDir()}/config.log", SPC_LOGS_DIR . "/{$log_file}"); - } - throw $e; - } - } -} diff --git a/src/SPC/util/executor/UnixCMakeExecutor.php b/src/SPC/util/executor/UnixCMakeExecutor.php deleted file mode 100644 index d0241f56..00000000 --- a/src/SPC/util/executor/UnixCMakeExecutor.php +++ /dev/null @@ -1,230 +0,0 @@ -initShell(); - } - - public function build(string $build_pos = '..'): void - { - // set cmake dir - $this->initBuildDir(); - - if ($this->reset) { - FileSystem::resetDir($this->build_dir); - } - - $this->shell = $this->shell->cd($this->build_dir); - - // config - $this->steps >= 1 && $this->shell->exec("cmake {$this->getConfigureArgs()} {$this->getDefaultCMakeArgs()} {$build_pos}"); - - // make - $this->steps >= 2 && $this->shell->exec("cmake --build . -j {$this->library->getBuilder()->concurrency}"); - - // install - $this->steps >= 3 && $this->shell->exec('make install'); - } - - /** - * Add optional library configuration. - * This method checks if a library is available and adds the corresponding arguments to the CMake configuration. - * - * @param string $name library name to check - * @param \Closure|string $true_args arguments to use if the library is available (allow closure, returns string) - * @param string $false_args arguments to use if the library is not available - * @return $this - */ - public function optionalLib(string $name, \Closure|string $true_args, string $false_args = ''): static - { - if ($get = $this->library->getBuilder()->getLib($name)) { - logger()->info("Building library [{$this->library->getName()}] with {$name} support"); - $args = $true_args instanceof \Closure ? $true_args($get) : $true_args; - } else { - logger()->info("Building library [{$this->library->getName()}] without {$name} support"); - $args = $false_args; - } - $this->addConfigureArgs($args); - return $this; - } - - /** - * Add configure args. - */ - public function addConfigureArgs(...$args): static - { - $this->configure_args = [...$this->configure_args, ...$args]; - return $this; - } - - public function appendEnv(array $env): static - { - $this->shell->appendEnv($env); - return $this; - } - - /** - * To build steps. - * - * @param int $step Step number, accept 1-3 - * @return $this - */ - public function toStep(int $step): static - { - $this->steps = $step; - return $this; - } - - /** - * Set custom CMake build directory. - * - * @param string $dir custom CMake build directory - */ - public function setBuildDir(string $dir): static - { - $this->build_dir = $dir; - return $this; - } - - /** - * Set the custom default args. - */ - public function setCustomDefaultArgs(...$args): static - { - $this->custom_default_args = $args; - return $this; - } - - /** - * Set the reset status. - * If we set it to false, it will not clean and create the specified cmake working directory. - */ - public function setReset(bool $reset): static - { - $this->reset = $reset; - return $this; - } - - /** - * Get configure argument line. - */ - private function getConfigureArgs(): string - { - return implode(' ', $this->configure_args); - } - - private function getDefaultCMakeArgs(): string - { - return implode(' ', $this->custom_default_args ?? [ - '-DCMAKE_BUILD_TYPE=Release', - "-DCMAKE_INSTALL_PREFIX={$this->library->getBuildRootPath()}", - '-DCMAKE_INSTALL_BINDIR=bin', - '-DCMAKE_INSTALL_LIBDIR=lib', - '-DCMAKE_INSTALL_INCLUDEDIR=include', - '-DPOSITION_INDEPENDENT_CODE=ON', - '-DBUILD_SHARED_LIBS=OFF', - "-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}", - ]); - } - - /** - * Initialize the CMake build directory. - * If the directory is not set, it defaults to the library's source directory with '/build' appended. - */ - private function initBuildDir(): void - { - if ($this->build_dir === null) { - $this->build_dir = "{$this->library->getSourceDir()}/build"; - } - } - - /** - * Generate cmake toolchain file for current spc instance, and return the file path. - * - * @return string CMake toolchain file path - */ - private function makeCmakeToolchainFile(): string - { - static $created; - if (isset($created)) { - return $created; - } - $os = PHP_OS_FAMILY; - $target_arch = arch2gnu(php_uname('m')); - $cflags = getenv('SPC_DEFAULT_C_FLAGS'); - $cc = getenv('CC'); - $cxx = getenv('CCX'); - $include = BUILD_INCLUDE_PATH; - logger()->debug("making cmake tool chain file for {$os} {$target_arch} with CFLAGS='{$cflags}'"); - $root = BUILD_ROOT_PATH; - $pkgConfigExecutable = PkgConfigUtil::findPkgConfig(); - $ccLine = ''; - if ($cc) { - $ccLine = 'SET(CMAKE_C_COMPILER ' . $cc . ')'; - } - $cxxLine = ''; - if ($cxx) { - $cxxLine = 'SET(CMAKE_CXX_COMPILER ' . $cxx . ')'; - } - $toolchain = <<shell = shell()->initializeEnv($this->library); - } -} diff --git a/src/SPC/util/shell/Shell.php b/src/SPC/util/shell/Shell.php deleted file mode 100644 index bfa51b86..00000000 --- a/src/SPC/util/shell/Shell.php +++ /dev/null @@ -1,173 +0,0 @@ -debug = $debug ?? defined('DEBUG_MODE'); - $this->enable_log_file = $enable_log_file; - } - - /** - * Equivalent to `cd` command in shell. - * - * @param string $dir Directory to change to - */ - public function cd(string $dir): static - { - logger()->debug('Entering dir: ' . $dir); - $c = clone $this; - $c->cd = $dir; - return $c; - } - - public function setEnv(array $env): static - { - foreach ($env as $k => $v) { - if (trim($v) === '') { - continue; - } - $this->env[$k] = trim($v); - } - return $this; - } - - public function appendEnv(array $env): static - { - foreach ($env as $k => $v) { - if ($v === '') { - continue; - } - if (!isset($this->env[$k])) { - $this->env[$k] = $v; - } else { - $this->env[$k] = "{$v} {$this->env[$k]}"; - } - } - return $this; - } - - /** - * Executes a command in the shell. - */ - abstract public function exec(string $cmd): static; - - /** - * Returns the last executed command. - */ - public function getLastCommand(): string - { - return $this->last_cmd; - } - - /** - * Executes a command with console and log file output. - * - * @param string $cmd Full command to execute (including cd and env vars) - * @param bool $console_output If true, output will be printed to console - * @param null|string $original_command Original command string for logging - */ - protected function passthru(string $cmd, bool $console_output = false, ?string $original_command = null): void - { - // write executed command to the log file using fwrite - $file_res = fopen(SPC_SHELL_LOG, 'a'); - if ($console_output) { - $console_res = STDOUT; - } - $descriptors = [ - 0 => ['file', 'php://stdin', 'r'], // stdin - 1 => ['pipe', 'w'], // stdout - 2 => ['pipe', 'w'], // stderr - ]; - $process = proc_open($cmd, $descriptors, $pipes); - - try { - if (!is_resource($process)) { - throw new ExecutionException( - cmd: $original_command ?? $cmd, - message: 'Failed to open process for command, proc_open() failed.', - code: -1, - cd: $this->cd, - env: $this->env - ); - } - // fclose($pipes[0]); - stream_set_blocking($pipes[1], false); - stream_set_blocking($pipes[2], false); - - while (true) { - $read = [$pipes[1], $pipes[2]]; - $write = null; - $except = null; - - $ready = stream_select($read, $write, $except, 0, 100000); - - if ($ready === false) { - $status = proc_get_status($process); - if (!$status['running']) { - break; - } - continue; - } - - if ($ready > 0) { - foreach ($read as $pipe) { - $chunk = fgets($pipe); - if ($chunk !== false) { - if ($console_output) { - fwrite($console_res, $chunk); - } - if ($this->enable_log_file) { - fwrite($file_res, $chunk); - } - } - } - } - - $status = proc_get_status($process); - if (!$status['running']) { - // check exit code - if ($status['exitcode'] !== 0) { - if ($this->enable_log_file) { - fwrite($file_res, "Command exited with non-zero code: {$status['exitcode']}\n"); - } - throw new ExecutionException( - cmd: $original_command ?? $cmd, - message: "Command exited with non-zero code: {$status['exitcode']}", - code: $status['exitcode'], - cd: $this->cd, - env: $this->env, - ); - } - break; - } - } - } finally { - fclose($pipes[1]); - fclose($pipes[2]); - fclose($file_res); - proc_close($process); - } - } - - /** - * Logs the command information to a log file. - */ - abstract protected function logCommandInfo(string $cmd): void; -} diff --git a/src/SPC/util/shell/UnixShell.php b/src/SPC/util/shell/UnixShell.php deleted file mode 100644 index 2fdc1b07..00000000 --- a/src/SPC/util/shell/UnixShell.php +++ /dev/null @@ -1,116 +0,0 @@ -info(ConsoleColor::yellow('[EXEC] ') . ConsoleColor::green($cmd)); - $original_command = $cmd; - $this->logCommandInfo($original_command); - $this->last_cmd = $cmd = $this->getExecString($cmd); - $this->passthru($cmd, $this->debug, $original_command); - return $this; - } - - /** - * Init the environment variable that common build will be used. - * - * @param BSDLibraryBase|LinuxLibraryBase|MacOSLibraryBase $library Library class - */ - public function initializeEnv(BSDLibraryBase|LinuxLibraryBase|MacOSLibraryBase $library): UnixShell - { - $this->setEnv([ - 'CFLAGS' => $library->getLibExtraCFlags(), - 'CXXFLAGS' => $library->getLibExtraCXXFlags(), - 'LDFLAGS' => $library->getLibExtraLdFlags(), - 'LIBS' => $library->getLibExtraLibs() . SPCTarget::getRuntimeLibs(), - ]); - return $this; - } - - public function execWithResult(string $cmd, bool $with_log = true): array - { - if ($with_log) { - /* @phpstan-ignore-next-line */ - logger()->info(ConsoleColor::blue('[EXEC] ') . ConsoleColor::green($cmd)); - } else { - /* @phpstan-ignore-next-line */ - logger()->debug(ConsoleColor::blue('[EXEC] ') . ConsoleColor::gray($cmd)); - } - $cmd = $this->getExecString($cmd); - exec($cmd, $out, $code); - return [$code, $out]; - } - - /** - * Returns unix-style environment variable string. - */ - public function getEnvString(): string - { - $str = ''; - foreach ($this->env as $k => $v) { - $str .= ' ' . $k . '="' . $v . '"'; - } - return trim($str); - } - - protected function logCommandInfo(string $cmd): void - { - // write executed command to log file using fwrite - $log_file = fopen(SPC_SHELL_LOG, 'a'); - fwrite($log_file, "\n>>>>>>>>>>>>>>>>>>>>>>>>>> [" . date('Y-m-d H:i:s') . "]\n"); - fwrite($log_file, "> Executing command: {$cmd}\n"); - // get the backtrace to find the file and line number - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); - if (isset($backtrace[1]['file'], $backtrace[1]['line'])) { - $file = $backtrace[1]['file']; - $line = $backtrace[1]['line']; - fwrite($log_file, "> Called from: {$file} at line {$line}\n"); - } - fwrite($log_file, "> Environment variables: {$this->getEnvString()}\n"); - if ($this->cd !== null) { - fwrite($log_file, "> Working dir: {$this->cd}\n"); - } - fwrite($log_file, "\n"); - } - - private function getExecString(string $cmd): string - { - // logger()->debug('Executed at: ' . debug_backtrace()[0]['file'] . ':' . debug_backtrace()[0]['line']); - $env_str = $this->getEnvString(); - if (!empty($env_str)) { - $cmd = "{$env_str} {$cmd}"; - } - if ($this->cd !== null) { - $cmd = 'cd ' . escapeshellarg($this->cd) . ' && ' . $cmd; - } - return $cmd; - } -} diff --git a/src/SPC/util/shell/WindowsCmd.php b/src/SPC/util/shell/WindowsCmd.php deleted file mode 100644 index aa558e63..00000000 --- a/src/SPC/util/shell/WindowsCmd.php +++ /dev/null @@ -1,135 +0,0 @@ -info(ConsoleColor::yellow('[EXEC] ') . ConsoleColor::green($cmd)); - - $original_command = $cmd; - $this->logCommandInfo($original_command); - $this->last_cmd = $cmd = $this->getExecString($cmd); - // echo $cmd . PHP_EOL; - - $this->passthru($cmd, $this->debug, $original_command); - return $this; - } - - public function execWithWrapper(string $wrapper, string $args): WindowsCmd - { - return $this->exec($wrapper . ' "' . str_replace('"', '^"', $args) . '"'); - } - - public function execWithResult(string $cmd, bool $with_log = true): array - { - if ($with_log) { - /* @phpstan-ignore-next-line */ - logger()->info(ConsoleColor::blue('[EXEC] ') . ConsoleColor::green($cmd)); - } else { - logger()->debug('Running command with result: ' . $cmd); - } - exec($cmd, $out, $code); - return [$code, $out]; - } - - public function setEnv(array $env): static - { - // windows currently does not support setting environment variables - throw new SPCInternalException('Windows does not support setting environment variables in shell commands.'); - } - - public function appendEnv(array $env): static - { - // windows currently does not support appending environment variables - throw new SPCInternalException('Windows does not support appending environment variables in shell commands.'); - } - - public function getLastCommand(): string - { - return $this->last_cmd; - } - - protected function passthru(string $cmd, bool $console_output = false, ?string $original_command = null): void - { - $file_res = null; - if ($this->enable_log_file) { - $file_res = fopen(SPC_SHELL_LOG, 'a'); - } - - try { - $process = popen($cmd . ' 2>&1', 'r'); - if (!$process) { - throw new ExecutionException( - cmd: $original_command ?? $cmd, - message: 'Failed to open process for command, popen() failed.', - code: -1, - cd: $this->cd, - env: $this->env - ); - } - - while (($line = fgets($process)) !== false) { - if ($console_output) { - echo $line; - } - fwrite($file_res, $line); - } - - $result_code = pclose($process); - - if ($result_code !== 0) { - if ($file_res) { - fwrite($file_res, "Command exited with non-zero code: {$result_code}\n"); - } - throw new ExecutionException( - cmd: $original_command ?? $cmd, - message: "Command exited with non-zero code: {$result_code}", - code: $result_code, - cd: $this->cd, - env: $this->env, - ); - } - } finally { - if ($file_res) { - fclose($file_res); - } - } - } - - protected function logCommandInfo(string $cmd): void - { - // write executed command to the log file using fwrite - $log_file = fopen(SPC_SHELL_LOG, 'a'); - fwrite($log_file, "\n>>>>>>>>>>>>>>>>>>>>>>>>>> [" . date('Y-m-d H:i:s') . "]\n"); - fwrite($log_file, "> Executing command: {$cmd}\n"); - if ($this->cd !== null) { - fwrite($log_file, "> Working dir: {$this->cd}\n"); - } - fwrite($log_file, "\n"); - } - - private function getExecString(string $cmd): string - { - if ($this->cd !== null) { - $cmd = 'cd /d ' . escapeshellarg($this->cd) . ' && ' . $cmd; - } - return $cmd; - } -} diff --git a/src/StaticPHP/Package/PackageInstaller.php b/src/StaticPHP/Package/PackageInstaller.php index b4c041df..1f778a0d 100644 --- a/src/StaticPHP/Package/PackageInstaller.php +++ b/src/StaticPHP/Package/PackageInstaller.php @@ -154,10 +154,9 @@ class PackageInstaller $this->resolvePackages(); } - // show install or build options in terminal with beautiful output - $this->printInstallerInfo(); - if ($this->interactive && !$disable_delay_msg) { + // show install or build options in terminal with beautiful output + $this->printInstallerInfo(); InteractiveTerm::notice('Build process will start after 2s ...' . PHP_EOL); sleep(2); }