also looking at this
chore(deps): update dependency actions/download-artifact to v5.0.0
#178
1 file
+638
-860
| @@ -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 | # Check for updates daily at 2 AM UTC |
| 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 | # First job: Check if we need to rebuild based on new PHP versions |
| 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,640 @@ jobs: | ||
| 83 | 90 | - name: Get PHP versions from ts-pkgx |
| 84 | 91 | id: get-versions |
| 85 | 92 | run: | |
| 86 | # Get dynamic PHP versions using our custom script | |
| 87 | PHP_VERSIONS=$(bun scripts/get-php-versions.ts | grep "JSON output for GitHub Actions:" -A 1 | tail -1) | |
| 93 | if [ -n "$" ]; then | |
| 94 | # Use specific version if provided | |
| 95 | PHP_VERSIONS='["$"]' | |
| 96 | else | |
| 97 | # Get dynamic PHP versions using our custom script | |
| 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 | # Job to provide feedback when no rebuild is needed | |
| 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 | # Matrix strategy for building across different platforms and configurations | |
| 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] # Include Intel Mac | |
| 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-14 | |
| 121 | - macos-15 | |
| 122 | - macos-15-intel | |
| 123 | - windows-latest | |
| 121 | 124 | include: |
| 122 | # Add Windows later if needed | |
| 123 | 125 | - os: ubuntu-latest |
| 124 | 126 | platform: linux |
| 125 | 127 | arch: x86_64 |
| 126 | - os: macos-latest | |
| 128 | - os: macos-14 | |
| 129 | platform: darwin | |
| 130 | arch: x86_64 | |
| 131 | - os: macos-15 | |
| 127 | 132 | platform: darwin |
| 128 | 133 | arch: arm64 |
| 129 | - os: macos-13 | |
| 134 | - os: macos-15-intel | |
| 130 | 135 | platform: darwin |
| 131 | 136 | arch: x86_64 |
| 132 | exclude: | |
| 133 | # Skip some combinations to reduce build time | |
| 134 | - os: macos-13 | |
| 135 | config: api-only | |
| 136 | # WordPress mainly used on Linux | |
| 137 | - os: macos-13 | |
| 138 | config: wordpress | |
| 137 | - os: windows-latest | |
| 138 | platform: win32 | |
| 139 | arch: x86_64 | |
| 140 | ||
| 141 | runs-on: ${{ matrix.os }} | |
| 139 | 142 | |
| 140 | 143 | steps: |
| 141 | - name: Checkout repository | |
| 144 | - name: Checkout code | |
| 142 | 145 | uses: actions/checkout@v4 |
| 143 | 146 | |
| 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 | |
| 147 | - name: Setup Bun | |
| 153 | 148 | uses: oven-sh/setup-bun@v2 |
| 154 | ||
| 155 | - name: Use cached node_modules | |
| 156 | uses: actions/cache@v4 | |
| 157 | 149 | 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 | |
| 150 | bun-version: latest | |
| 165 | 151 | |
| 166 | - name: Install build dependencies (Ubuntu) | |
| 152 | - name: Install build dependencies (Linux) | |
| 167 | 153 | if: matrix.platform == 'linux' |
| 168 | 154 | run: | |
| 169 | # Install PHP dependencies via apt-get (alternative to launchpad) | |
| 170 | echo "🔧 Installing PHP dependencies via apt-get..." | |
| 171 | echo "🔍 Debug info:" | |
| 172 | echo " - Platform: linux" | |
| 173 | echo " - Architecture: $(uname -m)" | |
| 174 | ||
| 175 | 155 | sudo apt-get update |
| 176 | 156 | 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 | |
| 157 | build-essential autoconf automake libtool pkg-config bison re2c \ | |
| 158 | libxml2-dev libssl-dev libcurl4-openssl-dev libpng-dev libjpeg-dev \ | |
| 159 | libfreetype6-dev libonig-dev libzip-dev libpq-dev libreadline-dev \ | |
| 160 | libbz2-dev libgmp-dev libldap2-dev libxslt1-dev libicu-dev \ | |
| 161 | libsodium-dev zlib1g-dev libsqlite3-dev libenchant-2-dev \ | |
| 162 | libtidy-dev libsnmp-dev libgd-dev libwebp-dev libc-client-dev \ | |
| 163 | libkrb5-dev libedit-dev libargon2-dev libffi-dev \ | |
| 164 | libmcrypt-dev libmhash-dev libpcre3-dev libexpat1-dev \ | |
| 165 | libc-ares-dev libnghttp2-dev libpsl-dev libidn2-dev \ | |
| 166 | librtmp-dev libssh2-1-dev libgssapi-krb5-2 libkrb5-dev \ | |
| 167 | gettext libgettext-ocaml-dev | |
| 203 | 168 | |
| 204 | 169 | - name: Install build dependencies (macOS) |
| 205 | 170 | if: matrix.platform == 'darwin' |
| 206 | 171 | run: | |
| 207 | # Install PHP dependencies via Homebrew (alternative to launchpad) | |
| 208 | echo "�� Installing PHP dependencies via Homebrew..." | |
| 209 | echo "�� Debug info:" | |
| 210 | echo " - Platform: darwin" | |
| 211 | echo " - Architecture: $(uname -m)" | |
| 212 | ||
| 213 | # Install dependencies with quiet output to reduce warnings | |
| 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 | # Verify readline installation | |
| 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 | # Verify PostgreSQL installation | |
| 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 | # Verify bzip2 installation | |
| 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 | # Verify gettext installation | |
| 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 | # Verify OpenLDAP installation | |
| 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 | # Create symlinks to help PHP find readline, bzip2, gettext, and openldap | |
| 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 | |
| 288 | run: | | |
| 289 | mkdir -p ${{ env.BUILD_DIR }} ${{ env.OUTPUT_DIR }} | |
| 290 | ||
| 291 | # Determine libpq prefix only on macOS (avoid brew on Linux) | |
| 292 | PG_PREFIX="" | |
| 293 | if [[ "$" == "darwin" ]]; then | |
| 294 | PG_PREFIX="$(brew --prefix libpq)" | |
| 172 | # macOS: Let Launchpad handle all dependencies | |
| 173 | echo "�� macOS build will use Launchpad for all dependencies" | |
| 174 | echo "�� Installing PHP dependencies via Launchpad first..." | |
| 175 | ||
| 176 | # Pre-install dependencies to ensure they're available | |
| 177 | echo "🔧 Pre-installing dependencies via Launchpad..." | |
| 178 | bun run launchpad install php --deps-only | |
| 179 | ||
| 180 | # Wait for dependencies to be fully installed | |
| 181 | echo "⏳ Waiting for dependency installation to complete..." | |
| 182 | sleep 10 | |
| 183 | ||
| 184 | # Debug: Check what was actually installed | |
| 185 | echo "🔍 Checking installed dependencies..." | |
| 186 | echo "📁 .local directory structure (first level):" | |
| 187 | find "$HOME/.local" -maxdepth 2 -type d | sort | head -20 | |
| 188 | ||
| 189 | echo "🔍 Looking for pkg-config specifically..." | |
| 190 | find "$HOME/.local" -name "*pkg*" -type f 2>/dev/null | head -10 || echo "No pkg-related files found" | |
| 191 | ||
| 192 | echo "🔍 Looking for freedesktop.org directory..." | |
| 193 | find "$HOME/.local" -path "*freedesktop*" -type d 2>/dev/null | head -5 || echo "No freedesktop.org directories found" | |
| 194 | ||
| 195 | # Debug: Check if pkg-config is available | |
| 196 | echo "🔍 Checking for pkg-config..." | |
| 197 | if command -v pkg-config >/dev/null 2>&1; then | |
| 198 | echo "✅ pkg-config found: $(which pkg-config)" | |
| 199 | echo "📋 pkg-config version: $(pkg-config --version)" | |
| 200 | else | |
| 201 | echo "❌ pkg-config not found in PATH" | |
| 202 | echo "🔍 Searching for pkg-config in .local..." | |
| 203 | find "$HOME/.local" -name "pkg-config" -type f 2>/dev/null || echo "No pkg-config found in .local" | |
| 295 | 204 | fi |
| 296 | 205 | |
| 297 | # Create configuration based on matrix config | |
| 298 | case "$" in | |
| 299 | "laravel-mysql") | |
| 300 | # For PHP 8.1, disable intl extension to avoid ICU4C C++17 issues | |
| 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 | # For PHP 8.1, disable intl extension to avoid ICU4C C++17 issues | |
| 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 | # For PHP 8.1, disable intl extension to avoid ICU4C C++17 issues | |
| 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 | # For PHP 8.1, disable intl extension to avoid ICU4C C++17 issues | |
| 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 | # Comprehensive configuration with all major database drivers and extensions for local testing | |
| 339 | # For PHP 8.1, disable intl extension to avoid ICU4C C++17 issues | |
| 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 | |
| 206 | # Debug: Check if ICU libraries are available | |
| 207 | echo "🔍 Checking for ICU libraries..." | |
| 208 | if [ -d "$HOME/.local/unicode.org" ]; then | |
| 209 | echo "✅ ICU libraries found at: $HOME/.local/unicode.org" | |
| 210 | ls -la "$HOME/.local/unicode.org/" | |
| 211 | if [ -f "$HOME/.local/unicode.org"/*/lib/pkgconfig/icu-uc.pc ]; then | |
| 212 | echo "✅ ICU pkgconfig files found" | |
| 213 | find "$HOME/.local/unicode.org" -name "*.pc" -type f | head -5 | |
| 214 | else | |
| 215 | echo "❌ ICU pkgconfig files not found" | |
| 216 | fi | |
| 217 | else | |
| 218 | echo "❌ ICU libraries not found" | |
| 219 | fi | |
| 347 | 220 | |
| 348 | echo "CONFIGURE_EXTENSIONS=$EXTENSIONS" >> $GITHUB_ENV | |
| 221 | # Debug: Check libxml2 libraries | |
| 222 | echo "🔍 Checking for libxml2 libraries..." | |
| 223 | if [ -d "$HOME/.local/gnome.org/libxml2" ]; then | |
| 224 | echo "✅ libxml2 libraries found at: $HOME/.local/gnome.org/libxml2" | |
| 225 | ls -la "$HOME/.local/gnome.org/libxml2/" | |
| 226 | if [ -f "$HOME/.local/gnome.org/libxml2"/*/lib/pkgconfig/libxml-2.0.pc ]; then | |
| 227 | echo "✅ libxml2 pkgconfig files found" | |
| 228 | find "$HOME/.local/gnome.org/libxml2" -name "libxml-2.0.pc" -type f | |
| 229 | else | |
| 230 | echo "❌ libxml2 pkgconfig files not found" | |
| 231 | fi | |
| 232 | else | |
| 233 | echo "❌ libxml2 libraries not found" | |
| 234 | fi | |
| 349 | 235 | |
| 350 | - name: Set macOS specific paths | |
| 351 | if: matrix.platform == 'darwin' | |
| 352 | run: | | |
| 353 | # Set paths for Homebrew dependencies including keg-only packages | |
| 354 | # Use a more organized approach to avoid duplicates | |
| 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 | # Set readline-specific paths | |
| 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 | # Ensure libpq is linked for pg_config availability (keg-only) | |
| 419 | brew link libpq --force || true | |
| 420 | ||
| 421 | # Check if PostgreSQL is available and working | |
| 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 | |
| 236 | # Debug: Check PATH and PKG_CONFIG_PATH | |
| 237 | echo "🔍 Environment check:" | |
| 238 | echo "PATH includes unicode.org: $(echo $PATH | grep -o unicode.org || echo 'NO')" | |
| 239 | echo "PATH includes freedesktop.org: $(echo $PATH | grep -o freedesktop.org || echo 'NO')" | |
| 240 | echo "PKG_CONFIG_PATH: ${PKG_CONFIG_PATH:-'NOT SET'}" | |
| 241 | ||
| 242 | # Debug: Check if Launchpad environment script exists | |
| 243 | echo "🔍 Checking for Launchpad environment..." | |
| 244 | if [ -f "$HOME/.local/launchpad.sh" ]; then | |
| 245 | echo "✅ Launchpad environment script found" | |
| 246 | echo "📋 Sourcing environment to check paths..." | |
| 247 | source "$HOME/.local/launchpad.sh" | |
| 248 | echo "PATH after sourcing: ${PATH:0:200}..." | |
| 249 | echo "PKG_CONFIG_PATH after sourcing: ${PKG_CONFIG_PATH:-'NOT SET'}" | |
| 436 | 250 | else |
| 437 | echo "PostgreSQL not found or not working, will disable PostgreSQL support" | |
| 438 | echo "POSTGRESQL_AVAILABLE=false" >> $GITHUB_ENV | |
| 251 | echo "❌ Launchpad environment script not found" | |
| 439 | 252 | fi |
| 440 | 253 | |
| 441 | - name: Download and extract PHP source | |
| 254 | - name: Install build dependencies (Windows) | |
| 255 | if: matrix.platform == 'win32' | |
| 442 | 256 | run: | |
| 443 | cd ${{ env.BUILD_DIR }} | |
| 444 | # Temporarily modify PATH to prioritize system binaries over launchpad binaries | |
| 445 | # This prevents conflicts with launchpad-installed binaries that may have library dependencies | |
| 446 | export PATH="/usr/bin:/usr/local/bin:/bin:$PATH" | |
| 447 | # Use system curl instead of launchpad curl to avoid library conflicts | |
| 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 | |
| 257 | # Windows: Install Visual Studio Build Tools and dependencies for PHP compilation | |
| 258 | choco install visualstudio2022buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --includeOptional --passive" | |
| 259 | choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' | |
| 260 | choco install git | |
| 261 | # Install additional dependencies needed for PHP extensions | |
| 262 | echo "Windows build dependencies installed for PHP compilation" | |
| 263 | ||
| 264 | - name: Setup Launchpad Environment (macOS) | |
| 265 | if: matrix.platform == 'darwin' | |
| 266 | shell: bash | |
| 454 | 267 | run: | |
| 455 | cd ${{ env.PHP_SOURCE_DIR }} | |
| 456 | ||
| 457 | # Create installation directory | |
| 458 | INSTALL_PREFIX="$/$" | |
| 459 | mkdir -p "$INSTALL_PREFIX" | |
| 460 | ||
| 461 | # Configure with platform-specific options | |
| 462 | if [[ "$" == "darwin" ]]; then | |
| 463 | # On macOS, use Homebrew-installed libraries | |
| 464 | # Set environment variables for readline detection | |
| 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 | # Set PostgreSQL environment variables and PATH | |
| 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 | # Set bzip2 environment variables | |
| 475 | export BZIP2_CFLAGS="-I$(brew --prefix bzip2)/include" | |
| 476 | export BZIP2_LIBS="-L$(brew --prefix bzip2)/lib -lbz2" | |
| 477 | ||
| 478 | # Set gettext environment variables | |
| 479 | export GETTEXT_CFLAGS="-I$(brew --prefix gettext)/include" | |
| 480 | export GETTEXT_LIBS="-L$(brew --prefix gettext)/lib -lintl" | |
| 481 | ||
| 482 | # Check if both LDAP libraries are available | |
| 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 | |
| 268 | # Find and setup Launchpad environment variables | |
| 269 | echo "🔧 Setting up Launchpad environment for macOS build..." | |
| 270 | ||
| 271 | # Store original PATH to preserve system tools | |
| 272 | echo "ORIGINAL_PATH=$PATH" >> $GITHUB_ENV | |
| 273 | ||
| 274 | # Find all Launchpad binary directories that should be added to PATH | |
| 275 | LAUNCHPAD_PATHS="" | |
| 276 | ||
| 277 | # Find pkg-config binary - search broadly first | |
| 278 | echo "🔍 Searching for pkg-config binary..." | |
| 279 | PKG_CONFIG_BINARY=$(find "$HOME/.local" -name "pkg-config" -type f 2>/dev/null | head -1) | |
| 280 | if [ -n "$PKG_CONFIG_BINARY" ]; then | |
| 281 | PKG_CONFIG_DIR=$(dirname "$PKG_CONFIG_BINARY") | |
| 282 | echo "✅ Found pkg-config at: $PKG_CONFIG_DIR" | |
| 283 | LAUNCHPAD_PATHS="$PKG_CONFIG_DIR" | |
| 284 | else | |
| 285 | echo "❌ pkg-config binary not found in .local" | |
| 286 | echo "🔍 Checking if pkg-config exists in system PATH..." | |
| 287 | if command -v pkg-config >/dev/null 2>&1; then | |
| 288 | echo "✅ pkg-config found in system PATH: $(which pkg-config)" | |
| 491 | 289 | else |
| 492 | echo "LDAP libraries not found, disabling LDAP support" | |
| 493 | LDAP_AVAILABLE=false | |
| 494 | # Remove LDAP from CONFIGURE_EXTENSIONS | |
| 495 | export CONFIGURE_EXTENSIONS=$(echo "$CONFIGURE_EXTENSIONS" | sed 's/--with-ldap//g' | sed 's/ */ /g') | |
| 496 | echo "Updated CONFIGURE_EXTENSIONS: $CONFIGURE_EXTENSIONS" | |
| 290 | echo "❌ pkg-config not found anywhere" | |
| 497 | 291 | fi |
| 292 | fi | |
| 498 | 293 | |
| 499 | # Set OpenLDAP environment variables (only if libraries are available) | |
| 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 | # Clear LDAP environment variables if not available | |
| 507 | unset LDAP_CFLAGS | |
| 508 | unset LDAP_LIBS | |
| 509 | echo "Debug: LDAP environment variables cleared" | |
| 294 | # Find other essential Launchpad tools that might override system tools | |
| 295 | # We'll be more selective to avoid overriding system tools | |
| 296 | SED_BINARY=$(find "$HOME/.local" -path "*/gnu.org/sed/*/bin/sed" -type f 2>/dev/null | head -1) | |
| 297 | if [ -n "$SED_BINARY" ]; then | |
| 298 | SED_DIR=$(dirname "$SED_BINARY") | |
| 299 | echo "✅ Found sed at: $SED_DIR" | |
| 300 | # Only add sed if we have other tools too, to avoid conflicts | |
| 301 | if [ -n "$LAUNCHPAD_PATHS" ]; then | |
| 302 | LAUNCHPAD_PATHS="$LAUNCHPAD_PATHS:$SED_DIR" | |
| 510 | 303 | fi |
| 304 | fi | |
| 305 | ||
| 306 | # Set the combined Launchpad paths (these will be prepended to PATH later) | |
| 307 | if [ -n "$LAUNCHPAD_PATHS" ]; then | |
| 308 | echo "LAUNCHPAD_BINARY_PATHS=$LAUNCHPAD_PATHS" >> $GITHUB_ENV | |
| 309 | echo "✅ Launchpad binary paths: $LAUNCHPAD_PATHS" | |
| 310 | else | |
| 311 | echo "LAUNCHPAD_BINARY_PATHS=" >> $GITHUB_ENV | |
| 312 | echo "❌ No Launchpad binary paths found - PATH will not be modified" | |
| 313 | fi | |
| 511 | 314 | |
| 512 | # Set C++ standard based on PHP version | |
| 513 | # PHP 8.4+ requires C++17, earlier versions may work with C++14 | |
| 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 | # PHP 8.2+ requires C++17 | |
| 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 | # PHP 8.1 configure step requires C++14, but build step will need C++17 for ICU4C | |
| 523 | export CXXFLAGS="-std=c++14 -stdlib=libc++" | |
| 524 | echo "Using C++14 for PHP $ (configure step only)" | |
| 315 | # Setup comprehensive PKG_CONFIG_PATH | |
| 316 | PKG_PATHS=$(find "$HOME/.local" -name "pkgconfig" -type d 2>/dev/null | tr '\n' ':') | |
| 317 | if [ -n "$PKG_PATHS" ]; then | |
| 318 | echo "LAUNCHPAD_PKG_CONFIG_PATH=$PKG_PATHS" >> $GITHUB_ENV | |
| 319 | echo "✅ PKG_CONFIG_PATH setup with $(echo "$PKG_PATHS" | tr ':' '\n' | wc -l) directories" | |
| 320 | fi | |
| 321 | ||
| 322 | - name: Build PHP | |
| 323 | shell: bash | |
| 324 | env: | |
| 325 | PHP_VERSION: ${{ matrix.php_version }} | |
| 326 | PHP_CONFIG: ${{ matrix.config }} | |
| 327 | TARGET_PLATFORM: ${{ matrix.platform }} | |
| 328 | TARGET_ARCH: ${{ matrix.arch }} | |
| 329 | BUILD_DIR: ${{ github.workspace }}/build | |
| 330 | OUTPUT_DIR: ${{ github.workspace }}/binaries | |
| 331 | # Environment for all platforms - will handle PATH logic in shell script | |
| 332 | PKG_CONFIG_PATH: ${{ matrix.platform == 'darwin' && env.LAUNCHPAD_PKG_CONFIG_PATH || env.PKG_CONFIG_PATH }} | |
| 333 | run: | | |
| 334 | # Setup PATH for macOS with Launchpad tools | |
| 335 | if [ "$" = "darwin" ]; then | |
| 336 | echo "🔧 Setting up macOS environment..." | |
| 337 | ||
| 338 | # Preserve original PATH | |
| 339 | ORIGINAL_PATH="$PATH" | |
| 340 | echo "✅ Original PATH: ${ORIGINAL_PATH:0:100}..." | |
| 341 | ||
| 342 | # Add Launchpad binary paths to PATH if they exist | |
| 343 | if [ -n "${LAUNCHPAD_BINARY_PATHS:-}" ] && [ "${LAUNCHPAD_BINARY_PATHS}" != "NOT SET" ]; then | |
| 344 | export PATH="$LAUNCHPAD_BINARY_PATHS:$ORIGINAL_PATH" | |
| 345 | echo "✅ Updated PATH with Launchpad binaries: ${LAUNCHPAD_BINARY_PATHS}" | |
| 525 | 346 | else |
| 526 | # Earlier PHP versions can use C++14 | |
| 527 | export CXXFLAGS="-std=c++14 -stdlib=libc++" | |
| 528 | echo "Using C++14 for PHP $" | |
| 347 | echo "❌ No Launchpad binary paths found - using original PATH" | |
| 529 | 348 | fi |
| 530 | 349 | |
| 531 | # Keep CFLAGS clean for C compiler | |
| 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 | # Ensure we're using clang++ on macOS | |
| 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 | |
| 350 | echo "✅ Final PATH: ${PATH:0:100}..." | |
| 351 | echo "✅ PKG_CONFIG_PATH: ${PKG_CONFIG_PATH:-'NOT SET'}" | |
| 547 | 352 | |
| 548 | # Verify C++ support based on PHP version | |
| 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 | |
| 353 | # Verify essential system tools are available | |
| 354 | echo "🔧 Checking essential system tools..." | |
| 355 | for tool in curl tar gzip grep tr find wc head; do | |
| 356 | if command -v $tool >/dev/null 2>&1; then | |
| 357 | echo "✅ $tool: $(which $tool)" | |
| 556 | 358 | else |
| 557 | echo "C++17 support test failed before configure" | |
| 558 | rm -f test_cpp.cpp test_cpp | |
| 359 | echo "❌ $tool: NOT FOUND" | |
| 559 | 360 | 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 | |
| 361 | done | |
| 362 | ||
| 363 | # Verify pkg-config is accessible | |
| 364 | echo "🔧 Checking pkg-config..." | |
| 365 | if command -v pkg-config >/dev/null 2>&1; then | |
| 366 | echo "✅ pkg-config is accessible: $(which pkg-config)" | |
| 367 | echo "✅ pkg-config version: $(pkg-config --version)" | |
| 368 | ||
| 369 | # Test libxml-2.0 specifically | |
| 370 | if pkg-config --exists libxml-2.0; then | |
| 371 | echo "✅ libxml-2.0 package found via pkg-config" | |
| 372 | echo "📋 libxml-2.0 cflags: $(pkg-config --cflags libxml-2.0)" | |
| 567 | 373 | else |
| 568 | echo "C++14 support test failed before configure" | |
| 569 | rm -f test_cpp.cpp test_cpp | |
| 374 | echo "❌ libxml-2.0 package not found via pkg-config" | |
| 375 | echo "🔍 Available packages: $(pkg-config --list-all | head -10)" | |
| 570 | 376 | fi |
| 571 | 377 | 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 | |
| 378 | echo "❌ pkg-config not accessible" | |
| 379 | echo "🔍 Searching for pkg-config in .local..." | |
| 380 | find "$HOME/.local" -name "pkg-config" -type f 2>/dev/null | head -3 || echo "No pkg-config binaries found" | |
| 582 | 381 | fi |
| 583 | ||
| 584 | # Try to find readline.h and set the path explicitly | |
| 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 | # Check if PostgreSQL is available and working | |
| 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 | # Remove PostgreSQL extensions from CONFIGURE_EXTENSIONS | |
| 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 | # Also disable PostgreSQL in the configuration | |
| 608 | EXTRA_CONFIG="$EXTRA_CONFIG --disable-pgsql --disable-pdo-pgsql" | |
| 609 | fi | |
| 610 | else | |
| 611 | # On Linux, use system-installed libraries | |
| 612 | # System libraries should be available via apt-get installation | |
| 613 | echo "Using system libraries installed via apt-get" | |
| 614 | EXTRA_CONFIG="" | |
| 615 | 382 | fi |
| 616 | 383 | |
| 617 | echo "Configuring PHP with:" | |
| 618 | echo " Extensions: $" | |
| 619 | echo " Prefix: $INSTALL_PREFIX" | |
| 620 | echo " Extra config: $EXTRA_CONFIG" | |
| 621 | ||
| 622 | # Debug: Check readline installation on macOS | |
| 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 | |
| 384 | # Run the build script with properly configured environment | |
| 385 | bun run scripts/build-php.ts | |
| 642 | 386 | |
| 643 | # Check if libcurl is found via pkg-config | |
| 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="" | |
| 387 | - name: Create tarball (Unix) | |
| 388 | if: matrix.platform != 'win32' | |
| 389 | run: | | |
| 390 | # Ensure binaries directory exists and check for builds | |
| 391 | if [ ! -d "binaries" ]; then | |
| 392 | echo "❌ Binaries directory not found" | |
| 393 | ls -la | |
| 394 | exit 1 | |
| 650 | 395 | fi |
| 651 | 396 | |
| 652 | # Build the final configure extensions based on availability | |
| 653 | FINAL_EXTENSIONS="$" | |
| 397 | cd binaries | |
| 398 | BINARY_NAME="php-$-$-$-$" | |
| 654 | 399 | |
| 655 | # If PostgreSQL is not available, remove PostgreSQL extensions | |
| 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 | # Set PHP version variables for C++ standard selection | |
| 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 | # Test C++17 support before configure | |
| 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 | |
| 400 | echo "🔍 Looking for binary directory: $BINARY_NAME" | |
| 401 | ls -la | |
| 685 | 402 | |
| 686 | if [[ "$" == "darwin" ]]; then | |
| 687 | # Set environment variables for configure | |
| 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 | # PHP 8.1 configure step uses C++14 (PHP requirement) | |
| 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" | |
| 403 | if [ -d "$BINARY_NAME" ]; then | |
| 404 | # Create metadata file if it doesn't exist | |
| 405 | if [ ! -f "$BINARY_NAME/metadata.json" ]; then | |
| 406 | echo '{"php_version":"$","platform":"$","arch":"$","config":"$","built_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > "$BINARY_NAME/metadata.json" | |
| 698 | 407 | fi |
| 699 | export CFLAGS="" | |
| 700 | export CPPFLAGS="$CPPFLAGS" | |
| 701 | ||
| 702 | # Also set CC and CXX explicitly | |
| 703 | export CC=clang | |
| 704 | export CXX=clang++ | |
| 705 | echo "Set CC=$CC, CXX=$CXX" | |
| 706 | fi | |
| 707 | 408 | |
| 708 | # Run configure with explicit environment | |
| 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 | |
| 409 | # Create tarball | |
| 410 | tar -czf "$BINARY_NAME.tar.gz" "$BINARY_NAME" | |
| 411 | echo "✅ Created tarball: $BINARY_NAME.tar.gz" | |
| 412 | ls -lh "$BINARY_NAME.tar.gz" | |
| 720 | 413 | 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 | # Check the generated Makefile for C++ flags | |
| 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" | |
| 414 | echo "❌ Binary directory not found: $BINARY_NAME" | |
| 415 | echo "Available directories:" | |
| 416 | ls -la | |
| 417 | exit 1 | |
| 737 | 418 | fi |
| 738 | 419 | |
| 739 | - name: Build PHP | |
| 420 | - name: Create tarball (Windows) | |
| 421 | if: matrix.platform == 'win32' | |
| 740 | 422 | run: | |
| 741 | cd ${{ env.PHP_SOURCE_DIR }} | |
| 742 | ||
| 743 | # Use all available CPU cores for faster builds | |
| 744 | if [[ "$" == "darwin" ]]; then | |
| 745 | JOBS=$(sysctl -n hw.ncpu) | |
| 746 | # Set C++ standard based on PHP version for build | |
| 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 | # PHP 8.1 needs C++17 for ICU4C compilation | |
| 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 | # Keep CFLAGS clean for C compiler | |
| 763 | export CFLAGS="" | |
| 764 | export CPPFLAGS="$CPPFLAGS" | |
| 765 | else | |
| 766 | JOBS=$(nproc) | |
| 767 | fi | |
| 423 | # Ensure binaries directory exists and check for builds | |
| 424 | if (-not (Test-Path -Path "binaries" -PathType Container)) { | |
| 425 | Write-Host "❌ Binaries directory not found" | |
| 426 | Get-ChildItem | |
| 427 | exit 1 | |
| 428 | } | |
| 768 | 429 | |
| 769 | echo "Building PHP with $JOBS parallel jobs" | |
| 770 | echo "CXXFLAGS: $CXXFLAGS" | |
| 771 | echo "CFLAGS: $CFLAGS" | |
| 772 | echo "CPPFLAGS: $CPPFLAGS" | |
| 773 | ||
| 774 | # Show what compiler is being used | |
| 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 | # Show compiler version and flags | |
| 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 | # Check available C++ standards | |
| 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 | |
| 430 | cd binaries | |
| 431 | $BINARY_NAME = "php-$-$-$-$" | |
| 432 | ||
| 433 | Write-Host "🔍 Looking for binary directory: $BINARY_NAME" | |
| 434 | Get-ChildItem | |
| 435 | ||
| 436 | if (Test-Path -Path $BINARY_NAME -PathType Container) { | |
| 437 | # Create metadata file if it doesn't exist | |
| 438 | if (-not (Test-Path -Path "$BINARY_NAME\metadata.json")) { | |
| 439 | $metadata = @{ | |
| 440 | php_version = "$" | |
| 441 | platform = "$" | |
| 442 | arch = "$" | |
| 443 | config = "$" | |
| 444 | built_at = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ") | |
| 445 | } | ConvertTo-Json | |
| 446 | $metadata | Out-File -FilePath "$BINARY_NAME\metadata.json" -Encoding UTF8 | |
| 447 | } | |
| 448 | ||
| 449 | # Create zip archive (Windows equivalent of tarball) | |
| 450 | Compress-Archive -Path $BINARY_NAME -DestinationPath "$BINARY_NAME.zip" -Force | |
| 451 | Write-Host "✅ Created archive: $BINARY_NAME.zip" | |
| 452 | Get-ChildItem "$BINARY_NAME.zip" | Format-List Name, Length | |
| 453 | } else { | |
| 454 | Write-Host "❌ Binary directory not found: $BINARY_NAME" | |
| 455 | Write-Host "Available directories:" | |
| 456 | Get-ChildItem | |
| 457 | exit 1 | |
| 458 | } | |
| 791 | 459 | |
| 792 | # Test C++ support based on PHP version | |
| 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 | |
| 815 | else | |
| 816 | echo "C++17 support test failed for PHP 8.1" | |
| 817 | rm -f test_cpp.cpp test_cpp | |
| 818 | 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 | |
| 460 | - name: Test PHP Binary (Unix) | |
| 461 | if: matrix.platform != 'win32' | |
| 462 | run: | | |
| 463 | BINARY_NAME="php-$-$-$-$" | |
| 464 | if [ -f "binaries/$BINARY_NAME/bin/php" ]; then | |
| 465 | echo "✅ PHP binary created successfully" | |
| 466 | binaries/$BINARY_NAME/bin/php --version | |
| 467 | echo "📋 All available extensions:" | |
| 468 | binaries/$BINARY_NAME/bin/php -m | |
| 469 | ||
| 470 | # Define essential extensions that MUST be present | |
| 471 | REQUIRED_EXTENSIONS=( | |
| 472 | "Core" "date" "hash" "json" "pcre" "Reflection" "SPL" "standard" | |
| 473 | "mbstring" "iconv" "filter" "ctype" "tokenizer" "session" "fileinfo" | |
| 474 | "phar" "dom" "xml" "xmlreader" "xmlwriter" "simplexml" | |
| 475 | "curl" "openssl" "zip" "zlib" "calendar" "ftp" "pcntl" "posix" | |
| 476 | "shmop" "sockets" "exif" "bcmath" "bz2" "gettext" "readline" | |
| 477 | ) | |
| 478 | ||
| 479 | # Define Zend extensions that need special checking | |
| 480 | ZEND_EXTENSIONS=("opcache") | |
| 481 | ||
| 482 | # Test each required extension | |
| 483 | echo "🧪 Testing essential extensions..." | |
| 484 | MISSING_EXTENSIONS=() | |
| 485 | for ext in "${REQUIRED_EXTENSIONS[@]}"; do | |
| 486 | EXT_LOADED=$(binaries/$BINARY_NAME/bin/php -r "echo extension_loaded('$ext') ? '1' : '0';") | |
| 487 | if [ "$EXT_LOADED" = "1" ]; then | |
| 488 | echo "✅ $ext: LOADED" | |
| 826 | 489 | else |
| 827 | echo "C++14 support test failed" | |
| 828 | rm -f test_cpp.cpp test_cpp | |
| 490 | echo "❌ $ext: MISSING" | |
| 491 | MISSING_EXTENSIONS+=("$ext") | |
| 829 | 492 | fi |
| 830 | fi | |
| 831 | fi | |
| 493 | done | |
| 832 | 494 | |
| 833 | # Pass compiler flags explicitly to make | |
| 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 | # Force update Makefile for PHP 8.1 to use C++17 | |
| 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 | # Set environment variables to force C++17 | |
| 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 | # Also update the Makefile to force C++17 for all compilation rules | |
| 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 | # Show what C++ flags are in the Makefile after all updates | |
| 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 | # Set system-wide C++17 flags | |
| 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 | # Test C++17 compilation before building | |
| 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 | |
| 495 | # Test Zend extensions separately | |
| 496 | for ext in "${ZEND_EXTENSIONS[@]}"; do | |
| 497 | EXT_LOADED=$(binaries/$BINARY_NAME/bin/php -r "echo function_exists('opcache_get_status') ? '1' : '0';") | |
| 498 | if [ "$EXT_LOADED" = "1" ]; then | |
| 499 | echo "✅ $ext: LOADED" | |
| 884 | 500 | else |
| 885 | echo "C++17 compilation test failed" | |
| 886 | rm -f test_cpp17.cpp test_cpp17 | |
| 501 | echo "❌ $ext: MISSING" | |
| 502 | MISSING_EXTENSIONS+=("$ext") | |
| 887 | 503 | fi |
| 504 | done | |
| 888 | 505 | |
| 889 | # Use a more aggressive approach - override the compiler | |
| 890 | echo "Using aggressive C++17 enforcement..." | |
| 891 | ||
| 892 | # Create a wrapper script that forces C++17 | |
| 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 | |
| 506 | # Check if any essential extensions are missing | |
| 507 | if [ ${#MISSING_EXTENSIONS[@]} -gt 0 ]; then | |
| 508 | echo "❌ Critical extensions missing: ${MISSING_EXTENSIONS[*]}" | |
| 509 | echo "This build is incomplete and will cause issues with Composer and Laravel." | |
| 510 | exit 1 | |
| 511 | fi | |
| 896 | 512 | |
| 897 | # Use the wrapper script as the C++ compiler | |
| 898 | make -j$JOBS CXXFLAGS="-std=c++17 -stdlib=libc++" CFLAGS="" CPPFLAGS="$CPPFLAGS" CC="clang" CXX="./cxx17_wrapper.sh" | |
| 513 | # Test phar extension functionality specifically | |
| 514 | echo "🧪 Testing phar extension functionality..." | |
| 515 | PHAR_LOADED=$(binaries/$BINARY_NAME/bin/php -r 'echo extension_loaded("phar") ? "1" : "0";') | |
| 516 | if [ "$PHAR_LOADED" = "1" ]; then | |
| 517 | echo "✅ Phar extension is loaded" | |
| 518 | # Test phar creation (essential for Composer) | |
| 519 | echo "🧪 Testing phar creation..." | |
| 520 | echo '<?php | |
| 521 | if (extension_loaded("phar")) { | |
| 522 | try { | |
| 523 | $phar = new Phar("test.phar"); | |
| 524 | $phar->addFromString("test.txt", "Hello World"); | |
| 525 | echo "✅ Phar creation successful\n"; | |
| 526 | unlink("test.phar"); | |
| 527 | } catch (Exception $e) { | |
| 528 | echo "❌ Phar creation failed: " . $e->getMessage() . "\n"; | |
| 529 | exit(1); | |
| 530 | } | |
| 531 | } else { | |
| 532 | echo "❌ Phar extension not loaded\n"; | |
| 533 | exit(1); | |
| 534 | } | |
| 535 | ?>' > test_phar_create.php | |
| 536 | binaries/$BINARY_NAME/bin/php -d phar.readonly=0 test_phar_create.php | |
| 537 | rm test_phar_create.php | |
| 899 | 538 | 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" | |
| 539 | echo "❌ Phar extension not loaded - this will break Composer!" | |
| 540 | exit 1 | |
| 905 | 541 | fi |
| 542 | ||
| 543 | # Test Composer compatibility | |
| 544 | echo "🧪 Testing Composer compatibility..." | |
| 545 | echo '<?php | |
| 546 | // Test essential functions for Composer | |
| 547 | $required_functions = [ | |
| 548 | "iconv", "mb_strlen", "filter_var", "hash", "json_encode", | |
| 549 | "curl_init", "openssl_get_cert_locations", "file_get_contents" | |
| 550 | ]; | |
| 551 | ||
| 552 | foreach ($required_functions as $func) { | |
| 553 | if (function_exists($func)) { | |
| 554 | echo "✅ Function $func: Available\n"; | |
| 555 | } else { | |
| 556 | echo "❌ Function $func: Missing\n"; | |
| 557 | exit(1); | |
| 558 | } | |
| 559 | } | |
| 560 | ||
| 561 | // Test essential classes | |
| 562 | $required_classes = ["Phar", "DOMDocument", "XMLReader", "ZipArchive"]; | |
| 563 | foreach ($required_classes as $class) { | |
| 564 | if (class_exists($class)) { | |
| 565 | echo "✅ Class $class: Available\n"; | |
| 566 | } else { | |
| 567 | echo "❌ Class $class: Missing\n"; | |
| 568 | exit(1); | |
| 569 | } | |
| 570 | } | |
| 571 | ||
| 572 | echo "✅ All Composer compatibility checks passed\n"; | |
| 573 | ?>' > test_composer_compat.php | |
| 574 | binaries/$BINARY_NAME/bin/php test_composer_compat.php | |
| 575 | rm test_composer_compat.php | |
| 576 | ||
| 577 | echo "✅ All PHP binary tests passed successfully!" | |
| 906 | 578 | else |
| 907 | make -j$JOBS | |
| 579 | echo "❌ PHP binary not found" | |
| 580 | exit 1 | |
| 908 | 581 | fi |
| 909 | 582 | |
| 910 | - name: Install PHP | |
| 583 | - name: Test PHP Binary (Windows) | |
| 584 | if: matrix.platform == 'win32' | |
| 911 | 585 | run: | |
| 912 | cd ${{ env.PHP_SOURCE_DIR }} | |
| 913 | make install | |
| 914 | ||
| 915 | # Verify installation | |
| 916 | INSTALL_PREFIX="$/$" | |
| 917 | "$INSTALL_PREFIX/bin/php" --version | |
| 918 | "$INSTALL_PREFIX/bin/php" -m # Show loaded modules | |
| 919 | ||
| 920 | # Generate a default php.ini to ensure DB extensions are enabled by default | |
| 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 | # Create metadata file | |
| 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/,$//')" | |
| 586 | $BINARY_NAME = "php-$-$-$-$" | |
| 587 | $phpExeRoot = "binaries\$BINARY_NAME\php.exe" | |
| 588 | $phpExeBin = "binaries\$BINARY_NAME\bin\php.exe" | |
| 589 | $PHP = if (Test-Path -Path $phpExeRoot -PathType Leaf) { $phpExeRoot } elseif (Test-Path -Path $phpExeBin -PathType Leaf) { $phpExeBin } else { $null } | |
| 590 | Write-Host "Checking for binary at: $PHP" | |
| 591 | ||
| 592 | # List all files in the binary directory to verify structure | |
| 593 | Write-Host "📂 Binary directory structure:" | |
| 594 | Get-ChildItem -Path "binaries\$BINARY_NAME" -Recurse | Format-Table Name, Length, LastWriteTime | |
| 595 | ||
| 596 | # Check if the PHP binary exists | |
| 597 | if ($PHP -and (Test-Path -Path $PHP -PathType Leaf)) { | |
| 598 | Write-Host "✅ PHP binary exists at expected location" | |
| 599 | ||
| 600 | # Get file size to verify it's a real binary (not just a placeholder) | |
| 601 | $fileSize = (Get-Item $PHP).Length | |
| 602 | Write-Host "📊 PHP binary size: $fileSize bytes" | |
| 603 | ||
| 604 | # Test PHP version and extensions | |
| 605 | Write-Host "🧪 Testing PHP binary..." | |
| 606 | & $PHP --version | |
| 607 | Write-Host "📋 All available extensions:" | |
| 608 | & $PHP -m | |
| 609 | ||
| 610 | # Define essential extensions that MUST be present | |
| 611 | $REQUIRED_EXTENSIONS = @( | |
| 612 | "Core", "date", "hash", "json", "pcre", "Reflection", "SPL", "standard", | |
| 613 | "mbstring", "iconv", "filter", "ctype", "tokenizer", "session", "fileinfo", | |
| 614 | "phar", "dom", "xml", "xmlreader", "xmlwriter", "simplexml", | |
| 615 | "curl", "openssl", "zip", "zlib", "calendar", "ftp", | |
| 616 | "shmop", "sockets", "exif", "bcmath", "bz2", "gettext", "readline" | |
| 617 | ) | |
| 618 | ||
| 619 | # Define Zend extensions that need special checking | |
| 620 | $ZEND_EXTENSIONS = @("opcache") | |
| 621 | ||
| 622 | # Test each required extension | |
| 623 | Write-Host "🧪 Testing essential extensions..." | |
| 624 | $MISSING_EXTENSIONS = @() | |
| 625 | foreach ($ext in $REQUIRED_EXTENSIONS) { | |
| 626 | $extLoaded = & $PHP -r "echo extension_loaded('$ext') ? '1' : '0';" | |
| 627 | if ($extLoaded -eq "1") { | |
| 628 | Write-Host "✅ $ext`: LOADED" | |
| 629 | } else { | |
| 630 | Write-Host "❌ $ext`: MISSING" | |
| 631 | $MISSING_EXTENSIONS += $ext | |
| 632 | } | |
| 633 | } | |
| 634 | ||
| 635 | # Test Zend extensions separately | |
| 636 | foreach ($ext in $ZEND_EXTENSIONS) { | |
| 637 | $extLoaded = & $PHP -r "echo function_exists('opcache_get_status') ? '1' : '0';" | |
| 638 | if ($extLoaded -eq "1") { | |
| 639 | Write-Host "✅ $ext`: LOADED" | |
| 640 | } else { | |
| 641 | Write-Host "❌ $ext`: MISSING" | |
| 642 | $MISSING_EXTENSIONS += $ext | |
| 643 | } | |
| 644 | } | |
| 645 | ||
| 646 | # Check if any essential extensions are missing | |
| 647 | if ($MISSING_EXTENSIONS.Count -gt 0) { | |
| 648 | Write-Host "❌ Critical extensions missing: $($MISSING_EXTENSIONS -join ', ')" | |
| 649 | Write-Host "This build is incomplete and will cause issues with Composer and Laravel." | |
| 650 | exit 1 | |
| 651 | } | |
| 652 | ||
| 653 | # Test phar extension functionality specifically | |
| 654 | Write-Host "🧪 Testing phar extension functionality..." | |
| 655 | $pharLoaded = & $PHP -r 'echo extension_loaded("phar") ? "1" : "0";' | |
| 656 | if ($pharLoaded -eq "1") { | |
| 657 | Write-Host "✅ Phar extension is loaded" | |
| 658 | # Test phar creation (essential for Composer) | |
| 659 | Write-Host "🧪 Testing phar creation..." | |
| 660 | $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); }' | |
| 661 | if ($pharTest -eq "OK") { | |
| 662 | Write-Host "✅ Phar creation successful" | |
| 663 | } else { | |
| 664 | Write-Host "❌ Phar creation failed: $pharTest" | |
| 665 | exit 1 | |
| 666 | } | |
| 667 | } else { | |
| 668 | Write-Host "❌ Phar extension not loaded - this will break Composer!" | |
| 669 | exit 1 | |
| 670 | } | |
| 671 | ||
| 672 | # Test Composer compatibility | |
| 673 | Write-Host "🧪 Testing Composer compatibility..." | |
| 674 | $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?>" | |
| 675 | $composerTestContent | Out-File -FilePath "test_composer_compat.php" -Encoding UTF8 | |
| 676 | & $PHP "test_composer_compat.php" | |
| 677 | Remove-Item "test_composer_compat.php" | |
| 678 | ||
| 679 | # Check if this is likely a real binary based on file size | |
| 680 | if ($fileSize -gt 1000000) { | |
| 681 | Write-Host "✅ PHP binary appears to be a real Windows binary (file size: $fileSize bytes)" | |
| 682 | ||
| 683 | # Check for DLLs which should be present in a real PHP distribution | |
| 684 | $dllCount = (Get-ChildItem -Path "binaries\$BINARY_NAME" -Filter "*.dll" -Recurse).Count | |
| 685 | Write-Host "Found $dllCount DLL files in the PHP distribution" | |
| 686 | ||
| 687 | if ($dllCount -gt 10) { | |
| 688 | Write-Host "✅ PHP distribution contains expected DLL files" | |
| 689 | } else { | |
| 690 | Write-Host "⚠️ PHP distribution contains fewer DLL files than expected" | |
| 691 | } | |
| 692 | } else { | |
| 693 | Write-Host "⚠️ PHP binary is smaller than expected, might be a placeholder" | |
| 694 | } | |
| 695 | ||
| 696 | Write-Host "✅ All PHP binary tests passed successfully!" | |
| 697 | } else { | |
| 698 | Write-Host "❌ PHP binary not found at expected location" | |
| 699 | Write-Host "Directory contents:" | |
| 700 | if (Test-Path -Path "binaries\$BINARY_NAME") { | |
| 701 | Get-ChildItem -Path "binaries\$BINARY_NAME" -Recurse | |
| 702 | } else { | |
| 703 | Write-Host "Binary directory does not exist" | |
| 704 | } | |
| 705 | exit 1 | |
| 980 | 706 | } |
| 981 | EOF | |
| 982 | ||
| 983 | # Create tarball | |
| 984 | tar -czf ${{ env.BINARY_NAME }}.tar.gz ${{ env.BINARY_NAME }}/ | |
| 985 | 707 | |
| 986 | # Show package info | |
| 987 | echo "Created package: $.tar.gz" | |
| 988 | ls -lh ${{ env.BINARY_NAME }}.tar.gz | |
| 989 | ||
| 990 | - name: Upload binary artifact | |
| 708 | - name: Upload PHP Binary (Unix) | |
| 709 | if: matrix.platform != 'win32' | |
| 991 | 710 | uses: actions/upload-artifact@v4 |
| 992 | 711 | with: |
| 993 | name: ${{ env.BINARY_NAME }} | |
| 994 | path: ${{ env.OUTPUT_DIR }}/${{ env.BINARY_NAME }}.tar.gz | |
| 995 | retention-days: 90 | |
| 712 | name: php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }} | |
| 713 | path: binaries/php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }}.tar.gz | |
| 714 | retention-days: 30 | |
| 996 | 715 | |
| 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 | # Create a simple Dockerfile for the binary | |
| 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 | # Build and push | |
| 1010 | IMAGE_TAG="$/$/php-binaries:$" | |
| 1011 | docker build -t "$IMAGE_TAG" . | |
| 1012 | docker push "$IMAGE_TAG" | |
| 716 | - name: Upload PHP Binary (Windows) | |
| 717 | if: matrix.platform == 'win32' | |
| 718 | uses: actions/upload-artifact@v4 | |
| 719 | with: | |
| 720 | name: php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }} | |
| 721 | path: binaries/php-${{ matrix.php_version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.config }}.zip | |
| 722 | retention-days: 30 | |
| 1013 | 723 | |
| 1014 | 724 | # Release job to create GitHub releases with binaries |
| 1015 | 725 | create-release: |
| 1016 | needs: [check-for-updates, build-matrix, get-php-versions] | |
| 726 | needs: [check-for-updates, build, get-php-versions] | |
| 1017 | 727 | runs-on: ubuntu-latest |
| 1018 | 728 | 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 | 729 | |
| @@ -1043,7 +753,7 @@ jobs: | ||
| 1043 | 753 | echo "php_versions_string=$PHP_VERSIONS_STRING" >> $GITHUB_OUTPUT |
| 1044 | 754 | |
| 1045 | 755 | - name: Download all artifacts |
| 1046 | uses: actions/download-artifact@v4 | |
| 756 | uses: actions/download-artifact@v5.0.0 | |
| 1047 | 757 | with: |
| 1048 | 758 | path: binaries/ |
| 1049 | 759 | |
| @@ -1055,14 +765,15 @@ jobs: | ||
| 1055 | 765 | echo "🔍 Current directory structure:" |
| 1056 | 766 | ls -la |
| 1057 | 767 | echo "" |
| 1058 | echo "🔍 Looking for tar.gz files:" | |
| 1059 | find . -name "*.tar.gz" -type f | |
| 768 | echo "🔍 Looking for binary files (tar.gz and zip):" | |
| 769 | find . -name "*.tar.gz" -type f -o -name "*.zip" -type f | |
| 1060 | 770 | echo "" |
| 1061 | 771 | |
| 1062 | 772 | # Create a temporary JSON array file |
| 1063 | 773 | echo "[]" > binaries_array.json |
| 1064 | 774 | |
| 1065 | # Find all tar.gz files recursively and process them | |
| 775 | # Process tar.gz files (Unix binaries) | |
| 776 | echo "Processing Unix binaries (.tar.gz files)..." | |
| 1066 | 777 | for tarball in $(find . -name "*.tar.gz" -type f); do |
| 1067 | 778 | filename=$(basename "$tarball") |
| 1068 | 779 | size=$(stat -c%s "$tarball" 2>/dev/null || stat -f%z "$tarball") |
| @@ -1116,6 +827,70 @@ jobs: | ||
| 1116 | 827 | mv temp_array.json binaries_array.json |
| 1117 | 828 | done |
| 1118 | 829 | |
| 830 | # Process zip files (Windows binaries) | |
| 831 | echo "Processing Windows binaries (.zip files)..." | |
| 832 | for zipfile in $(find . -name "*.zip" -type f); do | |
| 833 | filename=$(basename "$zipfile") | |
| 834 | size=$(stat -c%s "$zipfile" 2>/dev/null || stat -f%z "$zipfile") | |
| 835 | ||
| 836 | echo "Processing: $filename (size: $size bytes)" | |
| 837 | ||
| 838 | # Parse the binary name to extract components | |
| 839 | # Expected format: php-8.4.11-win32-x86_64-laravel-mysql.zip | |
| 840 | binary_name=$(echo "$filename" | sed 's/\.zip$//') | |
| 841 | ||
| 842 | # Extract components from binary name | |
| 843 | if [[ "$binary_name" =~ ^php-([^-]+)-([^-]+)-([^-]+)-(.+)$ ]]; then | |
| 844 | php_version="${BASH_REMATCH[1]}" | |
| 845 | platform="${BASH_REMATCH[2]}" | |
| 846 | architecture="${BASH_REMATCH[3]}" | |
| 847 | configuration="${BASH_REMATCH[4]}" | |
| 848 | else | |
| 849 | # Fallback if pattern doesn't match | |
| 850 | php_version="unknown" | |
| 851 | platform="unknown" | |
| 852 | architecture="unknown" | |
| 853 | configuration="unknown" | |
| 854 | fi | |
| 855 | ||
| 856 | # Try to extract metadata from zip if possible | |
| 857 | # This is more complex with zip files, so we'll use a simpler approach | |
| 858 | # Create a temporary directory | |
| 859 | temp_dir="temp_extract_$RANDOM" | |
| 860 | mkdir -p "$temp_dir" | |
| 861 | ||
| 862 | # Try to extract just the metadata file | |
| 863 | unzip -q -j "$zipfile" "*/metadata.json" -d "$temp_dir" 2>/dev/null || echo '{}' > "$temp_dir/metadata.json" | |
| 864 | ||
| 865 | # Create JSON object for this binary | |
| 866 | binary_json=$(jq -n \ | |
| 867 | --arg filename "$filename" \ | |
| 868 | --arg size "$size" \ | |
| 869 | --arg php_version "$php_version" \ | |
| 870 | --arg platform "$platform" \ | |
| 871 | --arg architecture "$architecture" \ | |
| 872 | --arg configuration "$configuration" \ | |
| 873 | --arg built_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ | |
| 874 | --arg extensions "$(cat "$temp_dir/metadata.json" | jq -r '.extensions // ""' 2>/dev/null || echo '')" \ | |
| 875 | '{ | |
| 876 | filename: $filename, | |
| 877 | size: ($size | tonumber), | |
| 878 | php_version: $php_version, | |
| 879 | platform: $platform, | |
| 880 | architecture: $architecture, | |
| 881 | configuration: $configuration, | |
| 882 | built_at: $built_at, | |
| 883 | extensions: $extensions | |
| 884 | }') | |
| 885 | ||
| 886 | # Add this binary to the array using jq | |
| 887 | jq --argjson binary "$binary_json" '. += [$binary]' binaries_array.json > temp_array.json | |
| 888 | mv temp_array.json binaries_array.json | |
| 889 | ||
| 890 | # Clean up temp directory | |
| 891 | rm -rf "$temp_dir" | |
| 892 | done | |
| 893 | ||
| 1119 | 894 | # Create the final manifest with proper structure and sorted binaries |
| 1120 | 895 | jq --arg version "$(date +%Y.%m.%d)" \ |
| 1121 | 896 | --arg built_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ |
| @@ -1135,7 +910,9 @@ jobs: | ||
| 1135 | 910 | cat manifest.json |
| 1136 | 911 | echo "" |
| 1137 | 912 | echo "📊 Summary:" |
| 1138 | echo " - Total binaries found: $(find . -name "*.tar.gz" -type f | wc -l)" | |
| 913 | echo " - Unix binaries found: $(find . -name "*.tar.gz" -type f | wc -l)" | |
| 914 | echo " - Windows binaries found: $(find . -name "*.zip" -type f | wc -l)" | |
| 915 | echo " - Total binaries found: $(find . -name "*.tar.gz" -o -name "*.zip" -type f | wc -l)" | |
| 1139 | 916 | echo " - Manifest file size: $(stat -c%s manifest.json 2>/dev/null || stat -f%z manifest.json) bytes" |
| 1140 | 917 | |
| 1141 | 918 | - name: Create GitHub Release |
| @@ -1148,7 +925,7 @@ jobs: | ||
| 1148 | 925 | |
| 1149 | 926 | > This release contains precompiled PHP binaries optimized for modern PHP usage |
| 1150 | 927 | |
| 1151 | - **Platforms**: Linux (x86_64), macOS (ARM64 & Intel) | |
| 928 | - **Platforms**: Linux (x86_64), macOS (ARM64 & Intel), Windows (x86_64) | |
| 1152 | 929 | - **PHP Versions**: ${{ steps.format-versions.outputs.php_versions_string }} |
| 1153 | 930 | - **Configuration Options**: |
| 1154 | 931 | - `laravel-mysql`: Laravel applications using MySQL or MariaDB |
| @@ -1168,6 +945,7 @@ jobs: | ||
| 1168 | 945 | See `manifest.json` for detailed information about each binary. |
| 1169 | 946 | files: | |
| 1170 | 947 | binaries/**/*.tar.gz |
| 948 | binaries/**/*.zip | |
| 1171 | 949 | binaries/manifest.json |
| 1172 | 950 | draft: false |
| 1173 | 951 | prerelease: false |