Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions .github/actions/build-extension/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'Build PHP Extension'
description: 'Run phpize, configure, and make for the firebird and optional pdo_fbird extensions'
description: 'Run phpize, configure, and make for the firebird and optional pdo_fbird extensions. Out-of-tree build: source is copied to a build directory, keeping the source tree pristine.'
inputs:
firebird-path:
description: 'Path to Firebird client installation'
Expand Down Expand Up @@ -38,7 +38,7 @@ inputs:
required: false
default: ''
phpize-clean:
description: 'Run phpize --clean and remove stale .so files before phpize. Prevents header/library version mismatches when the source tree is shared between containers with different Firebird client versions (e.g. FB 3.0 vs FB 5.0).'
description: 'Run phpize --clean before phpize (in the build directory)'
required: false
default: 'true'
php-bin-dir:
Expand All @@ -53,10 +53,30 @@ inputs:
description: 'Extra paths to prepend to LD_LIBRARY_PATH'
required: false
default: ''
build-dir:
description: 'Directory for out-of-tree build (source is copied here). Set to BUILD_DIR env var for subsequent steps.'
required: false
default: '/tmp/build-firebird'

runs:
using: composite
steps:
- name: Prepare build directory
shell: bash
env:
BUILD_DIR: ${{ inputs.build-dir }}
run: |
# Out-of-tree build: copy source to BUILD_DIR, keep source tree pristine.
# jane: Source tree is NEVER written to. All artifacts (modules/*.so,
# config.h, Makefile, debian/, autom4te.cache/) stay in BUILD_DIR.
# This prevents stale .so between containers (SIGSEGV fix),
# .deb version mismatches, and ensures idempotent builds.
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cp -a . "$BUILD_DIR/"
echo "BUILD_DIR=$BUILD_DIR" >> "$GITHUB_ENV"
echo "Source copied to $BUILD_DIR"

- name: phpize
shell: bash
env:
Expand All @@ -66,20 +86,12 @@ runs:
if [ -n "$PHP_BIN_DIR" ]; then
export PATH="$PHP_BIN_DIR:$PATH"
fi
cd "${BUILD_DIR}"
if [ "$PHPIZE_CLEAN" = 'true' ]; then
# Remove stale .so files BEFORE phpize --clean.
# jane: The /ext directory is a shared bind mount across all Docker
# containers (PHP 8.2-8.5 × FB 3/4/5). If a previous container compiled
# against FB 5.0 headers (FB_API_VER=50) and the current container has
# FB 3.0 (FB_API_VER=30), the stale .so calls IResultSet::close() which
# dispatches through a vtable slot that doesn't exist in FB 3.0's
# libfbclient → NULL function pointer → SIGSEGV during shutdown.
# See: src/cpp/fb_statement.hpp:409 (#if FB_API_VER >= 40 guard).
rm -f modules/firebird.so pdo_fbird/modules/pdo_fbird.so 2>/dev/null || true
phpize --clean
fi
phpize
# Clean .dep files between PHP versions (absolute paths differ)
find . -name '*.dep' -delete 2>/dev/null || true

- name: Configure
Expand All @@ -104,6 +116,8 @@ runs:
export LD_LIBRARY_PATH="$LD_PATH_EXTRA:${LD_LIBRARY_PATH:-}"
fi

cd "${BUILD_DIR}"

ARGS="--with-firebird=$FB_PATH"
if [ "$BUILD_PDO" = 'true' ]; then
ARGS="$ARGS --with-pdo-fbird=$FB_PATH"
Expand Down Expand Up @@ -133,6 +147,7 @@ runs:
env:
PRE_BUILD: ${{ inputs.pre-build-script }}
run: |
cd "${BUILD_DIR}"
eval "$PRE_BUILD"

- name: Build
Expand All @@ -147,4 +162,5 @@ runs:
if [ -n "$LD_PATH_EXTRA" ]; then
export LD_LIBRARY_PATH="$LD_PATH_EXTRA:${LD_LIBRARY_PATH:-}"
fi
cd "${BUILD_DIR}"
make -j"$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)"
15 changes: 10 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,7 @@ jobs:
shell: bash
run: |
set -eu
cd pdo_fbird
# Remove stale .so before phpize (same rationale as build-extension action)
cd "${BUILD_DIR}/pdo_fbird"
rm -f modules/pdo_fbird.so 2>/dev/null || true
phpize --clean
phpize
Expand All @@ -188,7 +187,7 @@ jobs:
uses: ./.github/actions/verify-extension
with:
mode: full
extension-path: modules/firebird.so
extension-path: ${{ env.BUILD_DIR }}/modules/firebird.so
ld-library-path-extra: /opt/firebird-client/lib

- name: Cache Composer dependencies
Expand All @@ -215,11 +214,17 @@ jobs:
env:
NO_INTERACTION: 1
REPORT_EXIT_STATUS: 1
FBIRD_SO: ${{ env.BUILD_DIR }}/modules/firebird.so
run: |
set -eu

EXTENSION_PATH="$(pwd)/modules/firebird.so"
PDO_FBIRD_PATH="$(pwd)/pdo_fbird/modules/pdo_fbird.so"
# jane: run-tests.php is generated by phpize in BUILD_DIR (out-of-tree
# build). Copy it to GITHUB_WORKSPACE so tests run from the source
# tree where vendor/autoload.php and tests/ are located.
cp "${BUILD_DIR}/run-tests.php" .

EXTENSION_PATH="${BUILD_DIR}/modules/firebird.so"
PDO_FBIRD_PATH="${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so"

# Build -d flags: load both extensions explicitly.
# jane: make test only loads the main extension; run-tests.php with
Expand Down
38 changes: 24 additions & 14 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ jobs:
shell: bash
run: |
set -eu
cd pdo_fbird
cd "${BUILD_DIR}/pdo_fbird"
phpize
./configure --with-pdo-fbird --with-firebird=/opt/firebird-client
make -j"$(nproc)"
Expand All @@ -98,7 +98,7 @@ jobs:
uses: ./.github/actions/verify-extension
with:
mode: full
extension-path: modules/firebird.so
extension-path: ${{ env.BUILD_DIR }}/modules/firebird.so
ld-library-path-extra: /opt/firebird-client/lib

- name: Install Composer dependencies
Expand All @@ -116,12 +116,17 @@ jobs:
NO_INTERACTION: 1
REPORT_EXIT_STATUS: 1
TEST_PHP_EXECUTABLE: php
FBIRD_SO: ${{ env.BUILD_DIR }}/modules/firebird.so
shell: bash
run: |
set -euo pipefail

EXTENSION_PATH="$(pwd)/modules/firebird.so"
PDO_FBIRD_PATH="$(pwd)/pdo_fbird/modules/pdo_fbird.so"
# jane: run-tests.php is generated by phpize in BUILD_DIR (out-of-tree
# build). Copy it to GITHUB_WORKSPACE so tests run from the source tree.
cp "${BUILD_DIR}/run-tests.php" .

EXTENSION_PATH="${BUILD_DIR}/modules/firebird.so"
PDO_FBIRD_PATH="${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so"

# Build extension flags - load both firebird and pdo_fbird explicitly.
# Per AGENTS.md: `make test` only loads firebird.so via the Makefile,
Expand Down Expand Up @@ -178,7 +183,12 @@ jobs:
mkdir -p coverage

echo "=== Debug: Listing gcno/gcda files ==="
find . -name "*.gcno" -o -name "*.gcda" 2>/dev/null | head -20 || true
find "${BUILD_DIR}" -name "*.gcno" -o -name "*.gcda" 2>/dev/null | head -20 || true

# jane: coverage data (.gcno/.gcda) is in BUILD_DIR (out-of-tree build).
# Use lcov --directory BUILD_DIR to capture from the correct location.
# Run gcov from BUILD_DIR where source files (.c) and .gcda files are.
cd "${BUILD_DIR}"

# Run gcov on source files
echo "Running gcov on source files..."
Expand All @@ -201,40 +211,40 @@ jobs:

# Capture coverage using lcov
echo "Capturing coverage data with lcov..."
lcov --directory . --capture --output-file coverage/lcov.info \
lcov --directory . --capture --output-file "${GITHUB_WORKSPACE}/coverage/lcov.info" \
--rc lcov_branch_coverage=0 \
--no-external \
--ignore-errors gcov \
2>&1 || true

if [ ! -s coverage/lcov.info ]; then
if [ ! -s "${GITHUB_WORKSPACE}/coverage/lcov.info" ]; then
echo "Warning: No coverage data captured"
echo "TN:" > coverage/lcov.info
echo "TN:" > "${GITHUB_WORKSPACE}/coverage/lcov.info"
fi

# Filter out system headers, PHP headers, and tests
lcov --remove coverage/lcov.info \
lcov --remove "${GITHUB_WORKSPACE}/coverage/lcov.info" \
'/usr/*' \
'*/php-src/*' \
'*/tests/*' \
'*/build/*' \
'*/modules/*' \
--output-file coverage/lcov_filtered.info \
--output-file "${GITHUB_WORKSPACE}/coverage/lcov_filtered.info" \
--rc lcov_branch_coverage=0 \
2>&1 || true

if [ ! -s coverage/lcov_filtered.info ]; then
if [ ! -s "${GITHUB_WORKSPACE}/coverage/lcov_filtered.info" ]; then
echo "Warning: No coverage data after filtering"
echo "TN:" > coverage/lcov_filtered.info
echo "TN:" > "${GITHUB_WORKSPACE}/coverage/lcov_filtered.info"
fi

# Generate HTML report
genhtml coverage/lcov_filtered.info --output-directory coverage/html \
genhtml "${GITHUB_WORKSPACE}/coverage/lcov_filtered.info" --output-directory "${GITHUB_WORKSPACE}/coverage/html" \
--rc lcov_branch_coverage=0 \
2>&1 || true

echo "Coverage summary:"
COVERAGE_OUTPUT=$(lcov --summary coverage/lcov_filtered.info)
COVERAGE_OUTPUT=$(lcov --summary "${GITHUB_WORKSPACE}/coverage/lcov_filtered.info")
echo "$COVERAGE_OUTPUT"

COVERAGE=$(echo "$COVERAGE_OUTPUT" | grep -oP "lines\.*: \K[0-9.]+")
Expand Down
27 changes: 12 additions & 15 deletions .github/workflows/release-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -396,27 +396,24 @@ jobs:
export FB_ROOT=/opt/firebird

# Ensure Firebird libraries are discoverable regardless of PHP_LIBDIR (lib vs lib64)
# config.m4 line 64 uses $PHP_FIREBIRD/$PHP_LIBDIR which may be lib64 on x86_64
# Force lib64 -> lib symlink (remove any pre-existing empty dir from source builds)
rm -rf "${FB_ROOT}/lib64" 2>/dev/null || true
ln -sf lib "${FB_ROOT}/lib64"

# Out-of-tree build: copy source to BUILD_DIR, keep source tree pristine
export BUILD_DIR="/tmp/build-firebird"
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cp -a . "$BUILD_DIR/"
cd "$BUILD_DIR"
echo "BUILD_DIR=$BUILD_DIR" >> $GITHUB_ENV

echo "Building with:"
php -v | head -1
echo "Firebird: ${FB_ROOT}"
echo "BUILD_DIR: ${BUILD_DIR}"

# Clean any previous builds
phpize --clean 2>/dev/null || true

# Build with LTO for optimized release binaries
# LTO is now handled by config.m4 (default: enabled, --disable-fbird-lto to opt out)
# -rpath-link helps the linker resolve DT_NEEDED transitive dependencies
# (e.g. libtommath.so needed by libfbclient.so) during configure link tests
export LDFLAGS="${LDFLAGS:-} -Wl,-rpath-link,${FB_ROOT}/lib"

# musl source-built libfbclient is a C++ library; PHP's configure tests
# link with cc (C compiler) so we must explicitly add -lstdc++ and the
# transitive deps that libfbclient.so DT_NEEDS.
if [ "${{ matrix.libc }}" = "musl" ]; then
export LIBS="-lstdc++ -lm"
echo "musl: added LIBS='${LIBS}' for C++ libfbclient linking"
Expand Down Expand Up @@ -450,13 +447,13 @@ jobs:
echo "FB_ROOT: ${FB_ROOT}"
echo "EXT_VERSION: ${EXT_VERSION}"
ls -la "${FB_ROOT}/lib/" || echo "FB_ROOT/lib not found"
ls -la modules/ || echo "modules/ not found"
ls -la "${BUILD_DIR}/modules/" || echo "modules/ not found"
which patchelf && patchelf --version || echo "patchelf not found"
echo "=== End Debug ==="

# Run build script (skip compilation since already done)
# Run build script (skip compilation since already done in BUILD_DIR)
chmod +x scripts/build-precompiled.sh
bash -x scripts/build-precompiled.sh --skip-build --checksums --verbose \
bash -x scripts/build-precompiled.sh --skip-build --build-dir "${BUILD_DIR}" --checksums --verbose \
"${{ matrix.php }}" "${{ matrix.variant }}" "${{ matrix.arch }}" 2>&1

# Get output filename
Expand Down
18 changes: 12 additions & 6 deletions .github/workflows/release-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,19 @@ jobs:
export PATH="/opt/php/${{ matrix.php }}-${{ matrix.variant }}/bin:${PATH}"
export FB_ROOT=/opt/firebird

# Out-of-tree build: copy source to BUILD_DIR, keep source tree pristine
export BUILD_DIR="/tmp/build-firebird"
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cp -a . "$BUILD_DIR/"
cd "$BUILD_DIR"
echo "BUILD_DIR=$BUILD_DIR" >> $GITHUB_ENV

echo "Building with:"
php -v | head -1
echo "Firebird: ${FB_ROOT}"
echo "BUILD_DIR: ${BUILD_DIR}"

phpize --clean 2>/dev/null || true

# LTO for optimized release binaries
export CFLAGS="${CFLAGS:-} -O2"
export LDFLAGS="${LDFLAGS:-} -L${FB_ROOT}/lib"
phpize
Expand Down Expand Up @@ -266,10 +272,10 @@ jobs:
mkdir -p "${DIST_DIR}/lib"

# Copy extension
cp modules/firebird.so "${DIST_DIR}/firebird.so"
cp "${BUILD_DIR}/modules/firebird.so" "${DIST_DIR}/firebird.so"
# Copy pdo_fbird.so if built
if [ -f pdo_fbird/modules/pdo_fbird.so ]; then
cp pdo_fbird/modules/pdo_fbird.so "${DIST_DIR}/pdo_fbird.so"
if [ -f "${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so" ]; then
cp "${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so" "${DIST_DIR}/pdo_fbird.so"
fi

# Bundle libfbclient.dylib and its dependencies
Expand Down
Loading
Loading