| @@ -2,28 +2,35 @@ name: Precompile PHP |
| 2 | 2 | |
| 3 | 3 | on: |
| 4 | 4 | push: |
| 5 | | - branches: [main, develop] |
| 6 | | - paths: |
| 7 | | - - .github/workflows/precompile-php.yml |
| 8 | | - - build-configs/** |
| 9 | | - - scripts/get-php-versions.ts |
| 10 | | - - scripts/check-php-updates.ts |
| 5 | + branches: [main] |
| 11 | 6 | schedule: |
| 12 | 7 | |
| 13 | 8 | - cron: '0 2 * * *' |
| 14 | 9 | workflow_dispatch: |
| 15 | 10 | inputs: |
| 11 | + php_version: |
| 12 | + description: 'PHP version to build (leave empty for auto-detection)' |
| 13 | + required: false |
| 14 | + type: string |
| 15 | + php_config: |
| 16 | + description: 'PHP build configuration' |
| 17 | + required: true |
| 18 | + default: 'laravel-mysql' |
| 19 | + type: choice |
| 20 | + options: |
| 21 | + - laravel-mysql |
| 22 | + - laravel-postgres |
| 23 | + - laravel-sqlite |
| 24 | + - api-only |
| 25 | + - enterprise |
| 26 | + - wordpress |
| 27 | + - full-stack |
| 16 | 28 | force_rebuild: |
| 17 | | - description: Force rebuild even if no new versions |
| 29 | + description: 'Force rebuild even if no updates' |
| 18 | 30 | required: false |
| 19 | 31 | default: false |
| 20 | 32 | type: boolean |
| 21 | 33 | |
| 22 | | -env: |
| 23 | | - REGISTRY_URL: ghcr.io |
| 24 | | - REGISTRY_USERNAME: ${{ github.actor }} |
| 25 | | - REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} |
| 26 | | - |
| 27 | 34 | jobs: |
| 28 | 35 | |
| 29 | 36 | check-for-updates: |
| @@ -68,7 +75,7 @@ jobs: |
| 68 | 75 | get-php-versions: |
| 69 | 76 | needs: check-for-updates |
| 70 | 77 | runs-on: ubuntu-latest |
| 71 | | - if: needs.check-for-updates.outputs.rebuild_needed == 'true' || github.event.inputs.force_rebuild == 'true' |
| 78 | + if: needs.check-for-updates.outputs.rebuild_needed == 'true' || github.event.inputs.force_rebuild == 'true' || github.event.inputs.php_version != '' |
| 72 | 79 | outputs: |
| 73 | 80 | php_versions: ${{ steps.get-versions.outputs.php_versions }} |
| 74 | 81 | steps: |
| @@ -83,937 +90,417 @@ jobs: |
| 83 | 90 | - name: Get PHP versions from ts-pkgx |
| 84 | 91 | id: get-versions |
| 85 | 92 | run: | |
| 86 | | - |
| 87 | | - PHP_VERSIONS=$(bun scripts/get-php-versions.ts | grep "JSON output for GitHub Actions:" -A 1 | tail -1) |
| 93 | + if [ -n "$" ]; then |
| 94 | + |
| 95 | + PHP_VERSIONS='["$"]' |
| 96 | + else |
| 97 | + |
| 98 | + PHP_VERSIONS=$(bun scripts/get-php-versions.ts | grep "JSON output for GitHub Actions:" -A 1 | tail -1) |
| 99 | + fi |
| 88 | 100 | echo "php_versions=$PHP_VERSIONS" >> $GITHUB_OUTPUT |
| 89 | 101 | echo "🔍 Dynamic PHP versions: $PHP_VERSIONS" |
| 90 | 102 | |
| 91 | | - |
| 92 | | - no-rebuild-needed: |
| 93 | | - needs: check-for-updates |
| 94 | | - runs-on: ubuntu-latest |
| 95 | | - if: needs.check-for-updates.outputs.rebuild_needed == 'false' && github.event.inputs.force_rebuild != 'true' |
| 96 | | - steps: |
| 97 | | - - name: Checkout repository |
| 98 | | - uses: actions/checkout@v4 |
| 99 | | - |
| 100 | | - - name: No rebuild needed |
| 101 | | - run: | |
| 102 | | - echo "✅ No rebuild needed" |
| 103 | | - echo "Reason: $" |
| 104 | | - echo "Current versions: $" |
| 105 | | - echo "Latest versions: $" |
| 106 | | - echo "" |
| 107 | | - echo "The workflow will skip building since no new PHP versions are available." |
| 108 | | - echo "To force a rebuild, use the 'force_rebuild' input parameter." |
| 109 | | - |
| 110 | | - |
| 111 | | - build-matrix: |
| 103 | + build: |
| 112 | 104 | needs: [check-for-updates, get-php-versions] |
| 113 | | - runs-on: ${{ matrix.os }} |
| 114 | | - if: needs.check-for-updates.outputs.rebuild_needed == 'true' || github.event.inputs.force_rebuild == 'true' |
| 105 | + if: needs.check-for-updates.outputs.rebuild_needed == 'true' || github.event.inputs.force_rebuild == 'true' || github.event.inputs.php_version != '' |
| 115 | 106 | strategy: |
| 116 | 107 | fail-fast: false |
| 117 | 108 | matrix: |
| 118 | | - os: [ubuntu-latest, macos-latest, macos-13] |
| 119 | | - php_version: ${{ fromJSON(needs.get-php-versions.outputs.php_versions) }} |
| 120 | | - config: [laravel-mysql, laravel-postgres, laravel-sqlite, api-only, enterprise, wordpress, full-stack] |
| 109 | + php_version: ${{ fromJson(needs.get-php-versions.outputs.php_versions) }} |
| 110 | + config: |
| 111 | + - laravel-mysql |
| 112 | + - laravel-postgres |
| 113 | + - laravel-sqlite |
| 114 | + - api-only |
| 115 | + - enterprise |
| 116 | + - wordpress |
| 117 | + - full-stack |
| 118 | + os: |
| 119 | + - ubuntu-latest |
| 120 | + - macos-13 |
| 121 | + - macos-latest |
| 122 | + - windows-latest |
| 121 | 123 | include: |
| 122 | | - |
| 123 | 124 | - os: ubuntu-latest |
| 124 | 125 | platform: linux |
| 125 | 126 | arch: x86_64 |
| 127 | + - os: macos-13 |
| 128 | + platform: darwin |
| 129 | + arch: x86_64 |
| 126 | 130 | - os: macos-latest |
| 127 | 131 | platform: darwin |
| 128 | 132 | arch: arm64 |
| 129 | | - - os: macos-13 |
| 130 | | - platform: darwin |
| 133 | + - os: windows-latest |
| 134 | + platform: win32 |
| 131 | 135 | arch: x86_64 |
| 132 | | - exclude: |
| 133 | | - |
| 134 | | - - os: macos-13 |
| 135 | | - config: api-only |
| 136 | | - |
| 137 | | - - os: macos-13 |
| 138 | | - config: wordpress |
| 136 | + |
| 137 | + runs-on: ${{ matrix.os }} |
| 139 | 138 | |
| 140 | 139 | steps: |
| 141 | | - - name: Checkout repository |
| 140 | + - name: Checkout code |
| 142 | 141 | uses: actions/checkout@v4 |
| 143 | 142 | |
| 144 | | - - name: Set up build environment |
| 145 | | - run: | |
| 146 | | - echo "Building PHP $ for $-$" |
| 147 | | - echo "Configuration: $" |
| 148 | | - echo "BINARY_NAME=php-$-$-$-$" >> $GITHUB_ENV |
| 149 | | - echo "BUILD_DIR=$/build" >> $GITHUB_ENV |
| 150 | | - echo "OUTPUT_DIR=$/binaries" >> $GITHUB_ENV |
| 151 | | - |
| 152 | | - - name: Install Bun |
| 143 | + - name: Setup Bun |
| 153 | 144 | uses: oven-sh/setup-bun@v2 |
| 154 | | - |
| 155 | | - - name: Use cached node_modules |
| 156 | | - uses: actions/cache@v4 |
| 157 | 145 | with: |
| 158 | | - path: node_modules |
| 159 | | - key: node-modules-${{ hashFiles('**/bun.lock') }} |
| 160 | | - restore-keys: | |
| 161 | | - node-modules- |
| 162 | | - |
| 163 | | - - name: Install Dependencies |
| 164 | | - run: bun install |
| 146 | + bun-version: latest |
| 165 | 147 | |
| 166 | | - - name: Install build dependencies (Ubuntu) |
| 148 | + - name: Install build dependencies (Linux) |
| 167 | 149 | if: matrix.platform == 'linux' |
| 168 | 150 | run: | |
| 169 | | - |
| 170 | | - echo "🔧 Installing PHP dependencies via apt-get..." |
| 171 | | - echo "🔍 Debug info:" |
| 172 | | - echo " - Platform: linux" |
| 173 | | - echo " - Architecture: $(uname -m)" |
| 174 | | - |
| 175 | 151 | sudo apt-get update |
| 176 | 152 | sudo apt-get install -y \ |
| 177 | | - build-essential \ |
| 178 | | - autoconf \ |
| 179 | | - automake \ |
| 180 | | - libtool \ |
| 181 | | - pkg-config \ |
| 182 | | - bison \ |
| 183 | | - re2c \ |
| 184 | | - libxml2-dev \ |
| 185 | | - libssl-dev \ |
| 186 | | - libcurl4-openssl-dev \ |
| 187 | | - libpng-dev \ |
| 188 | | - libjpeg-dev \ |
| 189 | | - libfreetype6-dev \ |
| 190 | | - libonig-dev \ |
| 191 | | - libzip-dev \ |
| 192 | | - libsqlite3-dev \ |
| 193 | | - libpq-dev \ |
| 194 | | - libreadline-dev \ |
| 195 | | - libbz2-dev \ |
| 196 | | - libgmp-dev \ |
| 197 | | - libldap2-dev \ |
| 198 | | - libsasl2-dev \ |
| 199 | | - libxslt1-dev \ |
| 200 | | - libicu-dev \ |
| 201 | | - libsodium-dev \ |
| 202 | | - zlib1g-dev |
| 153 | + build-essential autoconf automake libtool pkg-config bison re2c \ |
| 154 | + libxml2-dev libssl-dev libcurl4-openssl-dev libpng-dev libjpeg-dev \ |
| 155 | + libfreetype6-dev libonig-dev libzip-dev libpq-dev libreadline-dev \ |
| 156 | + libbz2-dev libgmp-dev libldap2-dev libxslt1-dev libicu-dev \ |
| 157 | + libsodium-dev zlib1g-dev libsqlite3-dev libenchant-2-dev \ |
| 158 | + libtidy-dev libsnmp-dev libgd-dev libwebp-dev libc-client-dev \ |
| 159 | + libkrb5-dev libedit-dev libargon2-dev libffi-dev \ |
| 160 | + libmcrypt-dev libmhash-dev libpcre3-dev libexpat1-dev \ |
| 161 | + libc-ares-dev libnghttp2-dev libpsl-dev libidn2-dev \ |
| 162 | + librtmp-dev libssh2-1-dev libgssapi-krb5-2 libkrb5-dev \ |
| 163 | + gettext libgettext-ocaml-dev |
| 203 | 164 | |
| 204 | 165 | - name: Install build dependencies (macOS) |
| 205 | 166 | if: matrix.platform == 'darwin' |
| 206 | 167 | run: | |
| 207 | | - |
| 208 | | - echo "🔧 Installing PHP dependencies via Homebrew..." |
| 209 | | - echo "🔍 Debug info:" |
| 210 | | - echo " - Platform: darwin" |
| 211 | | - echo " - Architecture: $(uname -m)" |
| 212 | | - |
| 213 | | - |
| 214 | | - brew install --quiet \ |
| 215 | | - autoconf \ |
| 216 | | - automake \ |
| 217 | | - libtool \ |
| 218 | | - pkg-config \ |
| 219 | | - bison \ |
| 220 | | - re2c \ |
| 221 | | - libxml2 \ |
| 222 | | - openssl@3 \ |
| 223 | | - curl \ |
| 224 | | - libpng \ |
| 225 | | - jpeg \ |
| 226 | | - freetype \ |
| 227 | | - oniguruma \ |
| 228 | | - libzip \ |
| 229 | | - postgresql@17 \ |
| 230 | | - libpq \ |
| 231 | | - readline \ |
| 232 | | - bzip2 \ |
| 233 | | - gmp \ |
| 234 | | - openldap \ |
| 235 | | - libxslt \ |
| 236 | | - icu4c \ |
| 237 | | - libsodium \ |
| 238 | | - zlib \ |
| 239 | | - libiconv \ |
| 240 | | - gettext |
| 241 | | - |
| 242 | | - |
| 243 | | - echo "Checking readline installation:" |
| 244 | | - ls -la $(brew --prefix readline)/include/readline/readline.h || echo "readline.h not found in expected location" |
| 245 | | - ls -la $(brew --prefix readline)/lib/libreadline.* || echo "libreadline not found in expected location" |
| 246 | | - |
| 247 | | - |
| 248 | | - echo "Checking PostgreSQL installation:" |
| 249 | | - ls -la $(brew --prefix libpq)/include/libpq-fe.h || echo "libpq-fe.h not found in expected location (libpq)" |
| 250 | | - ls -la $(brew --prefix libpq)/lib/libpq.* || echo "libpq not found in expected location (libpq)" |
| 251 | | - which pg_config || echo "pg_config not found in PATH" |
| 252 | | - |
| 253 | | - |
| 254 | | - echo "Checking bzip2 installation:" |
| 255 | | - ls -la $(brew --prefix bzip2)/include/bzlib.h || echo "bzlib.h not found in expected location" |
| 256 | | - ls -la $(brew --prefix bzip2)/lib/libbz2.* || echo "libbz2 not found in expected location" |
| 257 | | - |
| 258 | | - |
| 259 | | - echo "Checking gettext installation:" |
| 260 | | - ls -la $(brew --prefix gettext)/include/libintl.h || echo "libintl.h not found in expected location" |
| 261 | | - ls -la $(brew --prefix gettext)/lib/libintl.* || echo "libintl not found in expected location" |
| 262 | | - |
| 263 | | - |
| 264 | | - echo "Checking OpenLDAP installation:" |
| 265 | | - ls -la $(brew --prefix openldap)/include/ldap.h || echo "ldap.h not found in expected location" |
| 266 | | - ls -la $(brew --prefix openldap)/lib/libldap.* || echo "libldap not found in expected location" |
| 267 | | - ls -la $(brew --prefix openldap)/lib/liblber.* || echo "liblber not found in expected location" |
| 268 | | - echo "OpenLDAP include directory contents:" |
| 269 | | - ls -la $(brew --prefix openldap)/include/ | head -10 |
| 270 | | - echo "OpenLDAP lib directory contents:" |
| 271 | | - ls -la $(brew --prefix openldap)/lib/ | head -10 |
| 272 | | - |
| 273 | | - |
| 274 | | - echo "Creating symlinks for readline, bzip2, gettext, and openldap:" |
| 275 | | - sudo mkdir -p /usr/local/include/readline /usr/local/lib |
| 276 | | - sudo ln -sf $(brew --prefix readline)/include/readline/readline.h /usr/local/include/readline/readline.h |
| 277 | | - sudo ln -sf $(brew --prefix readline)/include/readline/history.h /usr/local/include/readline/history.h |
| 278 | | - sudo ln -sf $(brew --prefix readline)/lib/libreadline.* /usr/local/lib/ |
| 279 | | - sudo ln -sf $(brew --prefix bzip2)/include/bzlib.h /usr/local/include/bzlib.h |
| 280 | | - sudo ln -sf $(brew --prefix bzip2)/lib/libbz2.* /usr/local/lib/ |
| 281 | | - sudo ln -sf $(brew --prefix gettext)/include/libintl.h /usr/local/include/libintl.h |
| 282 | | - sudo ln -sf $(brew --prefix gettext)/lib/libintl.* /usr/local/lib/ |
| 283 | | - sudo ln -sf $(brew --prefix openldap)/include/ldap.h /usr/local/include/ldap.h |
| 284 | | - sudo ln -sf $(brew --prefix openldap)/lib/libldap.* /usr/local/lib/ |
| 285 | | - sudo ln -sf $(brew --prefix openldap)/lib/liblber.* /usr/local/lib/ |
| 286 | | - |
| 287 | | - - name: Create build configuration |
| 168 | + |
| 169 | + brew install autoconf automake libtool pkg-config bison re2c libxml2 openssl curl libpng jpeg freetype oniguruma libzip postgresql readline bzip2 gmp openldap libxslt icu4c libsodium zlib gettext |
| 170 | + |
| 171 | + echo "/opt/homebrew/bin:/usr/local/bin:$PATH" >> $GITHUB_PATH |
| 172 | + echo "PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" >> $GITHUB_ENV |
| 173 | + |
| 174 | + - name: Install build dependencies (Windows) |
| 175 | + if: matrix.platform == 'win32' |
| 288 | 176 | run: | |
| 289 | | - mkdir -p ${{ env.BUILD_DIR }} ${{ env.OUTPUT_DIR }} |
| 290 | | - |
| 291 | | - |
| 292 | | - PG_PREFIX="" |
| 293 | | - if [[ "$" == "darwin" ]]; then |
| 294 | | - PG_PREFIX="$(brew --prefix libpq)" |
| 295 | | - fi |
| 296 | | - |
| 297 | | - |
| 298 | | - case "$" in |
| 299 | | - "laravel-mysql") |
| 300 | | - |
| 301 | | - if [[ "$" == 8.1* ]]; then |
| 302 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-exif --enable-bcmath --with-pdo-mysql --with-mysqli --with-curl --with-openssl --enable-gd --with-zip --with-readline --with-libxml --with-zlib" |
| 303 | | - else |
| 304 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-intl --enable-exif --enable-bcmath --with-pdo-mysql --with-mysqli --with-curl --with-openssl --enable-gd --with-zip --with-readline --with-libxml --with-zlib" |
| 305 | | - fi |
| 306 | | - ;; |
| 307 | | - "laravel-postgres") |
| 308 | | - |
| 309 | | - if [[ "$" == 8.1* ]]; then |
| 310 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-exif --enable-bcmath --with-pdo-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-curl --with-openssl --enable-gd --with-zip --with-readline --with-libxml --with-zlib" |
| 311 | | - else |
| 312 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-intl --enable-exif --enable-bcmath --with-pdo-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-curl --with-openssl --enable-gd --with-zip --with-readline --with-libxml --with-zlib" |
| 313 | | - fi |
| 314 | | - ;; |
| 315 | | - "laravel-sqlite") |
| 316 | | - |
| 317 | | - if [[ "$" == 8.1* ]]; then |
| 318 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-exif --enable-bcmath --with-pdo-sqlite --with-sqlite3 --with-curl --with-openssl --enable-gd --with-zip --with-readline --with-libxml --with-zlib" |
| 319 | | - else |
| 320 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-intl --enable-exif --enable-bcmath --with-pdo-sqlite --with-sqlite3 --with-curl --with-openssl --enable-gd --with-zip --with-readline --with-libxml --with-zlib" |
| 321 | | - fi |
| 322 | | - ;; |
| 323 | | - "api-only") |
| 324 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-bcmath --with-pdo-mysql --with-mysqli --with-curl --with-openssl --with-zip --with-libxml --with-zlib" |
| 325 | | - ;; |
| 326 | | - "enterprise") |
| 327 | | - |
| 328 | | - if [[ "$" == 8.1* ]]; then |
| 329 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-exif --enable-bcmath --with-pdo-mysql --with-pdo-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-pdo-sqlite --with-mysqli --with-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-sqlite3 --with-curl --with-openssl --enable-gd --enable-soap --enable-sockets --with-zip --with-bz2 --with-readline --with-libxml --with-zlib --enable-pcntl --enable-posix --with-gettext --with-gmp --with-ldap --with-xsl --with-sodium" |
| 330 | | - else |
| 331 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-intl --enable-exif --enable-bcmath --with-pdo-mysql --with-pdo-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-pdo-sqlite --with-mysqli --with-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-sqlite3 --with-curl --with-openssl --enable-gd --enable-soap --enable-sockets --with-zip --with-bz2 --with-readline --with-libxml --with-zlib --enable-pcntl --enable-posix --with-gettext --with-gmp --with-ldap --with-xsl --with-sodium" |
| 332 | | - fi |
| 333 | | - ;; |
| 334 | | - "wordpress") |
| 335 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-exif --with-pdo-mysql --with-mysqli --with-curl --with-openssl --enable-gd --with-zip --with-libxml --with-zlib" |
| 336 | | - ;; |
| 337 | | - "full-stack") |
| 338 | | - |
| 339 | | - |
| 340 | | - if [[ "$" == 8.1* ]]; then |
| 341 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-exif --enable-bcmath --enable-calendar --enable-ftp --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --with-pdo-mysql --with-pdo-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-pdo-sqlite --with-mysqli --with-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-sqlite3 --with-curl --with-openssl --enable-gd --enable-soap --enable-sockets --with-zip --with-bz2 --with-readline --with-libxml --with-zlib --enable-pcntl --enable-posix --with-gettext --with-gmp --with-ldap --with-xsl --with-sodium --with-iconv --enable-fileinfo --enable-json --enable-phar --enable-filter --enable-hash --enable-session --enable-tokenizer --enable-ctype --enable-dom --enable-simplexml --enable-xml --enable-xmlreader --enable-xmlwriter --enable-shmop" |
| 342 | | - else |
| 343 | | - EXTENSIONS="--enable-cli --enable-fpm --enable-mbstring --enable-opcache --enable-intl --enable-exif --enable-bcmath --enable-calendar --enable-ftp --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --with-pdo-mysql --with-pdo-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-pdo-sqlite --with-mysqli --with-pgsql${PG_PREFIX:+=$PG_PREFIX} --with-sqlite3 --with-curl --with-openssl --enable-gd --enable-soap --enable-sockets --with-zip --with-bz2 --with-readline --with-libxml --with-zlib --enable-pcntl --enable-posix --with-gettext --with-gmp --with-ldap --with-xsl --with-sodium --with-iconv --enable-fileinfo --enable-json --enable-phar --enable-filter --enable-hash --enable-session --enable-tokenizer --enable-ctype --enable-dom --enable-simplexml --enable-xml --enable-xmlreader --enable-xmlwriter --enable-shmop" |
| 344 | | - fi |
| 345 | | - ;; |
| 346 | | - esac |
| 347 | | - |
| 348 | | - echo "CONFIGURE_EXTENSIONS=$EXTENSIONS" >> $GITHUB_ENV |
| 177 | + |
| 178 | + choco install visualstudio2022buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --includeOptional --passive" |
| 179 | + choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' |
| 180 | + choco install git |
| 181 | + |
| 182 | + echo "Windows build dependencies installed for PHP compilation" |
| 349 | 183 | |
| 350 | | - - name: Set macOS specific paths |
| 351 | | - if: matrix.platform == 'darwin' |
| 184 | + - name: Build PHP |
| 185 | + env: |
| 186 | + PHP_VERSION: ${{ matrix.php_version }} |
| 187 | + PHP_CONFIG: ${{ matrix.config }} |
| 188 | + TARGET_PLATFORM: ${{ matrix.platform }} |
| 189 | + TARGET_ARCH: ${{ matrix.arch }} |
| 190 | + BUILD_DIR: ${{ github.workspace }}/build |
| 191 | + OUTPUT_DIR: ${{ github.workspace }}/binaries |
| 192 | + run: bun run scripts/build-php.ts |
| 193 | + |
| 194 | + - name: Create tarball (Unix) |
| 195 | + if: matrix.platform != 'win32' |
| 352 | 196 | run: | |
| 353 | | - |
| 354 | | - |
| 355 | | - PKG_CONFIG_PATHS=( |
| 356 | | - "$(brew --prefix)/lib/pkgconfig" |
| 357 | | - "$(brew --prefix openssl@3)/lib/pkgconfig" |
| 358 | | - "$(brew --prefix libxml2)/lib/pkgconfig" |
| 359 | | - "$(brew --prefix icu4c)/lib/pkgconfig" |
| 360 | | - "$(brew --prefix zlib)/lib/pkgconfig" |
| 361 | | - "$(brew --prefix postgresql@17)/lib/pkgconfig" |
| 362 | | - "$(brew --prefix libpq)/lib/pkgconfig" |
| 363 | | - "$(brew --prefix bzip2)/lib/pkgconfig" |
| 364 | | - "$(brew --prefix gettext)/lib/pkgconfig" |
| 365 | | - "$(brew --prefix openldap)/lib/pkgconfig" |
| 366 | | - ) |
| 367 | | - PKG_CONFIG_PATH_JOINED=$(IFS=:; echo "${PKG_CONFIG_PATHS[*]}") |
| 368 | | - echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH_JOINED" >> $GITHUB_ENV |
| 369 | | - export PKG_CONFIG_PATH="$PKG_CONFIG_PATH_JOINED" |
| 370 | | - |
| 371 | | - PATH_PATHS=( |
| 372 | | - "$(brew --prefix bison)/bin" |
| 373 | | - "$(brew --prefix)/bin" |
| 374 | | - "$(brew --prefix libpq)/bin" |
| 375 | | - "$(brew --prefix postgresql@17)/bin" |
| 376 | | - "$(brew --prefix gettext)/bin" |
| 377 | | - ) |
| 378 | | - PATH_JOINED=$(IFS=:; echo "${PATH_PATHS[*]}") |
| 379 | | - echo "PATH=$PATH_JOINED:$PATH" >> $GITHUB_ENV |
| 380 | | - export PATH="$PATH_JOINED:$PATH" |
| 381 | | - |
| 382 | | - LDFLAGS_PATHS=( |
| 383 | | - "-L$(brew --prefix)/lib" |
| 384 | | - "-L$(brew --prefix openssl@3)/lib" |
| 385 | | - "-L$(brew --prefix zlib)/lib" |
| 386 | | - "-L$(brew --prefix libiconv)/lib" |
| 387 | | - "-L$(brew --prefix libpq)/lib" |
| 388 | | - "-L$(brew --prefix bzip2)/lib" |
| 389 | | - "-L$(brew --prefix gettext)/lib" |
| 390 | | - "-L$(brew --prefix openldap)/lib" |
| 391 | | - ) |
| 392 | | - LDFLAGS_JOINED=$(IFS=' '; echo "${LDFLAGS_PATHS[*]}") |
| 393 | | - echo "LDFLAGS=$LDFLAGS_JOINED" >> $GITHUB_ENV |
| 394 | | - export LDFLAGS="$LDFLAGS_JOINED" |
| 395 | | - |
| 396 | | - CPPFLAGS_PATHS=( |
| 397 | | - "-I$(brew --prefix)/include" |
| 398 | | - "-I$(brew --prefix openssl@3)/include" |
| 399 | | - "-I$(brew --prefix zlib)/include" |
| 400 | | - "-I$(brew --prefix libiconv)/include" |
| 401 | | - "-I$(brew --prefix libpq)/include" |
| 402 | | - "-I$(brew --prefix bzip2)/include" |
| 403 | | - "-I$(brew --prefix gettext)/include" |
| 404 | | - "-I$(brew --prefix openldap)/include" |
| 405 | | - ) |
| 406 | | - CPPFLAGS_JOINED=$(IFS=' '; echo "${CPPFLAGS_PATHS[*]}") |
| 407 | | - echo "CPPFLAGS=$CPPFLAGS_JOINED" >> $GITHUB_ENV |
| 408 | | - export CPPFLAGS="$CPPFLAGS_JOINED" |
| 409 | | - echo "CXXFLAGS=-std=c++17 -stdlib=libc++" >> $GITHUB_ENV |
| 410 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 411 | | - |
| 412 | | - |
| 413 | | - echo "READLINE_CFLAGS=-I$(brew --prefix readline)/include" >> $GITHUB_ENV |
| 414 | | - echo "READLINE_LIBS=-L$(brew --prefix readline)/lib -lreadline" >> $GITHUB_ENV |
| 415 | | - export READLINE_CFLAGS="-I$(brew --prefix readline)/include" |
| 416 | | - export READLINE_LIBS="-L$(brew --prefix readline)/lib -lreadline" |
| 417 | | - |
| 418 | | - |
| 419 | | - brew link libpq --force || true |
| 420 | | - |
| 421 | | - |
| 422 | | - echo "Debug: Checking PostgreSQL availability:" |
| 423 | | - echo " PATH: $PATH" |
| 424 | | - echo " Checking pg_config:" |
| 425 | | - which pg_config || echo " pg_config not found in PATH" |
| 426 | | - pg_config --version 2>/dev/null || echo " pg_config version check failed" |
| 427 | | - echo " Checking libpq-fe.h:" |
| 428 | | - ls -la $(brew --prefix libpq)/include/libpq-fe.h 2>/dev/null || echo " libpq-fe.h not found" |
| 429 | | - echo " Checking libpq installation:" |
| 430 | | - ls -la $(brew --prefix libpq)/include/ 2>/dev/null | head -5 || echo " libpq include directory not found" |
| 431 | | - ls -la $(brew --prefix libpq)/lib/ 2>/dev/null | head -5 || echo " libpq lib directory not found" |
| 432 | | - |
| 433 | | - if which pg_config >/dev/null 2>&1 && [[ -f "$(brew --prefix libpq)/include/libpq-fe.h" ]]; then |
| 434 | | - echo "PostgreSQL found and working" |
| 435 | | - echo "POSTGRESQL_AVAILABLE=true" >> $GITHUB_ENV |
| 197 | + cd binaries |
| 198 | + BINARY_NAME="php-$-$-$-$" |
| 199 | + if [ -d "$BINARY_NAME" ]; then |
| 200 | + |
| 201 | + echo '{"php_version":"$","platform":"$","arch":"$","config":"$","built_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > "$BINARY_NAME/metadata.json" |
| 202 | + |
| 203 | + |
| 204 | + tar -czf "$BINARY_NAME.tar.gz" "$BINARY_NAME" |
| 205 | + echo "✅ Created tarball: $BINARY_NAME.tar.gz" |
| 206 | + ls -lh "$BINARY_NAME.tar.gz" |
| 436 | 207 | else |
| 437 | | - echo "PostgreSQL not found or not working, will disable PostgreSQL support" |
| 438 | | - echo "POSTGRESQL_AVAILABLE=false" >> $GITHUB_ENV |
| 208 | + echo "❌ Binary directory not found: $BINARY_NAME" |
| 209 | + exit 1 |
| 439 | 210 | fi |
| 440 | 211 | |
| 441 | | - - name: Download and extract PHP source |
| 442 | | - run: | |
| 443 | | - cd ${{ env.BUILD_DIR }} |
| 444 | | - |
| 445 | | - |
| 446 | | - export PATH="/usr/bin:/usr/local/bin:/bin:$PATH" |
| 447 | | - |
| 448 | | - curl -fsSL "https://www.php.net/distributions/php-$.tar.gz" -o php.tar.gz |
| 449 | | - tar -xzf php.tar.gz |
| 450 | | - cd php-${{ matrix.php_version }} |
| 451 | | - echo "PHP_SOURCE_DIR=$/php-$" >> $GITHUB_ENV |
| 452 | | - |
| 453 | | - - name: Configure PHP build |
| 212 | + - name: Create tarball (Windows) |
| 213 | + if: matrix.platform == 'win32' |
| 454 | 214 | run: | |
| 455 | | - cd ${{ env.PHP_SOURCE_DIR }} |
| 456 | | - |
| 457 | | - |
| 458 | | - INSTALL_PREFIX="$/$" |
| 459 | | - mkdir -p "$INSTALL_PREFIX" |
| 460 | | - |
| 461 | | - |
| 462 | | - if [[ "$" == "darwin" ]]; then |
| 463 | | - |
| 464 | | - |
| 465 | | - export CPPFLAGS="$CPPFLAGS -I$(brew --prefix readline)/include" |
| 466 | | - export LDFLAGS="$LDFLAGS -L$(brew --prefix readline)/lib" |
| 467 | | - export LIBS="$LIBS -lreadline" |
| 468 | | - |
| 469 | | - |
| 470 | | - export PGSQL_CFLAGS="-I$(brew --prefix libpq)/include" |
| 471 | | - export PGSQL_LIBS="-L$(brew --prefix libpq)/lib -lpq" |
| 472 | | - export PATH="$(brew --prefix libpq)/bin:$(brew --prefix postgresql@17)/bin:$PATH" |
| 473 | | - |
| 474 | | - |
| 475 | | - export BZIP2_CFLAGS="-I$(brew --prefix bzip2)/include" |
| 476 | | - export BZIP2_LIBS="-L$(brew --prefix bzip2)/lib -lbz2" |
| 477 | | - |
| 478 | | - |
| 479 | | - export GETTEXT_CFLAGS="-I$(brew --prefix gettext)/include" |
| 480 | | - export GETTEXT_LIBS="-L$(brew --prefix gettext)/lib -lintl" |
| 481 | | - |
| 482 | | - |
| 483 | | - echo "Debug: Checking for lber library:" |
| 484 | | - ls -la $(brew --prefix openldap)/lib/liblber.* 2>/dev/null || echo " lber library not found" |
| 485 | | - echo "Debug: Checking for ldap library:" |
| 486 | | - ls -la $(brew --prefix openldap)/lib/libldap.* 2>/dev/null || echo " ldap library not found" |
| 487 | | - |
| 488 | | - if [[ -f "$(brew --prefix openldap)/lib/liblber.dylib" ]] && [[ -f "$(brew --prefix openldap)/lib/libldap.dylib" ]]; then |
| 489 | | - echo "Both LDAP libraries found, enabling LDAP support" |
| 490 | | - LDAP_AVAILABLE=true |
| 491 | | - else |
| 492 | | - echo "LDAP libraries not found, disabling LDAP support" |
| 493 | | - LDAP_AVAILABLE=false |
| 494 | | - |
| 495 | | - export CONFIGURE_EXTENSIONS=$(echo "$CONFIGURE_EXTENSIONS" | sed 's/--with-ldap//g' | sed 's/ */ /g') |
| 496 | | - echo "Updated CONFIGURE_EXTENSIONS: $CONFIGURE_EXTENSIONS" |
| 497 | | - fi |
| 498 | | - |
| 499 | | - |
| 500 | | - if [[ "$LDAP_AVAILABLE" == "true" ]]; then |
| 501 | | - export LDAP_CFLAGS="-I$(brew --prefix openldap)/include" |
| 502 | | - export LDAP_LIBS="-L$(brew --prefix openldap)/lib -lldap -llber" |
| 503 | | - echo "Debug: LDAP_CFLAGS=$LDAP_CFLAGS" |
| 504 | | - echo "Debug: LDAP_LIBS=$LDAP_LIBS" |
| 505 | | - else |
| 506 | | - |
| 507 | | - unset LDAP_CFLAGS |
| 508 | | - unset LDAP_LIBS |
| 509 | | - echo "Debug: LDAP environment variables cleared" |
| 510 | | - fi |
| 511 | | - |
| 512 | | - |
| 513 | | - |
| 514 | | - PHP_MAJOR_VERSION=$(echo "$" | cut -d. -f1) |
| 515 | | - PHP_MINOR_VERSION=$(echo "$" | cut -d. -f2) |
| 516 | | - |
| 517 | | - if [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -ge 2 ]]; then |
| 518 | | - |
| 519 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 520 | | - echo "Using C++17 for PHP $" |
| 521 | | - elif [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -eq 1 ]]; then |
| 522 | | - |
| 523 | | - export CXXFLAGS="-std=c++14 -stdlib=libc++" |
| 524 | | - echo "Using C++14 for PHP $ (configure step only)" |
| 525 | | - else |
| 526 | | - |
| 527 | | - export CXXFLAGS="-std=c++14 -stdlib=libc++" |
| 528 | | - echo "Using C++14 for PHP $" |
| 529 | | - fi |
| 530 | | - |
| 531 | | - |
| 532 | | - export CFLAGS="" |
| 533 | | - export CPPFLAGS="$CPPFLAGS" |
| 534 | | - echo "Set C++ flags for configure step" |
| 535 | | - echo "CXXFLAGS: $CXXFLAGS" |
| 536 | | - echo "CFLAGS: $CFLAGS" |
| 537 | | - echo "CPPFLAGS: $CPPFLAGS" |
| 538 | | - |
| 539 | | - |
| 540 | | - if command -v clang++ >/dev/null 2>&1; then |
| 541 | | - export CC=clang |
| 542 | | - export CXX=clang++ |
| 543 | | - echo "Using clang/clang++ compilers" |
| 544 | | - echo "CC: $CC" |
| 545 | | - echo "CXX: $CXX" |
| 546 | | - fi |
| 547 | | - |
| 548 | | - |
| 549 | | - if [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -ge 4 ]]; then |
| 550 | | - echo "Testing C++17 support before configure:" |
| 551 | | - echo '#include <type_traits>' > test_cpp.cpp |
| 552 | | - echo 'int main() { std::enable_if_t<true, int> x = 0; return x; }' >> test_cpp.cpp |
| 553 | | - if clang++ -std=c++17 -stdlib=libc++ test_cpp.cpp -o test_cpp 2>/dev/null; then |
| 554 | | - echo "C++17 support confirmed before configure" |
| 555 | | - rm -f test_cpp.cpp test_cpp |
| 556 | | - else |
| 557 | | - echo "C++17 support test failed before configure" |
| 558 | | - rm -f test_cpp.cpp test_cpp |
| 559 | | - fi |
| 560 | | - elif [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -eq 1 ]]; then |
| 561 | | - echo "Testing C++14 support before configure (PHP 8.1 configure step):" |
| 562 | | - echo '#include <type_traits>' > test_cpp.cpp |
| 563 | | - echo 'int main() { typename std::enable_if<true, int>::type x = 0; return x; }' >> test_cpp.cpp |
| 564 | | - if clang++ -std=c++14 -stdlib=libc++ test_cpp.cpp -o test_cpp 2>/dev/null; then |
| 565 | | - echo "C++14 support confirmed before configure" |
| 566 | | - rm -f test_cpp.cpp test_cpp |
| 567 | | - else |
| 568 | | - echo "C++14 support test failed before configure" |
| 569 | | - rm -f test_cpp.cpp test_cpp |
| 570 | | - fi |
| 571 | | - else |
| 572 | | - echo "Testing C++14 support before configure:" |
| 573 | | - echo '#include <type_traits>' > test_cpp.cpp |
| 574 | | - echo 'int main() { typename std::enable_if<true, int>::type x = 0; return x; }' >> test_cpp.cpp |
| 575 | | - if clang++ -std=c++14 -stdlib=libc++ test_cpp.cpp -o test_cpp 2>/dev/null; then |
| 576 | | - echo "C++14 support confirmed before configure" |
| 577 | | - rm -f test_cpp.cpp test_cpp |
| 578 | | - else |
| 579 | | - echo "C++14 support test failed before configure" |
| 580 | | - rm -f test_cpp.cpp test_cpp |
| 581 | | - fi |
| 582 | | - fi |
| 583 | | - |
| 584 | | - |
| 585 | | - READLINE_PATH=$(brew --prefix readline) |
| 586 | | - if [[ -f "$READLINE_PATH/include/readline/readline.h" ]]; then |
| 587 | | - echo "Found readline.h at $READLINE_PATH/include/readline/readline.h" |
| 588 | | - EXTRA_CONFIG="--with-iconv=$(brew --prefix libiconv) --with-readline=$READLINE_PATH" |
| 589 | | - else |
| 590 | | - echo "readline.h not found, disabling readline support" |
| 591 | | - EXTRA_CONFIG="--with-iconv=$(brew --prefix libiconv) --disable-readline" |
| 592 | | - fi |
| 593 | | - |
| 594 | | - |
| 595 | | - echo "Debug: POSTGRESQL_AVAILABLE=$POSTGRESQL_AVAILABLE" |
| 596 | | - if [[ "$POSTGRESQL_AVAILABLE" == "true" ]]; then |
| 597 | | - echo "PostgreSQL found and working" |
| 598 | | - else |
| 599 | | - if [[ "$" == "laravel-postgres" ]]; then |
| 600 | | - echo "❌ PostgreSQL not available; cannot build laravel-postgres binary on this runner" |
| 601 | | - exit 1 |
| 602 | | - fi |
| 603 | | - echo "PostgreSQL not found or not working, will disable PostgreSQL support for non-postgres configs" |
| 604 | | - |
| 605 | | - export CONFIGURE_EXTENSIONS=$(echo "$CONFIGURE_EXTENSIONS" | sed 's/--with-pdo-pgsql//g' | sed 's/--with-pgsql//g' | sed 's/ */ /g') |
| 606 | | - echo "Updated CONFIGURE_EXTENSIONS: $CONFIGURE_EXTENSIONS" |
| 607 | | - |
| 608 | | - EXTRA_CONFIG="$EXTRA_CONFIG --disable-pgsql --disable-pdo-pgsql" |
| 609 | | - fi |
| 610 | | - else |
| 611 | | - |
| 612 | | - |
| 613 | | - echo "Using system libraries installed via apt-get" |
| 614 | | - EXTRA_CONFIG="" |
| 615 | | - fi |
| 616 | | - |
| 617 | | - echo "Configuring PHP with:" |
| 618 | | - echo " Extensions: $" |
| 619 | | - echo " Prefix: $INSTALL_PREFIX" |
| 620 | | - echo " Extra config: $EXTRA_CONFIG" |
| 621 | | - |
| 622 | | - |
| 623 | | - if [[ "$" == "darwin" ]]; then |
| 624 | | - echo "Debug: Checking readline installation on macOS:" |
| 625 | | - echo " READLINE_CFLAGS: $READLINE_CFLAGS" |
| 626 | | - echo " READLINE_LIBS: $READLINE_LIBS" |
| 627 | | - echo " CPPFLAGS: $CPPFLAGS" |
| 628 | | - echo " LDFLAGS: $LDFLAGS" |
| 629 | | - echo " Checking if readline.h exists:" |
| 630 | | - find $(brew --prefix) -name "readline.h" 2>/dev/null || echo " No readline.h found" |
| 631 | | - |
| 632 | | - echo "Debug: Checking PostgreSQL installation on macOS:" |
| 633 | | - echo " PGSQL_CFLAGS: $PGSQL_CFLAGS" |
| 634 | | - echo " PGSQL_LIBS: $PGSQL_LIBS" |
| 635 | | - echo " PATH: $PATH" |
| 636 | | - echo " Checking if pg_config is available:" |
| 637 | | - which pg_config || echo " pg_config not found in PATH" |
| 638 | | - pg_config --version 2>/dev/null || echo " pg_config version check failed" |
| 639 | | - echo " Checking if libpq-fe.h exists:" |
| 640 | | - find $(brew --prefix) -name "libpq-fe.h" 2>/dev/null || echo " No libpq-fe.h found" |
| 641 | | - fi |
| 642 | | - |
| 643 | | - |
| 644 | | - if pkg-config --exists libcurl; then |
| 645 | | - echo "libcurl found via pkg-config" |
| 646 | | - CURL_CONFIG="" |
| 647 | | - else |
| 648 | | - echo "libcurl not found via pkg-config, using system curl" |
| 649 | | - CURL_CONFIG="" |
| 650 | | - fi |
| 651 | | - |
| 652 | | - |
| 653 | | - FINAL_EXTENSIONS="$" |
| 654 | | - |
| 655 | | - |
| 656 | | - if [[ "$" == "darwin" ]] && [[ "$POSTGRESQL_AVAILABLE" != "true" ]]; then |
| 657 | | - echo "Removing PostgreSQL extensions from configure command" |
| 658 | | - FINAL_EXTENSIONS=$(echo "$FINAL_EXTENSIONS" | sed 's/--with-pdo-pgsql//g' | sed 's/--with-pgsql//g' | sed 's/ */ /g') |
| 659 | | - echo "Final extensions: $FINAL_EXTENSIONS" |
| 660 | | - fi |
| 661 | | - |
| 662 | | - |
| 663 | | - PHP_MAJOR_VERSION=$(echo "$" | cut -d. -f1) |
| 664 | | - PHP_MINOR_VERSION=$(echo "$" | cut -d. -f2) |
| 665 | | - |
| 666 | | - echo "Configure environment:" |
| 667 | | - echo " CXXFLAGS: $CXXFLAGS" |
| 668 | | - echo " CFLAGS: $CFLAGS" |
| 669 | | - echo " CPPFLAGS: $CPPFLAGS" |
| 670 | | - echo " PHP Version: $ (Major: $PHP_MAJOR_VERSION, Minor: $PHP_MINOR_VERSION)" |
| 671 | | - |
| 672 | | - |
| 673 | | - if [[ "$" == "darwin" ]]; then |
| 674 | | - echo "Testing C++17 support before configure:" |
| 675 | | - echo '#include <type_traits>' > test_cpp17.cpp |
| 676 | | - echo 'int main() { std::enable_if_t<true, int> x = 0; return x; }' >> test_cpp17.cpp |
| 677 | | - if clang++ -std=c++17 -stdlib=libc++ test_cpp17.cpp -o test_cpp17 2>/dev/null; then |
| 678 | | - echo "C++17 support confirmed before configure" |
| 679 | | - rm -f test_cpp17.cpp test_cpp17 |
| 680 | | - else |
| 681 | | - echo "C++17 support test failed before configure" |
| 682 | | - rm -f test_cpp17.cpp test_cpp17 |
| 683 | | - fi |
| 684 | | - fi |
| 685 | | - |
| 686 | | - if [[ "$" == "darwin" ]]; then |
| 687 | | - |
| 688 | | - if [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -ge 2 ]]; then |
| 689 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 690 | | - echo "Set C++17 for configure: $CXXFLAGS" |
| 691 | | - elif [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -eq 1 ]]; then |
| 692 | | - |
| 693 | | - export CXXFLAGS="-std=c++14 -stdlib=libc++" |
| 694 | | - echo "Set C++14 for PHP 8.1 configure: $CXXFLAGS" |
| 695 | | - else |
| 696 | | - export CXXFLAGS="-std=c++14 -stdlib=libc++" |
| 697 | | - echo "Set C++14 for configure: $CXXFLAGS" |
| 698 | | - fi |
| 699 | | - export CFLAGS="" |
| 700 | | - export CPPFLAGS="$CPPFLAGS" |
| 701 | | - |
| 702 | | - |
| 703 | | - export CC=clang |
| 704 | | - export CXX=clang++ |
| 705 | | - echo "Set CC=$CC, CXX=$CXX" |
| 706 | | - fi |
| 707 | | - |
| 708 | | - |
| 709 | | - if [[ "$" == "darwin" ]]; then |
| 710 | | - CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" CC="$CC" CXX="$CXX" ./configure \ |
| 711 | | - --prefix="$INSTALL_PREFIX" \ |
| 712 | | - --with-config-file-path="$INSTALL_PREFIX/lib" \ |
| 713 | | - --with-config-file-scan-dir="$INSTALL_PREFIX/lib/conf.d" \ |
| 714 | | - --disable-debug \ |
| 715 | | - --enable-shared \ |
| 716 | | - --with-pic \ |
| 717 | | - $FINAL_EXTENSIONS \ |
| 718 | | - $EXTRA_CONFIG \ |
| 719 | | - $CURL_CONFIG |
| 720 | | - else |
| 721 | | - ./configure \ |
| 722 | | - --prefix="$INSTALL_PREFIX" \ |
| 723 | | - --with-config-file-path="$INSTALL_PREFIX/lib" \ |
| 724 | | - --with-config-file-scan-dir="$INSTALL_PREFIX/lib/conf.d" \ |
| 725 | | - --disable-debug \ |
| 726 | | - --enable-shared \ |
| 727 | | - --with-pic \ |
| 728 | | - $FINAL_EXTENSIONS \ |
| 729 | | - $EXTRA_CONFIG \ |
| 730 | | - $CURL_CONFIG |
| 731 | | - fi |
| 732 | | - |
| 733 | | - |
| 734 | | - if [[ "$" == "darwin" ]]; then |
| 735 | | - echo "Checking Makefile for C++ flags:" |
| 736 | | - grep -E "CXXFLAGS|CXX|std=" Makefile | head -10 || echo "No C++ flags found in Makefile" |
| 737 | | - fi |
| 215 | + cd binaries |
| 216 | + $BINARY_NAME = "php-$-$-$-$" |
| 217 | + if (Test-Path -Path $BINARY_NAME -PathType Container) { |
| 218 | + |
| 219 | + $metadata = @{ |
| 220 | + php_version = "$" |
| 221 | + platform = "$" |
| 222 | + arch = "$" |
| 223 | + config = "$" |
| 224 | + built_at = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ") |
| 225 | + } | ConvertTo-Json |
| 226 | + $metadata | Out-File -FilePath "$BINARY_NAME\metadata.json" -Encoding UTF8 |
| 227 | + |
| 228 | + |
| 229 | + Compress-Archive -Path $BINARY_NAME -DestinationPath "$BINARY_NAME.zip" -Force |
| 230 | + Write-Host "✅ Created archive: $BINARY_NAME.zip" |
| 231 | + Get-ChildItem "$BINARY_NAME.zip" | Format-List Name, Length |
| 232 | + } else { |
| 233 | + Write-Host "❌ Binary directory not found: $BINARY_NAME" |
| 234 | + exit 1 |
| 235 | + } |
| 738 | 236 | |
| 739 | | - - name: Build PHP |
| 237 | + - name: Test PHP Binary (Unix) |
| 238 | + if: matrix.platform != 'win32' |
| 740 | 239 | run: | |
| 741 | | - cd ${{ env.PHP_SOURCE_DIR }} |
| 742 | | - |
| 743 | | - |
| 744 | | - if [[ "$" == "darwin" ]]; then |
| 745 | | - JOBS=$(sysctl -n hw.ncpu) |
| 746 | | - |
| 747 | | - PHP_MAJOR_VERSION=$(echo "$" | cut -d. -f1) |
| 748 | | - PHP_MINOR_VERSION=$(echo "$" | cut -d. -f2) |
| 749 | | - |
| 750 | | - if [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -ge 2 ]]; then |
| 751 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 752 | | - echo "Set C++17 flags for macOS build" |
| 753 | | - elif [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -eq 1 ]]; then |
| 754 | | - |
| 755 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 756 | | - echo "Set C++17 flags for PHP 8.1 (ICU4C compatibility)" |
| 757 | | - else |
| 758 | | - export CXXFLAGS="-std=c++14 -stdlib=libc++" |
| 759 | | - echo "Set C++14 flags for macOS build" |
| 760 | | - fi |
| 761 | | - |
| 762 | | - |
| 763 | | - export CFLAGS="" |
| 764 | | - export CPPFLAGS="$CPPFLAGS" |
| 765 | | - else |
| 766 | | - JOBS=$(nproc) |
| 767 | | - fi |
| 768 | | - |
| 769 | | - echo "Building PHP with $JOBS parallel jobs" |
| 770 | | - echo "CXXFLAGS: $CXXFLAGS" |
| 771 | | - echo "CFLAGS: $CFLAGS" |
| 772 | | - echo "CPPFLAGS: $CPPFLAGS" |
| 773 | | - |
| 774 | | - |
| 775 | | - echo "Compiler being used:" |
| 776 | | - which gcc || which clang || echo "No compiler found" |
| 777 | | - echo "C++ compiler:" |
| 778 | | - which g++ || which clang++ || echo "No C++ compiler found" |
| 779 | | - |
| 780 | | - |
| 781 | | - echo "Compiler info:" |
| 782 | | - which gcc || which clang || echo "No compiler found" |
| 783 | | - gcc --version 2>/dev/null || clang --version 2>/dev/null || echo "Could not get compiler version" |
| 784 | | - |
| 785 | | - |
| 786 | | - echo "Checking available C++ standards:" |
| 787 | | - if command -v clang++ >/dev/null 2>&1; then |
| 788 | | - echo "Available C++ standards for clang++:" |
| 789 | | - clang++ --help | grep -E "std=" || echo "Could not determine available standards" |
| 790 | | - fi |
| 791 | | - |
| 792 | | - |
| 793 | | - PHP_MAJOR_VERSION=$(echo "$" | cut -d. -f1) |
| 794 | | - PHP_MINOR_VERSION=$(echo "$" | cut -d. -f2) |
| 795 | | - |
| 796 | | - if [[ "$" == "darwin" ]]; then |
| 797 | | - if [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -ge 2 ]]; then |
| 798 | | - echo "Testing C++17 support:" |
| 799 | | - echo '#include <type_traits>' > test_cpp.cpp |
| 800 | | - echo 'int main() { std::enable_if_t<true, int> x = 0; return x; }' >> test_cpp.cpp |
| 801 | | - if clang++ -std=c++17 -stdlib=libc++ test_cpp.cpp -o test_cpp 2>/dev/null; then |
| 802 | | - echo "C++17 support confirmed" |
| 803 | | - rm -f test_cpp.cpp test_cpp |
| 804 | | - else |
| 805 | | - echo "C++17 support test failed" |
| 806 | | - rm -f test_cpp.cpp test_cpp |
| 807 | | - fi |
| 808 | | - elif [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -eq 1 ]]; then |
| 809 | | - echo "Testing C++17 support for PHP 8.1 (ICU4C compatibility):" |
| 810 | | - echo '#include <type_traits>' > test_cpp.cpp |
| 811 | | - echo 'int main() { std::enable_if_t<true, int> x = 0; return x; }' >> test_cpp.cpp |
| 812 | | - if clang++ -std=c++17 -stdlib=libc++ test_cpp.cpp -o test_cpp 2>/dev/null; then |
| 813 | | - echo "C++17 support confirmed for PHP 8.1" |
| 814 | | - rm -f test_cpp.cpp test_cpp |
| 240 | + BINARY_NAME="php-$-$-$-$" |
| 241 | + if [ -f "binaries/$BINARY_NAME/bin/php" ]; then |
| 242 | + echo "✅ PHP binary created successfully" |
| 243 | + binaries/$BINARY_NAME/bin/php --version |
| 244 | + echo "📋 All available extensions:" |
| 245 | + binaries/$BINARY_NAME/bin/php -m |
| 246 | + |
| 247 | + |
| 248 | + REQUIRED_EXTENSIONS=( |
| 249 | + "Core" "date" "hash" "json" "pcre" "Reflection" "SPL" "standard" |
| 250 | + "mbstring" "iconv" "filter" "ctype" "tokenizer" "session" "fileinfo" |
| 251 | + "phar" "dom" "xml" "xmlreader" "xmlwriter" "simplexml" |
| 252 | + "curl" "openssl" "zip" "zlib" "calendar" "ftp" "pcntl" "posix" |
| 253 | + "shmop" "sockets" "exif" "bcmath" "bz2" "gettext" "readline" |
| 254 | + ) |
| 255 | + |
| 256 | + |
| 257 | + ZEND_EXTENSIONS=("opcache") |
| 258 | + |
| 259 | + |
| 260 | + echo "🧪 Testing essential extensions..." |
| 261 | + MISSING_EXTENSIONS=() |
| 262 | + for ext in "${REQUIRED_EXTENSIONS[@]}"; do |
| 263 | + EXT_LOADED=$(binaries/$BINARY_NAME/bin/php -r "echo extension_loaded('$ext') ? '1' : '0';") |
| 264 | + if [ "$EXT_LOADED" = "1" ]; then |
| 265 | + echo "✅ $ext: LOADED" |
| 815 | 266 | else |
| 816 | | - echo "C++17 support test failed for PHP 8.1" |
| 817 | | - rm -f test_cpp.cpp test_cpp |
| 267 | + echo "❌ $ext: MISSING" |
| 268 | + MISSING_EXTENSIONS+=("$ext") |
| 818 | 269 | fi |
| 819 | | - else |
| 820 | | - echo "Testing C++14 support:" |
| 821 | | - echo '#include <type_traits>' > test_cpp.cpp |
| 822 | | - echo 'int main() { typename std::enable_if<true, int>::type x = 0; return x; }' >> test_cpp.cpp |
| 823 | | - if clang++ -std=c++14 -stdlib=libc++ test_cpp.cpp -o test_cpp 2>/dev/null; then |
| 824 | | - echo "C++14 support confirmed" |
| 825 | | - rm -f test_cpp.cpp test_cpp |
| 270 | + done |
| 271 | + |
| 272 | + |
| 273 | + for ext in "${ZEND_EXTENSIONS[@]}"; do |
| 274 | + EXT_LOADED=$(binaries/$BINARY_NAME/bin/php -r "echo function_exists('opcache_get_status') ? '1' : '0';") |
| 275 | + if [ "$EXT_LOADED" = "1" ]; then |
| 276 | + echo "✅ $ext: LOADED" |
| 826 | 277 | else |
| 827 | | - echo "C++14 support test failed" |
| 828 | | - rm -f test_cpp.cpp test_cpp |
| 278 | + echo "❌ $ext: MISSING" |
| 279 | + MISSING_EXTENSIONS+=("$ext") |
| 829 | 280 | fi |
| 281 | + done |
| 282 | + |
| 283 | + |
| 284 | + if [ ${ |
| 285 | + echo "❌ Critical extensions missing: ${MISSING_EXTENSIONS[*]}" |
| 286 | + echo "This build is incomplete and will cause issues with Composer and Laravel." |
| 287 | + exit 1 |
| 830 | 288 | fi |
| 831 | | - fi |
| 832 | | - |
| 833 | | - |
| 834 | | - if [[ "$" == "darwin" ]]; then |
| 835 | | - PHP_MAJOR_VERSION=$(echo "$" | cut -d. -f1) |
| 836 | | - PHP_MINOR_VERSION=$(echo "$" | cut -d. -f2) |
| 837 | | - |
| 838 | | - if [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -ge 2 ]]; then |
| 839 | | - echo "Making with explicit C++17 flags:" |
| 840 | | - echo " CXXFLAGS: -std=c++17 -stdlib=libc++" |
| 841 | | - echo " CFLAGS: (empty)" |
| 842 | | - echo " CPPFLAGS: $CPPFLAGS" |
| 843 | | - make -j$JOBS CXXFLAGS="-std=c++17 -stdlib=libc++" CFLAGS="" CPPFLAGS="$CPPFLAGS" |
| 844 | | - elif [[ "$PHP_MAJOR_VERSION" -eq 8 && "$PHP_MINOR_VERSION" -eq 1 ]]; then |
| 845 | | - echo "Making with explicit C++17 flags for PHP 8.1 (ICU4C compatibility):" |
| 846 | | - echo " CXXFLAGS: -std=c++17 -stdlib=libc++" |
| 847 | | - echo " CFLAGS: (empty)" |
| 848 | | - echo " CPPFLAGS: $CPPFLAGS" |
| 849 | | - |
| 850 | | - |
| 851 | | - echo "Updating Makefile for PHP 8.1 C++17 compatibility..." |
| 852 | | - sed -i.bak 's/-std=c++14/-std=c++17/g' Makefile 2>/dev/null || echo "No C++14 flags found in Makefile to replace" |
| 853 | | - sed -i.bak 's/-std=gnu++14/-std=gnu++17/g' Makefile 2>/dev/null || echo "No gnu++14 flags found in Makefile to replace" |
| 854 | | - |
| 855 | | - |
| 856 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 857 | | - export CFLAGS="" |
| 858 | | - export CC=clang |
| 859 | | - export CXX=clang++ |
| 860 | | - echo "Final CXXFLAGS: $CXXFLAGS" |
| 861 | | - |
| 862 | | - |
| 863 | | - echo "Forcing C++17 in all Makefile compilation rules..." |
| 864 | | - sed -i.bak 's/$(CXX) $(CFLAGS_CXX) $(CXXFLAGS) $(CPPFLAGS_CXX) $(CPPFLAGS) -c/$(CXX) $(CFLAGS_CXX) -std=c++17 -stdlib=libc++ $(CXXFLAGS) $(CPPFLAGS_CXX) $(CPPFLAGS) -c/g' Makefile 2>/dev/null || echo "Could not update Makefile compilation rules" |
| 865 | | - |
| 866 | | - |
| 867 | | - echo "C++ flags in Makefile after all updates:" |
| 868 | | - grep -E "std=" Makefile | head -10 || echo "No std flags found in Makefile" |
| 869 | | - |
| 870 | | - |
| 871 | | - export CXXFLAGS="-std=c++17 -stdlib=libc++" |
| 872 | | - export CFLAGS="" |
| 873 | | - export CPPFLAGS="$CPPFLAGS" |
| 874 | | - export CC=clang |
| 875 | | - export CXX=clang++ |
| 876 | | - |
| 877 | | - |
| 878 | | - echo "Testing C++17 compilation before build:" |
| 879 | | - echo '#include <type_traits>' > test_cpp17.cpp |
| 880 | | - echo 'int main() { std::enable_if_t<true, int> x = 0; std::is_same_v<int, int> y = true; return 0; }' >> test_cpp17.cpp |
| 881 | | - if clang++ -std=c++17 -stdlib=libc++ test_cpp17.cpp -o test_cpp17 2>/dev/null; then |
| 882 | | - echo "C++17 compilation test passed" |
| 883 | | - rm -f test_cpp17.cpp test_cpp17 |
| 884 | | - else |
| 885 | | - echo "C++17 compilation test failed" |
| 886 | | - rm -f test_cpp17.cpp test_cpp17 |
| 887 | | - fi |
| 888 | | - |
| 889 | | - |
| 890 | | - echo "Using aggressive C++17 enforcement..." |
| 891 | | - |
| 892 | | - |
| 893 | | - echo '#!/bin/bash' > cxx17_wrapper.sh |
| 894 | | - echo 'exec clang++ -std=c++17 -stdlib=libc++ "$@"' >> cxx17_wrapper.sh |
| 895 | | - chmod +x cxx17_wrapper.sh |
| 896 | | - |
| 897 | | - |
| 898 | | - make -j$JOBS CXXFLAGS="-std=c++17 -stdlib=libc++" CFLAGS="" CPPFLAGS="$CPPFLAGS" CC="clang" CXX="./cxx17_wrapper.sh" |
| 289 | + |
| 290 | + |
| 291 | + echo "🧪 Testing phar extension functionality..." |
| 292 | + PHAR_LOADED=$(binaries/$BINARY_NAME/bin/php -r 'echo extension_loaded("phar") ? "1" : "0";') |
| 293 | + if [ "$PHAR_LOADED" = "1" ]; then |
| 294 | + echo "✅ Phar extension is loaded" |
| 295 | + |
| 296 | + echo "🧪 Testing phar creation..." |
| 297 | + echo '<?php |
| 298 | + if (extension_loaded("phar")) { |
| 299 | + try { |
| 300 | + $phar = new Phar("test.phar"); |
| 301 | + $phar->addFromString("test.txt", "Hello World"); |
| 302 | + echo "✅ Phar creation successful\n"; |
| 303 | + unlink("test.phar"); |
| 304 | + } catch (Exception $e) { |
| 305 | + echo "❌ Phar creation failed: " . $e->getMessage() . "\n"; |
| 306 | + exit(1); |
| 307 | + } |
| 308 | + } else { |
| 309 | + echo "❌ Phar extension not loaded\n"; |
| 310 | + exit(1); |
| 311 | + } |
| 312 | + ?>' > test_phar_create.php |
| 313 | + binaries/$BINARY_NAME/bin/php -d phar.readonly=0 test_phar_create.php |
| 314 | + rm test_phar_create.php |
| 899 | 315 | else |
| 900 | | - echo "Making with explicit C++14 flags:" |
| 901 | | - echo " CXXFLAGS: -std=c++14 -stdlib=libc++" |
| 902 | | - echo " CFLAGS: (empty)" |
| 903 | | - echo " CPPFLAGS: $CPPFLAGS" |
| 904 | | - make -j$JOBS CXXFLAGS="-std=c++14 -stdlib=libc++" CFLAGS="" CPPFLAGS="$CPPFLAGS" |
| 316 | + echo "❌ Phar extension not loaded - this will break Composer!" |
| 317 | + exit 1 |
| 905 | 318 | fi |
| 319 | + |
| 320 | + |
| 321 | + echo "🧪 Testing Composer compatibility..." |
| 322 | + echo '<?php |
| 323 | + // Test essential functions for Composer |
| 324 | + $required_functions = [ |
| 325 | + "iconv", "mb_strlen", "filter_var", "hash", "json_encode", |
| 326 | + "curl_init", "openssl_get_cert_locations", "file_get_contents" |
| 327 | + ]; |
| 328 | + |
| 329 | + foreach ($required_functions as $func) { |
| 330 | + if (function_exists($func)) { |
| 331 | + echo "✅ Function $func: Available\n"; |
| 332 | + } else { |
| 333 | + echo "❌ Function $func: Missing\n"; |
| 334 | + exit(1); |
| 335 | + } |
| 336 | + } |
| 337 | + |
| 338 | + // Test essential classes |
| 339 | + $required_classes = ["Phar", "DOMDocument", "XMLReader", "ZipArchive"]; |
| 340 | + foreach ($required_classes as $class) { |
| 341 | + if (class_exists($class)) { |
| 342 | + echo "✅ Class $class: Available\n"; |
| 343 | + } else { |
| 344 | + echo "❌ Class $class: Missing\n"; |
| 345 | + exit(1); |
| 346 | + } |
| 347 | + } |
| 348 | + |
| 349 | + echo "✅ All Composer compatibility checks passed\n"; |
| 350 | + ?>' > test_composer_compat.php |
| 351 | + binaries/$BINARY_NAME/bin/php test_composer_compat.php |
| 352 | + rm test_composer_compat.php |
| 353 | + |
| 354 | + echo "✅ All PHP binary tests passed successfully!" |
| 906 | 355 | else |
| 907 | | - make -j$JOBS |
| 356 | + echo "❌ PHP binary not found" |
| 357 | + exit 1 |
| 908 | 358 | fi |
| 909 | 359 | |
| 910 | | - - name: Install PHP |
| 360 | + - name: Test PHP Binary (Windows) |
| 361 | + if: matrix.platform == 'win32' |
| 911 | 362 | run: | |
| 912 | | - cd ${{ env.PHP_SOURCE_DIR }} |
| 913 | | - make install |
| 914 | | - |
| 915 | | - |
| 916 | | - INSTALL_PREFIX="$/$" |
| 917 | | - "$INSTALL_PREFIX/bin/php" --version |
| 918 | | - "$INSTALL_PREFIX/bin/php" -m |
| 919 | | - |
| 920 | | - |
| 921 | | - echo "Generating default php.ini for configuration: $" |
| 922 | | - EXT_DIR=$("$INSTALL_PREFIX/bin/php-config" --extension-dir 2>/dev/null || echo "") |
| 923 | | - PHP_INI_DIR="$INSTALL_PREFIX/lib" |
| 924 | | - mkdir -p "$PHP_INI_DIR" |
| 925 | | - PHP_INI="$PHP_INI_DIR/php.ini" |
| 926 | | - { |
| 927 | | - echo "; Launchpad php.ini (auto-generated in CI)" |
| 928 | | - echo "memory_limit = 512M" |
| 929 | | - echo "max_execution_time = 300" |
| 930 | | - echo "upload_max_filesize = 64M" |
| 931 | | - echo "post_max_size = 64M" |
| 932 | | - echo "display_errors = On" |
| 933 | | - echo "error_reporting = E_ALL" |
| 934 | | - if [ -n "$EXT_DIR" ]; then |
| 935 | | - echo "extension_dir = \"$EXT_DIR\"" |
| 936 | | - fi |
| 937 | | - case "$" in |
| 938 | | - "laravel-postgres") |
| 939 | | - echo "extension=pdo_pgsql" |
| 940 | | - echo "extension=pgsql" |
| 941 | | - ;; |
| 942 | | - "laravel-mysql") |
| 943 | | - echo "extension=pdo_mysql" |
| 944 | | - echo "extension=mysqli" |
| 945 | | - ;; |
| 946 | | - "laravel-sqlite") |
| 947 | | - echo "extension=pdo_sqlite" |
| 948 | | - echo "extension=sqlite3" |
| 949 | | - ;; |
| 950 | | - "enterprise"|"full-stack") |
| 951 | | - echo "extension=pdo_pgsql" |
| 952 | | - echo "extension=pgsql" |
| 953 | | - echo "extension=pdo_mysql" |
| 954 | | - echo "extension=mysqli" |
| 955 | | - echo "extension=pdo_sqlite" |
| 956 | | - echo "extension=sqlite3" |
| 957 | | - ;; |
| 958 | | - *) |
| 959 | | - : |
| 960 | | - ;; |
| 961 | | - esac |
| 962 | | - } > "$PHP_INI" |
| 963 | | - echo "Created $PHP_INI" |
| 964 | | - |
| 965 | | - - name: Create binary package |
| 966 | | - run: | |
| 967 | | - cd ${{ env.OUTPUT_DIR }} |
| 968 | | - |
| 969 | | - |
| 970 | | - cat > ${{ env.BINARY_NAME }}/metadata.json << EOF |
| 971 | | - { |
| 972 | | - "php_version": "$", |
| 973 | | - "platform": "$", |
| 974 | | - "architecture": "$", |
| 975 | | - "configuration": "$", |
| 976 | | - "built_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", |
| 977 | | - "built_by": "GitHub Actions", |
| 978 | | - "commit": "$", |
| 979 | | - "extensions": "$(echo '$' | tr ' ' '\n' | grep -E '^--(enable|with)-' | sed 's/^--[^-]*-//' | sort | tr '\n' ',' | sed 's/,$//')" |
| 363 | + $BINARY_NAME = "php-$-$-$-$" |
| 364 | + $phpExeRoot = "binaries\$BINARY_NAME\php.exe" |
| 365 | + $phpExeBin = "binaries\$BINARY_NAME\bin\php.exe" |
| 366 | + $PHP = if (Test-Path -Path $phpExeRoot -PathType Leaf) { $phpExeRoot } elseif (Test-Path -Path $phpExeBin -PathType Leaf) { $phpExeBin } else { $null } |
| 367 | + Write-Host "Checking for binary at: $PHP" |
| 368 | + |
| 369 | + |
| 370 | + Write-Host "📂 Binary directory structure:" |
| 371 | + Get-ChildItem -Path "binaries\$BINARY_NAME" -Recurse | Format-Table Name, Length, LastWriteTime |
| 372 | + |
| 373 | + |
| 374 | + if ($PHP -and (Test-Path -Path $PHP -PathType Leaf)) { |
| 375 | + Write-Host "✅ PHP binary exists at expected location" |
| 376 | + |
| 377 | + |
| 378 | + $fileSize = (Get-Item $PHP).Length |
| 379 | + Write-Host "📊 PHP binary size: $fileSize bytes" |
| 380 | + |
| 381 | + |
| 382 | + Write-Host "🧪 Testing PHP binary..." |
| 383 | + & $PHP --version |
| 384 | + Write-Host "📋 All available extensions:" |
| 385 | + & $PHP -m |
| 386 | + |
| 387 | + |
| 388 | + $REQUIRED_EXTENSIONS = @( |
| 389 | + "Core", "date", "hash", "json", "pcre", "Reflection", "SPL", "standard", |
| 390 | + "mbstring", "iconv", "filter", "ctype", "tokenizer", "session", "fileinfo", |
| 391 | + "phar", "dom", "xml", "xmlreader", "xmlwriter", "simplexml", |
| 392 | + "curl", "openssl", "zip", "zlib", "calendar", "ftp", |
| 393 | + "shmop", "sockets", "exif", "bcmath", "bz2", "gettext", "readline" |
| 394 | + ) |
| 395 | + |
| 396 | + |
| 397 | + $ZEND_EXTENSIONS = @("opcache") |
| 398 | + |
| 399 | + |
| 400 | + Write-Host "🧪 Testing essential extensions..." |
| 401 | + $MISSING_EXTENSIONS = @() |
| 402 | + foreach ($ext in $REQUIRED_EXTENSIONS) { |
| 403 | + $extLoaded = & $PHP -r "echo extension_loaded('$ext') ? '1' : '0';" |
| 404 | + if ($extLoaded -eq "1") { |
| 405 | + Write-Host "✅ $ext`: LOADED" |
| 406 | + } else { |
| 407 | + Write-Host "❌ $ext`: MISSING" |
| 408 | + $MISSING_EXTENSIONS += $ext |
| 409 | + } |
| 410 | + } |
| 411 | + |
| 412 | + |
| 413 | + foreach ($ext in $ZEND_EXTENSIONS) { |
| 414 | + $extLoaded = & $PHP -r "echo function_exists('opcache_get_status') ? '1' : '0';" |
| 415 | + if ($extLoaded -eq "1") { |
| 416 | + Write-Host "✅ $ext`: LOADED" |
| 417 | + } else { |
| 418 | + Write-Host "❌ $ext`: MISSING" |
| 419 | + $MISSING_EXTENSIONS += $ext |
| 420 | + } |
| 421 | + } |
| 422 | + |
| 423 | + |
| 424 | + if ($MISSING_EXTENSIONS.Count -gt 0) { |
| 425 | + Write-Host "❌ Critical extensions missing: $($MISSING_EXTENSIONS -join ', ')" |
| 426 | + Write-Host "This build is incomplete and will cause issues with Composer and Laravel." |
| 427 | + exit 1 |
| 428 | + } |
| 429 | + |
| 430 | + |
| 431 | + Write-Host "🧪 Testing phar extension functionality..." |
| 432 | + $pharLoaded = & $PHP -r 'echo extension_loaded("phar") ? "1" : "0";' |
| 433 | + if ($pharLoaded -eq "1") { |
| 434 | + Write-Host "✅ Phar extension is loaded" |
| 435 | + |
| 436 | + Write-Host "🧪 Testing phar creation..." |
| 437 | + $pharTest = & $PHP -d phar.readonly=0 -r 'try { $p = new Phar("test.phar"); $p->addFromString("t.txt", "x"); echo "OK"; unlink("test.phar"); } catch (Exception $e) { echo "ERR: ".$e->getMessage(); exit(1); }' |
| 438 | + if ($pharTest -eq "OK") { |
| 439 | + Write-Host "✅ Phar creation successful" |
| 440 | + } else { |
| 441 | + Write-Host "❌ Phar creation failed: $pharTest" |
| 442 | + exit 1 |
| 443 | + } |
| 444 | + } else { |
| 445 | + Write-Host "❌ Phar extension not loaded - this will break Composer!" |
| 446 | + exit 1 |
| 447 | + } |
| 448 | + |
| 449 | + |
| 450 | + Write-Host "🧪 Testing Composer compatibility..." |
| 451 | + $composerTestContent = "<?php`n// Test essential functions for Composer`n`$required_functions = [`n `"iconv`", `"mb_strlen`", `"filter_var`", `"hash`", `"json_encode`",`n `"curl_init`", `"openssl_get_cert_locations`", `"file_get_contents`"`n];`n`nforeach (`$required_functions as `$func) {`n if (function_exists(`$func)) {`n echo `"✅ Function `$func: Available\n`";`n } else {`n echo `"❌ Function `$func: Missing\n`";`n exit(1);`n }`n}`n`n// Test essential classes`n`$required_classes = [`"Phar`", `"DOMDocument`", `"XMLReader`", `"ZipArchive`"];`nforeach (`$required_classes as `$class) {`n if (class_exists(`$class)) {`n echo `"✅ Class `$class: Available\n`";`n } else {`n echo `"❌ Class `$class: Missing\n`";`n exit(1);`n }`n}`n`necho `"✅ All Composer compatibility checks passed\n`";`n?>" |
| 452 | + $composerTestContent | Out-File -FilePath "test_composer_compat.php" -Encoding UTF8 |
| 453 | + & $PHP "test_composer_compat.php" |
| 454 | + Remove-Item "test_composer_compat.php" |
| 455 | + |
| 456 | + |
| 457 | + if ($fileSize -gt 1000000) { |
| 458 | + Write-Host "✅ PHP binary appears to be a real Windows binary (file size: $fileSize bytes)" |
| 459 | + |
| 460 | + |
| 461 | + $dllCount = (Get-ChildItem -Path "binaries\$BINARY_NAME" -Filter "*.dll" -Recurse).Count |
| 462 | + Write-Host "Found $dllCount DLL files in the PHP distribution" |
| 463 | + |
| 464 | + if ($dllCount -gt 10) { |
| 465 | + Write-Host "✅ PHP distribution contains expected DLL files" |
| 466 | + } else { |
| 467 | + Write-Host "⚠️ PHP distribution contains fewer DLL files than expected" |
| 468 | + } |
| 469 | + } else { |
| 470 | + Write-Host "⚠️ PHP binary is smaller than expected, might be a placeholder" |
| 471 | + } |
| 472 | + |
| 473 | + Write-Host "✅ All PHP binary tests passed successfully!" |
| 474 | + } else { |
| 475 | + Write-Host "❌ PHP binary not found at expected location" |
| 476 | + Write-Host "Directory contents:" |
| 477 | + if (Test-Path -Path "binaries\$BINARY_NAME") { |
| 478 | + Get-ChildItem -Path "binaries\$BINARY_NAME" -Recurse |
| 479 | + } else { |
| 480 | + Write-Host "Binary directory does not exist" |
| 481 | + } |
| 482 | + exit 1 |
| 980 | 483 | } |
| 981 | | - EOF |
| 982 | | - |
| 983 | | - |
| 984 | | - tar -czf ${{ env.BINARY_NAME }}.tar.gz ${{ env.BINARY_NAME }}/ |
| 985 | | - |
| 986 | | - |
| 987 | | - echo "Created package: $.tar.gz" |
| 988 | | - ls -lh ${{ env.BINARY_NAME }}.tar.gz |
| 989 | 484 | |
| 990 | | - - name: Upload binary artifact |
| 991 | | - uses: actions/upload-artifact@v4 |
| 485 | + - name: Upload PHP Binary (Unix) |
| 486 | + if: matrix.platform != 'win32' |
| 487 | + uses: actions/upload-artifact@v4.6.2 |
| 992 | 488 | with: |
| 993 | | - name: ${{ env.BINARY_NAME }} |
| 994 | | - path: ${{ env.OUTPUT_DIR }}/${{ env.BINARY_NAME }}.tar.gz |
| 995 | | - retention-days: 90 |
| 489 | + name: php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }} |
| 490 | + path: binaries/php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }}.tar.gz |
| 491 | + retention-days: 30 |
| 996 | 492 | |
| 997 | | - - name: Upload to GitHub Container Registry (Linux) |
| 998 | | - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.platform == 'linux' |
| 999 | | - run: | |
| 1000 | | - echo ${{ secrets.GITHUB_TOKEN }} | docker login ${{ env.REGISTRY_URL }} -u ${{ env.REGISTRY_USERNAME }} --password-stdin |
| 1001 | | - |
| 1002 | | - |
| 1003 | | - cd ${{ env.OUTPUT_DIR }} |
| 1004 | | - cat > Dockerfile << EOF |
| 1005 | | - FROM scratch |
| 1006 | | - COPY ${{ env.BINARY_NAME }}.tar.gz /php-binary.tar.gz |
| 1007 | | - EOF |
| 1008 | | - |
| 1009 | | - |
| 1010 | | - IMAGE_TAG="$/$/php-binaries:$" |
| 1011 | | - docker build -t "$IMAGE_TAG" . |
| 1012 | | - docker push "$IMAGE_TAG" |
| 493 | + - name: Upload PHP Binary (Windows) |
| 494 | + if: matrix.platform == 'win32' |
| 495 | + uses: actions/upload-artifact@v4.6.2 |
| 496 | + with: |
| 497 | + name: php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }} |
| 498 | + path: binaries/php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }}.zip |
| 499 | + retention-days: 30 |
| 1013 | 500 | |
| 1014 | 501 | |
| 1015 | 502 | create-release: |
| 1016 | | - needs: [check-for-updates, build-matrix, get-php-versions] |
| 503 | + needs: [check-for-updates, build, get-php-versions] |
| 1017 | 504 | runs-on: ubuntu-latest |
| 1018 | 505 | if: ((github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch') && (needs.check-for-updates.outputs.rebuild_needed == 'true' || github.event.inputs.force_rebuild == 'true') |
| 1019 | 506 | |
| @@ -1055,14 +542,15 @@ jobs: |
| 1055 | 542 | echo "🔍 Current directory structure:" |
| 1056 | 543 | ls -la |
| 1057 | 544 | echo "" |
| 1058 | | - echo "🔍 Looking for tar.gz files:" |
| 1059 | | - find . -name "*.tar.gz" -type f |
| 545 | + echo "🔍 Looking for binary files (tar.gz and zip):" |
| 546 | + find . -name "*.tar.gz" -type f -o -name "*.zip" -type f |
| 1060 | 547 | echo "" |
| 1061 | 548 | |
| 1062 | 549 | |
| 1063 | 550 | echo "[]" > binaries_array.json |
| 1064 | 551 | |
| 1065 | | - |
| 552 | + |
| 553 | + echo "Processing Unix binaries (.tar.gz files)..." |
| 1066 | 554 | for tarball in $(find . -name "*.tar.gz" -type f); do |
| 1067 | 555 | filename=$(basename "$tarball") |
| 1068 | 556 | size=$(stat -c%s "$tarball" 2>/dev/null || stat -f%z "$tarball") |
| @@ -1115,6 +603,70 @@ jobs: |
| 1115 | 603 | jq --argjson binary "$binary_json" '. += [$binary]' binaries_array.json > temp_array.json |
| 1116 | 604 | mv temp_array.json binaries_array.json |
| 1117 | 605 | done |
| 606 | + |
| 607 | + |
| 608 | + echo "Processing Windows binaries (.zip files)..." |
| 609 | + for zipfile in $(find . -name "*.zip" -type f); do |
| 610 | + filename=$(basename "$zipfile") |
| 611 | + size=$(stat -c%s "$zipfile" 2>/dev/null || stat -f%z "$zipfile") |
| 612 | + |
| 613 | + echo "Processing: $filename (size: $size bytes)" |
| 614 | + |
| 615 | + |
| 616 | + |
| 617 | + binary_name=$(echo "$filename" | sed 's/\.zip$//') |
| 618 | + |
| 619 | + |
| 620 | + if [[ "$binary_name" =~ ^php-([^-]+)-([^-]+)-([^-]+)-(.+)$ ]]; then |
| 621 | + php_version="${BASH_REMATCH[1]}" |
| 622 | + platform="${BASH_REMATCH[2]}" |
| 623 | + architecture="${BASH_REMATCH[3]}" |
| 624 | + configuration="${BASH_REMATCH[4]}" |
| 625 | + else |
| 626 | + |
| 627 | + php_version="unknown" |
| 628 | + platform="unknown" |
| 629 | + architecture="unknown" |
| 630 | + configuration="unknown" |
| 631 | + fi |
| 632 | + |
| 633 | + |
| 634 | + |
| 635 | + |
| 636 | + temp_dir="temp_extract_$RANDOM" |
| 637 | + mkdir -p "$temp_dir" |
| 638 | + |
| 639 | + |
| 640 | + unzip -q -j "$zipfile" "*/metadata.json" -d "$temp_dir" 2>/dev/null || echo '{}' > "$temp_dir/metadata.json" |
| 641 | + |
| 642 | + |
| 643 | + binary_json=$(jq -n \ |
| 644 | + --arg filename "$filename" \ |
| 645 | + --arg size "$size" \ |
| 646 | + --arg php_version "$php_version" \ |
| 647 | + --arg platform "$platform" \ |
| 648 | + --arg architecture "$architecture" \ |
| 649 | + --arg configuration "$configuration" \ |
| 650 | + --arg built_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ |
| 651 | + --arg extensions "$(cat "$temp_dir/metadata.json" | jq -r '.extensions // ""' 2>/dev/null || echo '')" \ |
| 652 | + '{ |
| 653 | + filename: $filename, |
| 654 | + size: ($size | tonumber), |
| 655 | + php_version: $php_version, |
| 656 | + platform: $platform, |
| 657 | + architecture: $architecture, |
| 658 | + configuration: $configuration, |
| 659 | + built_at: $built_at, |
| 660 | + extensions: $extensions |
| 661 | + }') |
| 662 | + |
| 663 | + |
| 664 | + jq --argjson binary "$binary_json" '. += [$binary]' binaries_array.json > temp_array.json |
| 665 | + mv temp_array.json binaries_array.json |
| 666 | + |
| 667 | + |
| 668 | + rm -rf "$temp_dir" |
| 669 | + done |
| 1118 | 670 | |
| 1119 | 671 | |
| 1120 | 672 | jq --arg version "$(date +%Y.%m.%d)" \ |
| @@ -1135,7 +687,9 @@ jobs: |
| 1135 | 687 | cat manifest.json |
| 1136 | 688 | echo "" |
| 1137 | 689 | echo "📊 Summary:" |
| 1138 | | - echo " - Total binaries found: $(find . -name "*.tar.gz" -type f | wc -l)" |
| 690 | + echo " - Unix binaries found: $(find . -name "*.tar.gz" -type f | wc -l)" |
| 691 | + echo " - Windows binaries found: $(find . -name "*.zip" -type f | wc -l)" |
| 692 | + echo " - Total binaries found: $(find . -name "*.tar.gz" -o -name "*.zip" -type f | wc -l)" |
| 1139 | 693 | echo " - Manifest file size: $(stat -c%s manifest.json 2>/dev/null || stat -f%z manifest.json) bytes" |
| 1140 | 694 | |
| 1141 | 695 | - name: Create GitHub Release |
| @@ -1148,7 +702,7 @@ jobs: |
| 1148 | 702 | |
| 1149 | 703 | > This release contains precompiled PHP binaries optimized for modern PHP usage |
| 1150 | 704 | |
| 1151 | | - - **Platforms**: Linux (x86_64), macOS (ARM64 & Intel) |
| 705 | + - **Platforms**: Linux (x86_64), macOS (ARM64 & Intel), Windows (x86_64) |
| 1152 | 706 | - **PHP Versions**: ${{ steps.format-versions.outputs.php_versions_string }} |
| 1153 | 707 | - **Configuration Options**: |
| 1154 | 708 | - `laravel-mysql`: Laravel applications using MySQL or MariaDB |
| @@ -1168,6 +722,7 @@ jobs: |
| 1168 | 722 | See `manifest.json` for detailed information about each binary. |
| 1169 | 723 | files: | |
| 1170 | 724 | binaries/**/*.tar.gz |
| 725 | + binaries/**/*.zip |
| 1171 | 726 | binaries/manifest.json |
| 1172 | 727 | draft: false |
| 1173 | 728 | prerelease: false |