diff --git a/.github/actions/build-extension/action.yml b/.github/actions/build-extension/action.yml index f93e8632..57dab90b 100644 --- a/.github/actions/build-extension/action.yml +++ b/.github/actions/build-extension/action.yml @@ -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' @@ -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: @@ -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: @@ -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 @@ -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" @@ -133,6 +147,7 @@ runs: env: PRE_BUILD: ${{ inputs.pre-build-script }} run: | + cd "${BUILD_DIR}" eval "$PRE_BUILD" - name: Build @@ -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)" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc7f99d3..a8525d4b 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 @@ -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 @@ -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 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e634a4a3..59a010b4 100755 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -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)" @@ -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 @@ -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, @@ -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..." @@ -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.]+") diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 6ccf6b48..e4a55121 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -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" @@ -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 diff --git a/.github/workflows/release-macos.yml b/.github/workflows/release-macos.yml index d7623d14..c910ce5d 100644 --- a/.github/workflows/release-macos.yml +++ b/.github/workflows/release-macos.yml @@ -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 @@ -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 diff --git a/.github/workflows/sanitizers.yml b/.github/workflows/sanitizers.yml index 3e9caf7c..66efe7f5 100755 --- a/.github/workflows/sanitizers.yml +++ b/.github/workflows/sanitizers.yml @@ -87,7 +87,7 @@ jobs: export CFLAGS="-I/opt/firebird-client/include ${SANITIZE_FLAGS}" export CXXFLAGS="-I/opt/firebird-client/include ${SANITIZE_FLAGS}" export LDFLAGS="-L/opt/firebird-client/lib -fsanitize=address,undefined" - cd pdo_fbird + cd "${BUILD_DIR}/pdo_fbird" phpize ./configure --with-pdo-fbird --with-firebird=/opt/firebird-client make -j"$(nproc)" @@ -97,7 +97,7 @@ jobs: uses: ./.github/actions/verify-extension with: mode: build-only - extension-path: modules/firebird.so + extension-path: ${{ env.BUILD_DIR }}/modules/firebird.so ld-library-path-extra: /opt/firebird-client/lib sanitizer-type: asan @@ -209,7 +209,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: Create LSan suppressions file @@ -246,18 +246,23 @@ jobs: NO_INTERACTION: 1 REPORT_EXIT_STATUS: 1 TEST_PHP_EXECUTABLE: php + FBIRD_SO: ${{ env.BUILD_DIR }}/modules/firebird.so run: | set -eu export LD_LIBRARY_PATH="/opt/firebird-client/lib:${LD_LIBRARY_PATH:-}" + # 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" . + # Note: Standalone LSan (-fsanitize=leak) links directly into the extension # No LD_PRELOAD needed (unlike ASan which needs runtime library preloading) echo "=== Running tests with LeakSanitizer ===" - EXTENSION_PATH="$(pwd)/modules/firebird.so" - PDO_FBIRD_PATH="$(pwd)/pdo_fbird/modules/pdo_fbird.so" + EXTENSION_PATH="${BUILD_DIR}/modules/firebird.so" + PDO_FBIRD_PATH="${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so" # Per AGENTS.md: `make test` only loads firebird.so and ignores # PHP_TEST_SHARED_EXTENSIONS, causing ALL pdo_fbird tests to SKIP. @@ -429,7 +434,7 @@ jobs: uses: ./.github/actions/verify-extension with: mode: best-effort - extension-path: modules/firebird.so + extension-path: ${{ env.BUILD_DIR }}/modules/firebird.so ld-library-path-extra: /opt/firebird-client/lib php-bin: /opt/php-tsan/bin/php sanitizer-type: tsan @@ -462,16 +467,21 @@ jobs: env: NO_INTERACTION: 1 REPORT_EXIT_STATUS: 1 + FBIRD_SO: ${{ env.BUILD_DIR }}/modules/firebird.so run: | set -eu export PATH="/opt/php-tsan/bin:$PATH" export LD_LIBRARY_PATH="/opt/firebird-client/lib:/usr/lib:${LD_LIBRARY_PATH:-}" + # 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" . + echo "=== Running tests with ThreadSanitizer (ZTS) ===" - EXTENSION_PATH="$(pwd)/modules/firebird.so" - PDO_FBIRD_PATH="$(pwd)/pdo_fbird/modules/pdo_fbird.so" + EXTENSION_PATH="${BUILD_DIR}/modules/firebird.so" + PDO_FBIRD_PATH="${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so" # Per AGENTS.md: `make test` only loads firebird.so and ignores # PHP_TEST_SHARED_EXTENSIONS, causing ALL pdo_fbird tests to SKIP. diff --git a/packaging/debian/build-matrix.sh b/packaging/debian/build-matrix.sh index a8d2bc3a..f8d7a1af 100755 --- a/packaging/debian/build-matrix.sh +++ b/packaging/debian/build-matrix.sh @@ -207,9 +207,15 @@ build_package() { local fb_vol="" [ -d "$fb_host_dir" ] && fb_vol="-v ${fb_host_dir}:${fb_mount}" + # Out-of-tree build: source mounted READ-ONLY, build happens in /build (ephemeral) + # jane: No Docker volume for /build — the container is --rm, so /build is + # automatically cleaned when the container exits. The source tree at /src + # is never written to. + local build_dir="/build" + docker run --rm \ --platform "$platform" \ - -v "${REPO_ROOT}:/ext" \ + -v "${REPO_ROOT}:/src:ro" \ -v "${abs_output}:/output" \ $fb_vol \ -e PHP_VERSION="$php_ver" \ @@ -217,6 +223,8 @@ build_package() { -e ARCH="$arch" \ -e OUTPUT_DIR="/output" \ -e FB_ROOT="${fb_mount}" \ + -e BUILD_DIR="${build_dir}" \ + -e SOURCE_DIR="/src" \ "$docker_image" \ bash -c "export DEBIAN_FRONTEND=noninteractive && \ $(if [ "$(is_ubuntu "$distro")" = "true" ]; then @@ -224,7 +232,11 @@ build_package() { apt-get install -y -qq lsb-release ca-certificates curl && \ curl -sSLo /tmp/keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb && \ dpkg -i /tmp/keyring.deb && \ - printf 'Types: deb\nURIs: https://packages.sury.org/php/\nSuites: \$(lsb_release -sc)\nComponents: main\nSigned-By: /usr/share/keyrings/debsuryorg-archive-keyring.gpg\n' > /etc/apt/sources.list.d/php.sources && \ + echo 'Types: deb' > /etc/apt/sources.list.d/php.sources && \ + echo 'URIs: https://packages.sury.org/php/' >> /etc/apt/sources.list.d/php.sources && \ + echo 'Suites: $distro' >> /etc/apt/sources.list.d/php.sources && \ + echo 'Components: main' >> /etc/apt/sources.list.d/php.sources && \ + echo 'Signed-By: /usr/share/keyrings/debsuryorg-archive-keyring.gpg' >> /etc/apt/sources.list.d/php.sources && \ apt-get update -qq && \ apt-get install -y -qq --no-install-recommends \ php${php_ver}-cli php${php_ver}-dev \ @@ -238,7 +250,7 @@ build_package() { libicu-dev libxml2-dev libtommath1 patchelf dpkg-dev debhelper \ jq curl wget git ca-certificates &&" fi) \ - cd /ext && bash packaging/debian/build.sh --php-version $php_ver --distro $distro --arch $arch --output-dir /output" \ + bash /src/packaging/debian/build.sh --php-version $php_ver --distro $distro --arch $arch --output-dir /output --build-dir ${build_dir}" \ > "$result_log" 2>&1 || exit_code=$? if [ $exit_code -eq 0 ]; then diff --git a/packaging/debian/build.sh b/packaging/debian/build.sh index e65b0e4e..79b02852 100755 --- a/packaging/debian/build.sh +++ b/packaging/debian/build.sh @@ -34,6 +34,7 @@ DISTRO="bookworm" ARCH="x86_64" FB_ROOT="${FB_ROOT:-/opt/firebird}" OUTPUT_DIR="${OUTPUT_DIR:-dist/deb}" +BUILD_DIR="${BUILD_DIR:-}" VERBOSE=0 # ----------------------------------------------------------------------------- @@ -64,6 +65,8 @@ while [ $# -gt 0 ]; do --output-dir) OUTPUT_DIR="$2"; shift 2 ;; --output-dir=*) OUTPUT_DIR="${1#--output-dir=}"; shift ;; --verbose|-v) VERBOSE=1; shift ;; + --build-dir) BUILD_DIR="$2"; shift 2 ;; + --build-dir=*) BUILD_DIR="${1#--build-dir=}"; shift ;; --help|-h) usage ;; *) echo "ERROR: Unknown argument: $1" >&2; exit 1 ;; esac @@ -102,7 +105,22 @@ log "Using: $PHPIZE, $PHPCONFIG" # ----------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SOURCE_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" + +# Out-of-tree build: if BUILD_DIR is set, copy source there and work from it. +# jane: REPO_ROOT is repointed to BUILD_DIR so all cd "$REPO_ROOT" calls and +# packaging/debian/* path references resolve to the build copy, not the +# read-only source. This prevents build artifacts from polluting the source +# tree and fixes .deb version mismatches (stale debian/changelog template). +if [ -n "$BUILD_DIR" ] && [ "$BUILD_DIR" != "$SOURCE_ROOT" ]; then + log_info "Out-of-tree build: copying source to ${BUILD_DIR}" + mkdir -p "$BUILD_DIR" + rm -rf "${BUILD_DIR}"/* "${BUILD_DIR}"/.[!.]* 2>/dev/null || true + cp -a "$SOURCE_ROOT"/* "$BUILD_DIR/" + REPO_ROOT="$BUILD_DIR" +else + REPO_ROOT="$SOURCE_ROOT" +fi cd "$REPO_ROOT" # ----------------------------------------------------------------------------- @@ -349,18 +367,23 @@ dpkg-buildpackage -us -uc -b -d 2>&1 || { # Step 6: Find and report the .deb file # ----------------------------------------------------------------------------- -# dpkg-buildpackage puts the .deb in the parent directory -DEB_FILE=$(find "${REPO_ROOT}/.." -name "php${PHP_VERSION}-firebird_*.deb" -type f | head -n 1) +# dpkg-buildpackage puts the .deb in the parent directory of REPO_ROOT. +# jane: -maxdepth 1 is critical - without it, find searches the ENTIRE +# filesystem (including /src/dist/ which has stale .deb files from previous +# test runs). head -n 1 would pick the stale 13.0.0-1 file instead of the +# freshly built 13.0.1-rc.1-1 file. ! -name "*dbgsym*" excludes debug symbol +# packages that dpkg-buildpackage also produces. +DEB_FILE=$(find "${REPO_ROOT}/.." -maxdepth 1 -name "php${PHP_VERSION}-firebird_*.deb" -type f ! -name "*dbgsym*" | head -n 1) if [ -z "$DEB_FILE" ]; then - # Fallback: search in current directory - DEB_FILE=$(find . -name "php${PHP_VERSION}-firebird_*.deb" -type f | head -n 1) + # Fallback: search in current directory (same constraints) + DEB_FILE=$(find . -maxdepth 1 -name "php${PHP_VERSION}-firebird_*.deb" -type f ! -name "*dbgsym*" | head -n 1) fi if [ -z "$DEB_FILE" ]; then log_error "No .deb file found after build" log_error "Searching for any .deb files..." - find "${REPO_ROOT}/.." . -name "*.deb" -type f 2>/dev/null | head -10 + find "${REPO_ROOT}/.." -maxdepth 1 -name "*.deb" -type f ! -name "*dbgsym*" 2>/dev/null | head -10 exit 1 fi diff --git a/scripts/build-precompiled.sh b/scripts/build-precompiled.sh index 4dbd8078..9f46c7a5 100755 --- a/scripts/build-precompiled.sh +++ b/scripts/build-precompiled.sh @@ -50,6 +50,7 @@ SKIP_BUILD=false GENERATE_CHECKSUMS=true VERBOSE=0 RUN_VERIFY=false +BUILD_DIR="${BUILD_DIR:-}" # Set via --build-dir or env var; empty = current dir # Auto-detect platform case "$(uname -s)" in @@ -356,6 +357,14 @@ while [[ $# -gt 0 ]]; do RUN_VERIFY=true shift ;; + --build-dir) + BUILD_DIR="$2" + shift 2 + ;; + --build-dir=*) + BUILD_DIR="${1#--build-dir=}" + shift + ;; --help|-h) usage ;; @@ -385,6 +394,15 @@ PHP_VERSION="${PHP_VERSION:-8.4}" VARIANT="${VARIANT:-nts}" ARCH="${ARCH:-x86_64}" +# Resolve BUILD_DIR: if set, .so files are there; otherwise current directory +if [ -n "$BUILD_DIR" ]; then + FIREBIRD_SO="${BUILD_DIR}/modules/firebird.so" + PDO_FBIRD_SO="${BUILD_DIR}/pdo_fbird/modules/pdo_fbird.so" +else + FIREBIRD_SO="modules/firebird.so" + PDO_FBIRD_SO="pdo_fbird/modules/pdo_fbird.so" +fi + # ============================================================================= # Distribution Naming # ============================================================================= @@ -482,8 +500,8 @@ if [ "$SKIP_BUILD" = false ]; then fi # Verify build -if [ "$DRY_RUN" = 0 ] && [ ! -f "modules/firebird.so" ]; then - log_error "Build failed - modules/firebird.so not found" +if [ "$DRY_RUN" = 0 ] && [ ! -f "$FIREBIRD_SO" ]; then + log_error "Build failed - $FIREBIRD_SO not found" exit 1 fi @@ -505,12 +523,12 @@ fi log_info "Copying extension..." if [ "$DRY_RUN" = 1 ]; then - log_dry_run "Would copy: modules/firebird.so -> ${DIST_DIR}/" + log_dry_run "Would copy: $FIREBIRD_SO -> ${DIST_DIR}/" else - cp modules/firebird.so "${DIST_DIR}/" - # Copy pdo_fbird.so if it was built as a separate extension - if [ -f pdo_fbird/modules/pdo_fbird.so ]; then - cp pdo_fbird/modules/pdo_fbird.so "${DIST_DIR}/" + cp "$FIREBIRD_SO" "${DIST_DIR}/" + # Copy pdo_fbird.so if built + if [ -f "$PDO_FBIRD_SO" ]; then + cp "$PDO_FBIRD_SO" "${DIST_DIR}/" log_info "Copied pdo_fbird.so" fi fi diff --git a/tests/fbird_event_live_001.phpt b/tests/fbird_event_live_001.phpt index 4617368e..2558ebbc 100644 --- a/tests/fbird_event_live_001.phpt +++ b/tests/fbird_event_live_001.phpt @@ -45,7 +45,7 @@ var_dump($event instanceof \Firebird\Event || is_resource($event)); // Spawn child process to insert (fires trigger on commit) $child = proc_open( - ['php', '-d', 'extension=' . realpath('modules/firebird.so')], + ['php', '-d', 'extension=' . (getenv('FBIRD_SO') ?: realpath('modules/firebird.so'))], [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes ); @@ -85,7 +85,7 @@ $cmd2 = sprintf( ); $child2 = proc_open( - ['php', '-d', 'extension=' . realpath('modules/firebird.so')], + ['php', '-d', 'extension=' . (getenv('FBIRD_SO') ?: realpath('modules/firebird.so'))], [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes2 ); diff --git a/tests/oop_event_methods_001.phpt b/tests/oop_event_methods_001.phpt index 48b48d7a..33ca755e 100644 --- a/tests/oop_event_methods_001.phpt +++ b/tests/oop_event_methods_001.phpt @@ -40,7 +40,7 @@ $cmd = sprintf( ); $child = proc_open( - ['php', '-d', 'extension=' . realpath('modules/firebird.so')], + ['php', '-d', 'extension=' . (getenv('FBIRD_SO') ?: realpath('modules/firebird.so'))], [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes );