Skip to content

Build PHP (macOS)

Build PHP (macOS) #13

Workflow file for this run

name: Build PHP (macOS)
# Required repository secrets (same names as nativephp-php-bin-mobile):
# R2_ACCESS_KEY_ID - Cloudflare R2 access key
# R2_SECRET_ACCESS_KEY - Cloudflare R2 secret key
permissions:
contents: read
on:
schedule:
# Every Friday at midnight UTC (matches the mobile build trigger).
- cron: '0 0 * * 5'
workflow_dispatch:
inputs:
version:
description: 'PHP version to build'
type: choice
options:
- all
- "8.3"
- "8.4"
- "8.5"
default: all
env:
SPC_VERSION: 2.8.5
SPC_BUILD_OS: mac
# Each branch uploads to its own directory: main/, feature-x/, etc.
R2_PREFIX: ${{ format('{0}/', github.ref_name) }}
R2_ENDPOINT: https://713f4e1d515cf082921cdf5122bf1739.r2.cloudflarestorage.com
R2_BUCKET: nativephplibs
jobs:
build:
name: ${{ matrix.version }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON((github.event.inputs.version || 'all') == 'all' && '["8.3","8.4","8.5"]' || format('["{0}"]', github.event.inputs.version)) }}
os: [macos-15-intel, macos-latest]
include:
- os: macos-15-intel
arch: x64
spc_asset: spc-macos-x86_64.tar.gz
- os: macos-latest
arch: arm64
spc_asset: spc-macos-aarch64.tar.gz
steps:
- uses: actions/checkout@v6
- name: Download SPC
shell: bash
run: |
cd ..
curl -fsSL -o spc.tar.gz "https://github.com/crazywhalecc/static-php-cli/releases/download/${SPC_VERSION}/${{ matrix.spc_asset }}"
tar -xzf spc.tar.gz
chmod +x spc
mkdir -p static-php-cli/bin
mv spc static-php-cli/bin/
- name: Install build dependencies
run: brew install automake gzip
- name: Setup system PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
tools: pecl, composer
extensions: curl, openssl, mbstring, sodium, tokenizer, filter
ini-values: memory_limit=-1
- name: SPC doctor
run: |
cd ../static-php-cli
./bin/spc doctor
- name: Read PHP extensions from file
shell: bash
run: |
EXTENSIONS=$(php -r "echo trim(file_get_contents('php-extensions.txt'));")
EXT_HASH=$(php -r "echo md5(getenv('EXTENSIONS'));")
echo "PHP_EXTENSIONS=$EXTENSIONS" >> $GITHUB_ENV
echo "PHP_EXT_HASH=$EXT_HASH" >> $GITHUB_ENV
- name: Read PHP libraries from file
shell: bash
run: |
LIBRARIES=$(php -r "echo trim(file_get_contents('php-libraries.txt'));")
echo "PHP_LIBS=$LIBRARIES" >> $GITHUB_ENV
- id: cache-spc-downloads
uses: actions/cache@v5
with:
path: ../static-php-cli/downloads
key: spc-downloads-${{ env.PHP_EXT_HASH }}
- name: Download PHP extension sources
if: steps.cache-spc-downloads.outputs.cache-hit != 'true'
run: |
cd ../static-php-cli
./bin/spc download --with-php=${{ matrix.version }} --for-extensions "${{ env.PHP_EXTENSIONS }}" --prefer-pre-built
- name: Build PHP
run: |
cd ../static-php-cli
./bin/spc build --build-cli "${{ env.PHP_EXTENSIONS }}" --with-libs="${{ env.PHP_LIBS }}" --debug
- name: Get built PHP version
shell: bash
run: |
PHP_VERSION_FULL=$(../static-php-cli/buildroot/bin/php -r "echo PHP_VERSION;")
echo "PHP_VERSION_FULL=$PHP_VERSION_FULL" >> $GITHUB_ENV
- name: Create bin directories
run: |
mkdir -p bin/${{ env.SPC_BUILD_OS }}/${{ matrix.arch }}
mkdir -p license-files
mkdir -p build-meta
- name: Zip PHP binary, copy metadata
shell: bash
run: |
rm -f bin/${{ env.SPC_BUILD_OS }}/${{ matrix.arch }}/php-${{ matrix.version }}.zip
mkdir -p tmp-bin
cp ../static-php-cli/buildroot/bin/php tmp-bin/
cd tmp-bin
zip ../bin/${{ env.SPC_BUILD_OS }}/${{ matrix.arch }}/php-${{ matrix.version }}.zip php
cd ..
rm -rf tmp-bin
cp ../static-php-cli/buildroot/license/* license-files/
cp ../static-php-cli/buildroot/build-extensions.json build-meta/build-extensions-${{ env.SPC_BUILD_OS }}.json
cp ../static-php-cli/buildroot/build-libraries.json build-meta/build-libraries-${{ env.SPC_BUILD_OS }}.json
# Upload the built zip (and a sha256 sidecar) to R2 instead of committing
# it to git. Mirrors nativephp-php-bin-mobile/.github/workflows/build.yml:
# same `aws s3 cp` tooling, R2_* secrets, endpoint and --cache-control.
- name: Upload to R2
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
run: |
ZIP="bin/${SPC_BUILD_OS}/${{ matrix.arch }}/php-${{ matrix.version }}.zip"
DEST="${R2_PREFIX}desktop/${SPC_BUILD_OS}/${{ matrix.arch }}/php-${{ matrix.version }}.zip"
# Compute the checksum and upload it as a sidecar first.
SHA=$(shasum -a 256 "$ZIP" | awk '{print $1}')
echo "$SHA $(basename "$ZIP")" > "$ZIP.sha256"
echo "Uploading $ZIP -> ${DEST} (sha256=$SHA)"
aws s3 cp "$ZIP" "s3://${R2_BUCKET}/${DEST}" \
--endpoint-url "$R2_ENDPOINT" \
--cache-control "public, max-age=31536000, immutable"
aws s3 cp "$ZIP.sha256" "s3://${R2_BUCKET}/${DEST}.sha256" \
--endpoint-url "$R2_ENDPOINT" \
--content-type "text/plain" \
--cache-control "public, max-age=31536000, immutable"
# Regenerate the branch manifest from everything currently in R2. Runs after
# all build jobs; safe because it lists the whole bucket prefix, so it always
# reflects every platform/version actually uploaded (mac, linux, win).
manifest:
needs: build
# Run even if some matrix legs failed, so the manifest still reflects the
# binaries that DID upload. Skip only on cancellation. The generator lists
# the live bucket, so it never references a missing object.
if: always() && needs.build.result != 'cancelled'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Generate and upload versions.json
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
BUCKET: ${{ env.R2_BUCKET }}
BASE_URL: https://bin.nativephp.com
run: |
chmod +x .github/scripts/generate-versions-json.sh
.github/scripts/generate-versions-json.sh > versions.json
echo "versions.json:"
cat versions.json
# Manifest LAST, after every binary it references is already in R2.
aws s3 cp versions.json "s3://${R2_BUCKET}/${R2_PREFIX}desktop/versions.json" \
--endpoint-url "$R2_ENDPOINT" \
--content-type "application/json" \
--cache-control "no-cache, no-store"