diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 654171b..00e26ae 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,5 +1,5 @@
{
- "name": "colopl_bc: Pskel (for Codespaces)",
+ "name": "colopl_bc: Pskel",
"customizations": {
"vscode": {
"extensions": [
@@ -7,10 +7,17 @@
"ms-vscode.cpptools-extension-pack",
"maelvalais.autoconf",
"ms-azuretools.vscode-docker",
- "editorconfig.editorconfig"
+ "editorconfig.editorconfig",
+ "markis.code-coverage"
]
}
},
"dockerComposeFile": "./../compose.yaml",
- "service": "shell"
+ "service": "shell",
+ "mounts": [
+ "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
+ ],
+ "workspaceFolder": "/workspace",
+ "initializeCommand": "git submodule update --init --recursive",
+ "postCreateCommand": "ln -sf \"$(pwd)/pskel.sh\" /usr/local/bin/pskel"
}
diff --git a/.devcontainer/local/devcontainer.json b/.devcontainer/local/devcontainer.json
deleted file mode 100644
index 0e35acf..0000000
--- a/.devcontainer/local/devcontainer.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "colopl_bc: Pskel (for Local)",
- "customizations": {
- "vscode": {
- "extensions": [
- "ms-vscode.cpptools",
- "ms-vscode.cpptools-extension-pack",
- "maelvalais.autoconf",
- "ms-azuretools.vscode-docker",
- "editorconfig.editorconfig"
- ]
- }
- },
- "dockerComposeFile": "./../../compose.yaml",
- "service": "shell",
- "mounts": [
- "source=${localWorkspaceFolder},target=/workspaces/pskel,type=bind,consistency=cached"
- ],
- "workspaceFolder": "/workspaces/pskel"
-}
diff --git a/.gitattributes b/.gitattributes
index 43bc10e..e12ef0c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,15 +1,21 @@
# Exclude non-essential files from git archive (used by PIE/Composer downloads)
-/.github/ export-ignore
-/build/ export-ignore
-/patches/ export-ignore
-/tests/ export-ignore
-/third_party/ export-ignore
-/ext/tests/ export-ignore
+# Exclude devcontainer and editor metadata from git archive
+/.devcontainer/ export-ignore
+/.dockerignore export-ignore
+/.editorconfig export-ignore
+/.github/ export-ignore
+/.gitmodules export-ignore
+/.vscode/ export-ignore
+/build/ export-ignore
+/patches/ export-ignore
+/tests/ export-ignore
+/third_party/ export-ignore
+/ext/tests/ export-ignore
/ext/description-pak export-ignore
-Dockerfile export-ignore
-compose.yaml export-ignore
-library_test.sh export-ignore
-phpstan.neon export-ignore
-phpunit.xml export-ignore
-pskel.sh export-ignore
-CHANGELOG.md export-ignore
+Dockerfile export-ignore
+compose.yaml export-ignore
+library_test.sh export-ignore
+phpstan.neon export-ignore
+phpunit.xml export-ignore
+pskel.sh export-ignore
+CHANGELOG.md export-ignore
diff --git a/.github/workflows/ci_coverage.yaml b/.github/workflows/ci_coverage.yaml
index 466259a..1817e7d 100644
--- a/.github/workflows/ci_coverage.yaml
+++ b/.github/workflows/ci_coverage.yaml
@@ -93,6 +93,16 @@ jobs:
touch "lcov.info"
docker compose run -v "$(pwd)/lcov.info:/ext/lcov.info" --rm shell pskel coverage
mv "lcov.info" "${{ matrix.platform }}_${{ matrix.versions }}_${{ matrix.ts }}_lcov.info"
+ - name: Verify shard function coverage records
+ run: |
+ COVERAGE_FILE="${{ matrix.platform }}_${{ matrix.versions }}_${{ matrix.ts }}_lcov.info"
+ for RECORD in "FN:" "FNDA:" "FNF:" "FNH:"; do
+ if ! grep -q "^${RECORD}" "${COVERAGE_FILE}"; then
+ echo "Missing ${RECORD} records in ${COVERAGE_FILE}"
+ exit 1
+ fi
+ done
+ lcov --summary "${COVERAGE_FILE}"
- name: Upload coverage artifact
uses: actions/upload-artifact@v7
with:
@@ -137,6 +147,24 @@ jobs:
with:
name: initialized-ext-coverage
path: ext/
+ - name: Verify downloaded function coverage records
+ run: |
+ cd "coverage-files" || exit 1
+ set -- ./*.info
+ if test "${1}" = "./*.info"; then
+ echo "No coverage .info files found"
+ exit 1
+ fi
+ for INFO_FILE in "$@"; do
+ for RECORD in "FN:" "FNDA:" "FNF:" "FNH:"; do
+ if ! grep -q "^${RECORD}" "${INFO_FILE}"; then
+ echo "Missing ${RECORD} records in ${INFO_FILE} before merge"
+ exit 1
+ fi
+ done
+ lcov --summary "${INFO_FILE}"
+ done
+ cd - || exit 1
- name: Generate integrated HTML coverage reports
run: |
if ! test -d "/ext"; then
@@ -165,6 +193,15 @@ jobs:
genhtml "total.info" \
--output-directory "coverage-html" \
--title "Extension code coverage"
+ - name: Verify merged function coverage records
+ run: |
+ for RECORD in "FN:" "FNDA:" "FNF:" "FNH:"; do
+ if ! grep -q "^${RECORD}" "total.info"; then
+ echo "Missing ${RECORD} records in total.info after merge"
+ exit 1
+ fi
+ done
+ lcov --summary "total.info"
- name: Setup Pages
uses: actions/configure-pages@v6
- name: Upload Pages artifact
diff --git a/.github/workflows/ci_emulated_linux.yaml b/.github/workflows/ci_emulated_linux.yaml
index 979b21d..a0fe59d 100644
--- a/.github/workflows/ci_emulated_linux.yaml
+++ b/.github/workflows/ci_emulated_linux.yaml
@@ -60,7 +60,7 @@ jobs:
- name: Generate image tag
id: image-tag
run: |
- TAG="ghcr.io/${{ github.repository }}/ci-emulated-cache:${{ steps.cut-arch.outputs.arch }}-${{ matrix.version }}-${{ matrix.type }}-${{ matrix.distro }}-${{ hashFiles('**/Dockerfile', '**/compose.yaml', '**/pskel.sh') }}"
+ TAG="ghcr.io/${{ github.repository }}/ci-emulated-cache:${{ steps.cut-arch.outputs.arch }}-${{ matrix.version }}-${{ matrix.type }}-${{ matrix.distro }}-${{ hashFiles('**/Dockerfile', '**/compose.yaml', '**/pskel.sh', '.pskel/**') }}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Check if image exists
id: check-image
diff --git a/.github/workflows/ci_native_linux.yaml b/.github/workflows/ci_native_linux.yaml
index 3b4a454..d4bcb62 100644
--- a/.github/workflows/ci_native_linux.yaml
+++ b/.github/workflows/ci_native_linux.yaml
@@ -62,9 +62,9 @@ jobs:
docker compose build --no-cache --build-arg IMAGE="php" --build-arg TAG="${{ matrix.version }}-${{ matrix.type }}-${{ matrix.distro }}"
- name: Test extension with Bundled PHP
run: docker compose run --rm -v "$(pwd)/php-cache:/opt/php-cache" -e PHP_CACHE_DIR="/opt/php-cache" -e GITHUB_ACTIONS="true" -e CONTAINER_IMAGE_HASH="${{ steps.pull-image.outputs.image_hash }}" shell pskel test
- - name: Test extension with PHP Debug Build
+ - name: Test extension with PHP Debug Build (in-tree static)
if: matrix.version != '8.1'
- run: docker compose run --rm -v "$(pwd)/php-cache:/opt/php-cache" -e PHP_CACHE_DIR="/opt/php-cache" -e GITHUB_ACTIONS="true" -e CONTAINER_IMAGE_HASH="${{ steps.pull-image.outputs.image_hash }}" shell pskel test debug
+ run: docker compose run --rm -v "$(pwd)/php-cache:/opt/php-cache" -e PHP_CACHE_DIR="/opt/php-cache" -e GITHUB_ACTIONS="true" -e CONTAINER_IMAGE_HASH="${{ steps.pull-image.outputs.image_hash }}" shell pskel test debug-static
- name: Test extension with Valgrind
if: matrix.distro != 'alpine' && matrix.version != '8.1'
run: docker compose run --rm -v "$(pwd)/php-cache:/opt/php-cache" -e PHP_CACHE_DIR="/opt/php-cache" -e GITHUB_ACTIONS="true" -e CONTAINER_IMAGE_HASH="${{ steps.pull-image.outputs.image_hash }}" shell pskel test valgrind
diff --git a/.github/workflows/pie_release.yaml b/.github/workflows/pie_release.yaml
deleted file mode 100644
index e64bdb6..0000000
--- a/.github/workflows/pie_release.yaml
+++ /dev/null
@@ -1,119 +0,0 @@
-name: Build and release binaries for PIE
-
-on:
- push:
- tags:
- - '*'
-
-permissions:
- contents: read
-
-jobs:
- CreateDraftRelease:
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - uses: actions/checkout@v6
- with:
- fetch-tags: 'true'
- ref: ${{ github.ref }}
- - name: Create draft release from tag
- env:
- GH_TOKEN: ${{ github.token }}
- run: gh release create "${{ github.ref_name }}" --title "${{ github.ref_name }}" --draft --notes-from-tag
- AddPieBinaries:
- needs: [ CreateDraftRelease ]
- runs-on: ${{ matrix.operating-system }}
- strategy:
- fail-fast: false
- matrix:
- operating-system:
- - ubuntu-latest
- - macos-latest
- php-versions:
- - '8.1'
- - '8.2'
- - '8.3'
- - '8.4'
- - '8.5'
- zts-mode:
- - ts
- - nts
- permissions:
- contents: write
- steps:
- - name: Checkout
- uses: actions/checkout@v6
- - name: Setup PHP
- uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
- with:
- php-version: ${{ matrix.php-versions }}
- env:
- phpts: ${{ matrix.zts-mode }}
- - name: Build and release
- uses: php/pie-ext-binary-builder@5298761950f63c7e9565ed7004e922b346e4386c # 0.0.3
- with:
- release-tag: ${{ github.ref_name }}
- github-token: ${{ secrets.GITHUB_TOKEN }}
- configure-flags: '--enable-colopl_bc'
- build-path: 'ext'
- GetWindowsExtensionMatrix:
- needs: [ CreateDraftRelease ]
- runs-on: ubuntu-latest
- outputs:
- matrix: ${{ steps.extension-matrix.outputs.matrix }}
- steps:
- - name: Checkout
- uses: actions/checkout@v6
- with:
- fetch-depth: 1
- - name: Get the extension matrix
- id: extension-matrix
- uses: php/php-windows-builder/extension-matrix@e03e5d39879adaeb61ed2225f0f4eae7db8c1df8 # 1.8.1
- with:
- php-version-list: '8.1,8.2,8.3,8.4,8.5'
- BuildWindows:
- needs: GetWindowsExtensionMatrix
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix: ${{ fromJson(needs.GetWindowsExtensionMatrix.outputs.matrix) }}
- steps:
- - name: Checkout
- uses: actions/checkout@v6
- with:
- fetch-depth: 1
- # Workaround: php-windows-builder reads config.w32 from repo root,
- # but our extension source is in ext/. Copy ext/* to root so the
- # action can find config.w32 and the source files.
- - name: Copy extension source to root
- shell: pwsh
- run: Copy-Item -Path ext\* -Destination . -Recurse -Force
- - name: Build the extension
- uses: php/php-windows-builder/extension@e03e5d39879adaeb61ed2225f0f4eae7db8c1df8 # 1.8.1
- with:
- php-version: ${{ matrix.php-version }}
- arch: ${{ matrix.arch }}
- ts: ${{ matrix.ts }}
- ReleaseWindows:
- runs-on: ubuntu-latest
- needs: BuildWindows
- permissions:
- contents: write
- steps:
- - name: Upload artifact to the release
- uses: php/php-windows-builder/release@e03e5d39879adaeb61ed2225f0f4eae7db8c1df8 # 1.8.1
- with:
- release: ${{ github.ref_name }}
- token: ${{ secrets.GITHUB_TOKEN }}
- publish-release:
- needs: [ AddPieBinaries, ReleaseWindows ]
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - name: Publish release
- env:
- GH_TOKEN: ${{ github.token }}
- run: gh release edit "${{ github.ref_name }}" --draft=false --repo "${{ github.repository }}"
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..3e31eaa
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,209 @@
+name: Build and release extension artifacts
+
+on:
+ push:
+ tags:
+ - '*'
+
+permissions:
+ contents: read
+
+jobs:
+ CreateDraftRelease:
+ runs-on: ubuntu-latest
+ outputs:
+ package_version: ${{ steps.package-version.outputs.version }}
+ permissions:
+ contents: write
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-tags: 'true'
+ ref: ${{ github.ref }}
+ - name: Normalize package version
+ id: package-version
+ run: echo "version=${GITHUB_REF_NAME#v}" >> "${GITHUB_OUTPUT}"
+ - name: Create draft release from tag
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ if gh release view "${{ github.ref_name }}" >/dev/null 2>&1; then
+ echo "Release already exists: ${{ github.ref_name }}"
+ else
+ gh release create "${{ github.ref_name }}" --title "${{ github.ref_name }}" --draft --notes-from-tag
+ fi
+ BuildDebPackages:
+ needs: [ CreateDraftRelease ]
+ runs-on: ${{ matrix.runs-on }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - runs-on: ubuntu-24.04
+ platform: linux/amd64
+ arch: amd64
+ dockerfile: build/ubuntu2204/Dockerfile
+ image_name: colopl-bc-u2204-php81
+ artifact_name: ubuntu2204-php81-amd64-debs
+ prune_meta_package: false
+ - runs-on: ubuntu-24.04-arm
+ platform: linux/arm64
+ arch: arm64
+ dockerfile: build/ubuntu2204/Dockerfile
+ image_name: colopl-bc-u2204-php81
+ artifact_name: ubuntu2204-php81-arm64-debs
+ prune_meta_package: true
+ - runs-on: ubuntu-24.04
+ platform: linux/amd64
+ arch: amd64
+ dockerfile: build/ubuntu2204_sury84/Dockerfile
+ image_name: colopl-bc-u2204-sury84-php84
+ artifact_name: ubuntu2204-sury84-php84-amd64-debs
+ prune_meta_package: false
+ - runs-on: ubuntu-24.04-arm
+ platform: linux/arm64
+ arch: arm64
+ dockerfile: build/ubuntu2204_sury84/Dockerfile
+ image_name: colopl-bc-u2204-sury84-php84
+ artifact_name: ubuntu2204-sury84-php84-arm64-debs
+ prune_meta_package: false
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ - name: Build package image
+ run: |
+ docker build \
+ --pull \
+ --build-arg PLATFORM="${{ matrix.platform }}" \
+ -f "${{ matrix.dockerfile }}" \
+ -t "${{ matrix.image_name }}:${{ matrix.arch }}" \
+ .
+ - name: Build deb packages
+ run: |
+ mkdir -p "artifacts"
+ docker run --rm \
+ --platform "${{ matrix.platform }}" \
+ -e VERSION="${{ needs.CreateDraftRelease.outputs.package_version }}" \
+ -v "${PWD}/artifacts:/tmp/artifacts" \
+ "${{ matrix.image_name }}:${{ matrix.arch }}"
+ - name: Remove duplicated meta package
+ if: matrix.prune_meta_package
+ run: rm -f artifacts/php-colopl-bc_*_all.deb
+ - name: Upload deb package artifacts
+ uses: actions/upload-artifact@v7
+ with:
+ name: ${{ matrix.artifact_name }}
+ path: artifacts/*
+ if-no-files-found: error
+ retention-days: 1
+ AddPieBinaries:
+ needs: [ CreateDraftRelease ]
+ runs-on: ${{ matrix.operating-system }}
+ strategy:
+ fail-fast: false
+ matrix:
+ operating-system:
+ - ubuntu-latest
+ - macos-latest
+ php-versions:
+ - '8.1'
+ - '8.2'
+ - '8.3'
+ - '8.4'
+ - '8.5'
+ zts-mode:
+ - ts
+ - nts
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ - name: Setup PHP
+ uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
+ with:
+ php-version: ${{ matrix.php-versions }}
+ env:
+ phpts: ${{ matrix.zts-mode }}
+ - name: Build and release
+ uses: php/pie-ext-binary-builder@5298761950f63c7e9565ed7004e922b346e4386c # 0.0.3
+ with:
+ release-tag: ${{ github.ref_name }}
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ configure-flags: '--enable-colopl_bc'
+ build-path: 'ext'
+ GetWindowsExtensionMatrix:
+ needs: [ CreateDraftRelease ]
+ runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.extension-matrix.outputs.matrix }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 1
+ - name: Get the extension matrix
+ id: extension-matrix
+ uses: php/php-windows-builder/extension-matrix@e03e5d39879adaeb61ed2225f0f4eae7db8c1df8 # 1.8.1
+ with:
+ php-version-list: '8.1,8.2,8.3,8.4,8.5'
+ BuildWindows:
+ needs: GetWindowsExtensionMatrix
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix: ${{ fromJson(needs.GetWindowsExtensionMatrix.outputs.matrix) }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 1
+ # Workaround: php-windows-builder reads config.w32 from repo root,
+ # but our extension source is in ext/. Copy ext/* to root so the
+ # action can find config.w32 and the source files.
+ - name: Copy extension source to root
+ shell: pwsh
+ run: Copy-Item -Path ext\* -Destination . -Recurse -Force
+ - name: Build the extension
+ uses: php/php-windows-builder/extension@e03e5d39879adaeb61ed2225f0f4eae7db8c1df8 # 1.8.1
+ with:
+ php-version: ${{ matrix.php-version }}
+ arch: ${{ matrix.arch }}
+ ts: ${{ matrix.ts }}
+ ReleaseWindows:
+ runs-on: ubuntu-latest
+ needs: BuildWindows
+ permissions:
+ contents: write
+ steps:
+ - name: Upload artifact to the release
+ uses: php/php-windows-builder/release@e03e5d39879adaeb61ed2225f0f4eae7db8c1df8 # 1.8.1
+ with:
+ release: ${{ github.ref_name }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+ ReleaseDebPackages:
+ runs-on: ubuntu-latest
+ needs: BuildDebPackages
+ permissions:
+ contents: write
+ steps:
+ - name: Download deb package artifacts
+ uses: actions/download-artifact@v8
+ with:
+ pattern: '*-debs'
+ path: deb-artifacts
+ merge-multiple: true
+ - name: Upload deb packages to the release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: gh release upload "${{ github.ref_name }}" deb-artifacts/* --clobber
+ PublishRelease:
+ needs: [ AddPieBinaries, ReleaseWindows, ReleaseDebPackages ]
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Publish release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: gh release edit "${{ github.ref_name }}" --draft=false --repo "${{ github.repository }}"
diff --git a/.gitignore b/.gitignore
index 6b74b10..dde4b98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,9 @@
/ext/*~
/vendor
/artifacts
+/.idea
*.DS_Store
lcov.info
+.phpunit.cache
.phpunit.result.cache
composer.lock
diff --git a/.gitmodules b/.gitmodules
index 1c917d9..e34b3b3 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,5 @@
[submodule "third_party/valgrind"]
path = third_party/valgrind
url = https://sourceware.org/git/valgrind.git
+ branch = VALGRIND_3_27_0
+
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b8..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 8bcca30..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 7d33487..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/php-colopl_bc.iml b/.idea/php-colopl_bc.iml
deleted file mode 100644
index 43c9694..0000000
--- a/.idea/php-colopl_bc.iml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/php.xml b/.idea/php.xml
deleted file mode 100644
index 817548c..0000000
--- a/.idea/php.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/phpunit.xml b/.idea/phpunit.xml
deleted file mode 100644
index 4f8104c..0000000
--- a/.idea/phpunit.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.pskel/LICENSE.template b/.pskel/LICENSE.template
new file mode 100644
index 0000000..b043d7a
--- /dev/null
+++ b/.pskel/LICENSE.template
@@ -0,0 +1,26 @@
+Copyright (c) %YEAR% %VENDOR%
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04abb0f..ca5d1af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,14 @@
-# 11.1.0
+# 12.1.0
+- Change the project license from PHP-3.01 to BSD-3-Clause
+- Tighten package support to PHP 7.4 or PHP 8.1+
+- Refactor internals toward PHP 8.1+ APIs
+- Replace checkinstall-based Ubuntu 22.04 packaging with standard Debian package builds
+- Restore tag-triggered GitHub Actions builds for Ubuntu 22.04 deb packages
+- Fix in-source build on PHP 8.5 and later (#70)
+- Improve `.deb` build from upstream method (#18)
+- Official support for PIE
+
+# 11.1.0
- Add Windows and macOS support
- Bump Pskel 2.0.0
- Fix SEGV on date_create, date_create_immutable (#30, https://github.com/colopl/php-colopl_bc/issues/30)
diff --git a/Dockerfile b/Dockerfile
index 9fe1358..160cec3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -15,34 +15,33 @@ ENV LC_ALL="C"
RUN docker-php-source extract \
&& if test -f "/etc/debian_version"; then \
- apt-get update \
- && DEBIAN_FRONTEND="noninteractive" apt-get install -y "bison" "re2c" "zlib1g-dev" "libsqlite3-dev" "libxml2-dev" \
+ apt-get update && \
+ DEBIAN_FRONTEND="noninteractive" apt-get install -y "bison" "re2c" "zlib1g-dev" "libsqlite3-dev" "libxml2-dev" \
"autoconf" "pkg-config" "make" "gcc" "rsync" "git" "ssh" "libc6-dbg" \
- "ca-certificates" "tzdata" "lsb-release" "curl" \
+ "ca-certificates" "tzdata" "curl" "gnupg" \
"lcov" "gzip" \
"vim" \
"unzip" && \
if test "${ENABLE_CLANG}" = "1"; then \
- # fixme: re-enable keyring usage when SHA256 key is available
- # apt-get --no-install-recommends -y "gnupg" && \
- # curl -sSL "https://apt.llvm.org/llvm-snapshot.gpg.key" | gpg --dearmor > "/usr/share/keyrings/llvm-archive-keyring.gpg" && \
- echo "deb [trusted=yes] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs) main" > "/etc/apt/sources.list.d/llvm.list" && \
- echo "deb [trusted=yes] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-21 main" >> "/etc/apt/sources.list.d/llvm.list" && \
+ LLVM_APT_CODENAME="$(. "/etc/os-release" && printf '%s' "${VERSION_CODENAME}")" && \
+ test -n "${LLVM_APT_CODENAME}" && \
+ mkdir -p "/usr/share/keyrings" && \
+ curl -fsSL "https://apt.llvm.org/llvm-snapshot.gpg.key" | gpg --dearmor --yes -o "/usr/share/keyrings/llvm-snapshot.gpg" && \
+ echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] https://apt.llvm.org/${LLVM_APT_CODENAME}/ llvm-toolchain-${LLVM_APT_CODENAME}-22 main" > "/etc/apt/sources.list.d/llvm.list" && \
apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y \
- "clang-21" "clang-tools-21" "clang-format-21" "clang-tidy-21" \
- "libclang-rt-21-dev" "lld-21" "lldb-21" \
- "libc++-21-dev" "libc++abi-21-dev" \
- "llvm-21" "llvm-21-dev" "llvm-21-runtime" \
- "clang-format-21" && \
- update-alternatives --install "/usr/bin/clang" clang "/usr/bin/clang-21" 100 && \
- update-alternatives --install "/usr/bin/clang++" clang++ "/usr/bin/clang++-21" 100 && \
- update-alternatives --install "/usr/bin/clang-format" clang-format "/usr/bin/clang-format-21" 100 && \
- update-alternatives --install "/usr/bin/clang-tidy" clang-tidy "/usr/bin/clang-tidy-21" 100 && \
- update-alternatives --install "/usr/bin/lldb" lldb "/usr/bin/lldb-21" 100 && \
- update-alternatives --install "/usr/bin/ld.lld" ld.lld "/usr/bin/ld.lld-21" 100 && \
- update-alternatives --install "/usr/bin/llvm-symbolizer" llvm-symbolizer "/usr/bin/llvm-symbolizer-21" 100 && \
- update-alternatives --install "/usr/bin/llvm-config" llvm-config "/usr/bin/llvm-config-21" 100; \
+ "clang-22" "clang-tools-22" "clang-format-22" "clang-tidy-22" \
+ "libclang-rt-22-dev" "lld-22" "lldb-22" \
+ "libc++-22-dev" "libc++abi-22-dev" \
+ "llvm-22" "llvm-22-dev" "llvm-22-runtime" && \
+ update-alternatives --install "/usr/bin/clang" clang "/usr/bin/clang-22" 100 && \
+ update-alternatives --install "/usr/bin/clang++" clang++ "/usr/bin/clang++-22" 100 && \
+ update-alternatives --install "/usr/bin/clang-format" clang-format "/usr/bin/clang-format-22" 100 && \
+ update-alternatives --install "/usr/bin/clang-tidy" clang-tidy "/usr/bin/clang-tidy-22" 100 && \
+ update-alternatives --install "/usr/bin/lldb" lldb "/usr/bin/lldb-22" 100 && \
+ update-alternatives --install "/usr/bin/ld.lld" ld.lld "/usr/bin/ld.lld-22" 100 && \
+ update-alternatives --install "/usr/bin/llvm-symbolizer" llvm-symbolizer "/usr/bin/llvm-symbolizer-22" 100 && \
+ update-alternatives --install "/usr/bin/llvm-config" llvm-config "/usr/bin/llvm-config-22" 100; \
fi; \
else \
apk add --no-cache "bison" "zlib-dev" "sqlite-dev" "libxml2-dev" "linux-headers" \
@@ -57,6 +56,10 @@ COPY ./third_party/valgrind "/third_party/valgrind"
ARG SKIP_VALGRIND
RUN if test "${SKIP_VALGRIND}" != "1" && test -f "/etc/debian_version"; then \
cd "/third_party/valgrind" && \
+ test -x "./autogen.sh" || { \
+ echo "Valgrind submodule is missing. Run 'git submodule update --init --recursive' before building the container." >&2; \
+ exit 1; \
+ } && \
if test -f "/etc/debian_version"; then \
apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y \
@@ -73,11 +76,13 @@ RUN if test "${SKIP_VALGRIND}" != "1" && test -f "/etc/debian_version"; then \
cd -; \
fi
-COPY ./pskel.sh "/usr/local/bin/pskel"
+COPY ./.pskel "/opt/pskel/.pskel"
+COPY ./pskel.sh "/opt/pskel/pskel.sh"
COPY ./patches "/patches"
COPY ./ext "/ext"
-RUN chmod +x "/usr/local/bin/pskel"
+RUN chmod +x "/opt/pskel/pskel.sh" \
+ && ln -sf "/opt/pskel/pskel.sh" "/usr/local/bin/pskel"
RUN cat <<'EOF' > "/usr/local/bin/docker-entrypoint.sh"
#!/bin/sh
diff --git a/LICENSE b/LICENSE
index 4076fe9..74b9886 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,68 +1,29 @@
---------------------------------------------------------------------
- The PHP License, version 3.01
-Copyright (c) 1999 - 2019 The PHP Group. All rights reserved.
---------------------------------------------------------------------
+BSD 3-Clause License
-Redistribution and use in source and binary forms, with or without
-modification, is permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- 3. The name "PHP" must not be used to endorse or promote products
- derived from this software without prior written permission. For
- written permission, please contact group@php.net.
-
- 4. Products derived from this software may not be called "PHP", nor
- may "PHP" appear in their name, without prior written permission
- from group@php.net. You may indicate that your software works in
- conjunction with PHP by saying "Foo for PHP" instead of calling
- it "PHP Foo" or "phpfoo"
-
- 5. The PHP Group may publish revised and/or new versions of the
- license from time to time. Each version will be given a
- distinguishing version number.
- Once covered code has been published under a particular version
- of the license, you may always continue to use it under the terms
- of that version. You may also choose to use such covered code
- under the terms of any subsequent version of the license
- published by the PHP Group. No one other than the PHP Group has
- the right to modify the terms applicable to covered code created
- under this License.
-
- 6. Redistributions of any form whatsoever must retain the following
- acknowledgment:
- "This product includes PHP software, freely available from
- ".
+Copyright (c) COLOPL, Inc.
+All rights reserved.
-THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
-ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
-DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGE.
-
---------------------------------------------------------------------
-
-This software consists of voluntary contributions made by many
-individuals on behalf of the PHP Group.
-
-The PHP Group can be contacted via Email at group@php.net.
-
-For more information on the PHP Group and the PHP project,
-please see .
-
-PHP includes the Zend Engine, freely available at
-.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 46add65..2369435 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,10 @@ Provides various compatibility functions required for PHP (temporary) migration.
## Supported Versions
-- Extension: PHP >= 8.0, 8.5 >= PHP
-- Library: PHP >= 7.4, 8.5 >= PHP
+- Extension: PHP >= 8.1, 8.5 >= PHP
+- Library: PHP == 7.4 or PHP >= 8.1, 8.5 >= PHP
-Library is introduced for migration to PHP 8.x with the same code base. If you do not need to work with the same code base, you can use only the Extension.
+Library is introduced for migration from PHP 7.4 to PHP 8.1+ with the same code base. PHP 8.0 is not supported. If you do not need to work with the same code base, you can use only the Extension.
## Usage
@@ -37,6 +37,31 @@ $ php -m | grep "colopl_bc"
colopl_bc
```
+### Build Ubuntu 22.04 packages
+
+Ubuntu 22.04 packages are built with standard Debian packaging via `dpkg-buildpackage`, not `checkinstall`.
+The packaging definitions live alongside each build target under `build/ubuntu2204/debian` and `build/ubuntu2204_sury84/debian`.
+
+Build packages for the official Ubuntu 22.04 PHP 8.1 stack:
+
+```bash
+$ docker build -f "build/ubuntu2204/Dockerfile" -t "colopl-bc-u2204-php81" .
+$ mkdir -p "artifacts"
+$ docker run --rm -e VERSION="x.y.z" -v "$(pwd)/artifacts:/tmp/artifacts" "colopl-bc-u2204-php81"
+```
+
+This target produces `php-colopl-bc` and `php8.1-colopl-bc` binary packages together with the corresponding `.changes` and `.buildinfo` files.
+
+Build packages for Ubuntu 22.04 with the Ondrej Sury PHP 8.4 repository:
+
+```bash
+$ docker build -f "build/ubuntu2204_sury84/Dockerfile" -t "colopl-bc-u2204-php84" .
+$ mkdir -p "artifacts"
+$ docker run --rm -e VERSION="x.y.z" -v "$(pwd)/artifacts:/tmp/artifacts" "colopl-bc-u2204-php84"
+```
+
+This target produces the `php8.4-colopl-bc` binary package together with the corresponding `.changes` and `.buildinfo` files.
+
The library is installed in the following steps.
```bash
@@ -212,3 +237,7 @@ Generate random numbers.
- `Colopl\ColoplBc\Php70\date_create_immutable()`
Always instantiate DateTime without milliseconds.
+
+## License
+
+This project is licensed under the BSD-3-Clause license. See [LICENSE](LICENSE).
diff --git a/build/library/test.sh b/build/library/test.sh
index cad9edd..e2c7193 100755
--- a/build/library/test.sh
+++ b/build/library/test.sh
@@ -1,6 +1,11 @@
#!/bin/sh
-if php -r 'exit((\PHP_VERSION_ID >= 80000) ? 0 : 1);'; then
+if php -r 'exit((\PHP_VERSION_ID >= 80000 && \PHP_VERSION_ID < 80100) ? 0 : 1);'; then
+ echo 'colopl_bc does not support PHP 8.0' >&2
+ exit 1
+fi
+
+if php -r 'exit((\PHP_VERSION_ID >= 80100) ? 0 : 1);'; then
cd "ext"
phpize
./configure --with-php-config="$(which php-config)"
@@ -14,7 +19,7 @@ fi
composer install
composer exec -- phpunit --config="phpunit.xml"
-if php -r 'exit((\PHP_VERSION_ID >= 80000) ? 0 : 1);'; then
+if php -r 'exit((\PHP_VERSION_ID >= 80100) ? 0 : 1);'; then
composer exec -- phpstan analyse --memory-limit=-1 --configuration="phpstan.neon"
composer exec -- psalm --memory-limit=-1 --config="psalm.xml"
fi
diff --git a/build/ubuntu2204/Dockerfile b/build/ubuntu2204/Dockerfile
index df5a932..a34d4b5 100644
--- a/build/ubuntu2204/Dockerfile
+++ b/build/ubuntu2204/Dockerfile
@@ -2,10 +2,21 @@ ARG PLATFORM=${BUILDPLATFORM:-linux/amd64}
FROM --platform=${PLATFORM} ubuntu:22.04
+ENV DEBIAN_FRONTEND="noninteractive"
+
RUN apt-get update && \
- DEBIAN_FRONTEND="noninteractive" apt-get install -y "php" "php-dev" "checkinstall"
+ apt-get install -y --no-install-recommends \
+ "build-essential" \
+ "debhelper" \
+ "dpkg-dev" \
+ "php8.1-cli" \
+ "php8.1-dev" && \
+ rm -rf /var/lib/apt/lists/*
-COPY ./ext /tmp/ext
+COPY ./ext /tmp/src/ext
+COPY ./LICENSE /tmp/src/LICENSE
+COPY ./README.md /tmp/src/README.md
+COPY ./build/ubuntu2204/debian /tmp/build/ubuntu2204/debian
COPY ./build/ubuntu2204/build.sh /usr/bin/build
diff --git a/build/ubuntu2204/build.sh b/build/ubuntu2204/build.sh
index 6970709..c7153f1 100755
--- a/build/ubuntu2204/build.sh
+++ b/build/ubuntu2204/build.sh
@@ -1,18 +1,19 @@
#!/bin/sh -eux
-cd "/tmp/ext"
- echo "COLOPL PHP backwards compatibility extension" > "description-pak"
- phpize
- ./configure --with-php-config="$(which "php-config")"
- make -j$(nproc)
- checkinstall \
- --pkgname="php-colopl-bc" \
- --pkglicense="PHP-3.01" \
- --pkgversion="${VERSION}" \
- --pkggroup="php" \
- --maintainer="g-kudo@colopl.co.jp" \
- --requires="php" \
- --stripso="yes" \
- --pakdir="/tmp/artifacts" \
- --nodoc
-cd -
+: "${VERSION:?VERSION is required}"
+
+SOURCE_DIR="/tmp/src"
+PACKAGING_DIR="/tmp/build/ubuntu2204/debian"
+ARTIFACTS_DIR="/tmp/artifacts"
+
+rm -rf "${SOURCE_DIR}/debian"
+install -d "${SOURCE_DIR}/debian" "${ARTIFACTS_DIR}"
+find "${ARTIFACTS_DIR}" -mindepth 1 -maxdepth 1 -delete
+
+cp -a "${PACKAGING_DIR}/." "${SOURCE_DIR}/debian/"
+sed "s/@VERSION@/${VERSION}/g" "${PACKAGING_DIR}/changelog.in" > "${SOURCE_DIR}/debian/changelog"
+rm -f "${SOURCE_DIR}/debian/changelog.in"
+
+cd "${SOURCE_DIR}"
+dpkg-buildpackage -us -uc -b
+find /tmp -maxdepth 1 -type f \( -name '*.deb' -o -name '*.buildinfo' -o -name '*.changes' \) -exec cp {} "${ARTIFACTS_DIR}/" \;
diff --git a/build/ubuntu2204/debian/changelog.in b/build/ubuntu2204/debian/changelog.in
new file mode 100644
index 0000000..4ca3c51
--- /dev/null
+++ b/build/ubuntu2204/debian/changelog.in
@@ -0,0 +1,5 @@
+php-colopl-bc (@VERSION@) jammy; urgency=medium
+
+ * Build php8.1-colopl-bc for Ubuntu 22.04.
+
+ -- Go Kudo Sun, 20 Apr 2026 00:00:00 +0000
diff --git a/build/ubuntu2204/debian/control b/build/ubuntu2204/debian/control
new file mode 100644
index 0000000..012d90d
--- /dev/null
+++ b/build/ubuntu2204/debian/control
@@ -0,0 +1,32 @@
+Source: php-colopl-bc
+Section: php
+Priority: optional
+Maintainer: Go Kudo
+Homepage: https://github.com/colopl/php-colopl_bc
+Standards-Version: 4.6.2
+Rules-Requires-Root: no
+Build-Depends:
+ debhelper-compat (= 13),
+ php8.1-cli,
+ php8.1-dev
+
+Package: php-colopl-bc
+Section: php
+Architecture: all
+Depends:
+ ${misc:Depends},
+ php8.1-colopl-bc
+Description: Meta package for the COLOPL backwards compatibility extension
+ This package depends on the Ubuntu 22.04 build of the colopl_bc extension
+ for PHP 8.1.
+
+Package: php8.1-colopl-bc
+Section: php
+Architecture: any
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+ php8.1-common
+Description: COLOPL backwards compatibility extension for PHP 8.1
+ The colopl_bc extension provides compatibility helpers that support staged
+ migrations from older PHP behavior to PHP 8.1 and later.
diff --git a/build/ubuntu2204/debian/copyright b/build/ubuntu2204/debian/copyright
new file mode 100644
index 0000000..1a55bf3
--- /dev/null
+++ b/build/ubuntu2204/debian/copyright
@@ -0,0 +1,31 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: php-colopl-bc
+Source: https://github.com/colopl/php-colopl_bc
+
+Files: *
+Copyright: 2020-2026 COLOPL, Inc.
+License: BSD-3-Clause
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ .
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ .
+ 3. Neither the name of COLOPL, Inc. nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build/ubuntu2204/debian/php8.1-colopl-bc.postinst b/build/ubuntu2204/debian/php8.1-colopl-bc.postinst
new file mode 100755
index 0000000..889f0aa
--- /dev/null
+++ b/build/ubuntu2204/debian/php8.1-colopl-bc.postinst
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+
+case "$1" in
+ configure|abort-upgrade|abort-deconfigure|abort-remove)
+ if command -v phpenmod >/dev/null 2>&1; then
+ phpenmod -v 8.1 -s ALL colopl_bc || true
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/build/ubuntu2204/debian/php8.1-colopl-bc.prerm b/build/ubuntu2204/debian/php8.1-colopl-bc.prerm
new file mode 100755
index 0000000..df9cc04
--- /dev/null
+++ b/build/ubuntu2204/debian/php8.1-colopl-bc.prerm
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+
+case "$1" in
+ remove|deconfigure)
+ if command -v phpdismod >/dev/null 2>&1; then
+ phpdismod -v 8.1 -s ALL colopl_bc || true
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/build/ubuntu2204/debian/rules b/build/ubuntu2204/debian/rules
new file mode 100755
index 0000000..ff5d175
--- /dev/null
+++ b/build/ubuntu2204/debian/rules
@@ -0,0 +1,32 @@
+#!/usr/bin/make -f
+
+PHPIZE = phpize
+PHP_CONFIG = php-config
+PHP_VERSION = 8.1
+BINARY_PACKAGE = php8.1-colopl-bc
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+%:
+ dh $@
+
+override_dh_auto_configure:
+ cd ext && $(PHPIZE)
+ cd ext && ./configure --with-php-config="$$(command -v $(PHP_CONFIG))"
+
+override_dh_auto_build:
+ $(MAKE) -C ext -j$(shell nproc)
+
+override_dh_auto_test:
+ cd ext && TEST_PHP_ARGS="--show-diff -q" $(MAKE) test
+
+override_dh_auto_install:
+ extdir="$$( $(PHP_CONFIG) --extension-dir )"; \
+ pkgdir="$(CURDIR)/debian/$(BINARY_PACKAGE)"; \
+ install -d "$$pkgdir$$extdir" "$$pkgdir/etc/php/$(PHP_VERSION)/mods-available"; \
+ install -m 0644 ext/modules/colopl_bc.so "$$pkgdir$$extdir/colopl_bc.so"; \
+ printf '%s\n' '; priority=20' 'extension=colopl_bc' > "$$pkgdir/etc/php/$(PHP_VERSION)/mods-available/colopl_bc.ini"
+
+override_dh_auto_clean:
+ if [ -f ext/Makefile ]; then $(MAKE) -C ext clean || true; fi
+ rm -rf ext/modules ext/autom4te.cache
diff --git a/build/ubuntu2204/debian/source/format b/build/ubuntu2204/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/build/ubuntu2204/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/build/ubuntu2204_sury84/Dockerfile b/build/ubuntu2204_sury84/Dockerfile
index 4743d10..0d1a42c 100644
--- a/build/ubuntu2204_sury84/Dockerfile
+++ b/build/ubuntu2204_sury84/Dockerfile
@@ -9,10 +9,18 @@ RUN apt-get update && \
"software-properties-common" && \
add-apt-repository ppa:ondrej/php -y && \
apt-get update && \
- apt-get install -y \
- "php8.4" "php8.4-dev" "checkinstall"
+ apt-get install -y --no-install-recommends \
+ "build-essential" \
+ "debhelper" \
+ "dpkg-dev" \
+ "php8.4-cli" \
+ "php8.4-dev" && \
+ rm -rf /var/lib/apt/lists/*
-COPY ./ext /tmp/ext
+COPY ./ext /tmp/src/ext
+COPY ./LICENSE /tmp/src/LICENSE
+COPY ./README.md /tmp/src/README.md
+COPY ./build/ubuntu2204_sury84/debian /tmp/build/ubuntu2204_sury84/debian
COPY ./build/ubuntu2204_sury84/build.sh /usr/bin/build
diff --git a/build/ubuntu2204_sury84/build.sh b/build/ubuntu2204_sury84/build.sh
index 8c516c2..267963a 100755
--- a/build/ubuntu2204_sury84/build.sh
+++ b/build/ubuntu2204_sury84/build.sh
@@ -1,19 +1,19 @@
#!/bin/sh -eux
-cd "/tmp/ext"
- echo "COLOPL PHP backwards compatibility extension for sury PHP 8.4" > "description-pak"
- phpize8.4
- ./configure --with-php-config="$(which "php-config8.4")"
- make -j"$(nproc)"
- TEST_PHP_ARGS="--show-diff -q" make test
- checkinstall \
- --pkgname="php8.4-colopl-bc" \
- --pkglicense="PHP-3.01" \
- --pkgversion="${VERSION}" \
- --pkggroup="php8.4" \
- --maintainer="g-kudo@colopl.co.jp" \
- --requires="php8.4-common" \
- --stripso="yes" \
- --pakdir="/tmp/artifacts" \
- --nodoc
-cd -
+: "${VERSION:?VERSION is required}"
+
+SOURCE_DIR="/tmp/src"
+PACKAGING_DIR="/tmp/build/ubuntu2204_sury84/debian"
+ARTIFACTS_DIR="/tmp/artifacts"
+
+rm -rf "${SOURCE_DIR}/debian"
+install -d "${SOURCE_DIR}/debian" "${ARTIFACTS_DIR}"
+find "${ARTIFACTS_DIR}" -mindepth 1 -maxdepth 1 -delete
+
+cp -a "${PACKAGING_DIR}/." "${SOURCE_DIR}/debian/"
+sed "s/@VERSION@/${VERSION}/g" "${PACKAGING_DIR}/changelog.in" > "${SOURCE_DIR}/debian/changelog"
+rm -f "${SOURCE_DIR}/debian/changelog.in"
+
+cd "${SOURCE_DIR}"
+dpkg-buildpackage -us -uc -b
+find /tmp -maxdepth 1 -type f \( -name '*.deb' -o -name '*.buildinfo' -o -name '*.changes' \) -exec cp {} "${ARTIFACTS_DIR}/" \;
diff --git a/build/ubuntu2204_sury84/debian/changelog.in b/build/ubuntu2204_sury84/debian/changelog.in
new file mode 100644
index 0000000..79b1a3c
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/changelog.in
@@ -0,0 +1,5 @@
+php-colopl-bc (@VERSION@) jammy; urgency=medium
+
+ * Build php8.4-colopl-bc for Ubuntu 22.04 with the Ondrej Sury PHP 8.4 repository.
+
+ -- Go Kudo Sun, 20 Apr 2026 00:00:00 +0000
\ No newline at end of file
diff --git a/build/ubuntu2204_sury84/debian/control b/build/ubuntu2204_sury84/debian/control
new file mode 100644
index 0000000..1a5950c
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/control
@@ -0,0 +1,22 @@
+Source: php-colopl-bc
+Section: php
+Priority: optional
+Maintainer: Go Kudo
+Homepage: https://github.com/colopl/php-colopl_bc
+Standards-Version: 4.6.2
+Rules-Requires-Root: no
+Build-Depends:
+ debhelper-compat (= 13),
+ php8.4-cli,
+ php8.4-dev
+
+Package: php8.4-colopl-bc
+Section: php
+Architecture: any
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+ php8.4-common
+Description: COLOPL backwards compatibility extension for Sury PHP 8.4
+ The colopl_bc extension provides compatibility helpers that support staged
+ migrations from older PHP behavior to PHP 8.1 and later.
diff --git a/build/ubuntu2204_sury84/debian/copyright b/build/ubuntu2204_sury84/debian/copyright
new file mode 100644
index 0000000..f0bcbb6
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/copyright
@@ -0,0 +1,31 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: php-colopl-bc
+Source: https://github.com/colopl/php-colopl_bc
+
+Files: *
+Copyright: 2020-2026 COLOPL, Inc.
+License: BSD-3-Clause
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ .
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ .
+ 3. Neither the name of COLOPL, Inc. nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/build/ubuntu2204_sury84/debian/php8.4-colopl-bc.postinst b/build/ubuntu2204_sury84/debian/php8.4-colopl-bc.postinst
new file mode 100755
index 0000000..b346166
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/php8.4-colopl-bc.postinst
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+
+case "$1" in
+ configure|abort-upgrade|abort-deconfigure|abort-remove)
+ if command -v phpenmod >/dev/null 2>&1; then
+ phpenmod -v 8.4 -s ALL colopl_bc || true
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
\ No newline at end of file
diff --git a/build/ubuntu2204_sury84/debian/php8.4-colopl-bc.prerm b/build/ubuntu2204_sury84/debian/php8.4-colopl-bc.prerm
new file mode 100755
index 0000000..4b4dbd9
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/php8.4-colopl-bc.prerm
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+
+case "$1" in
+ remove|deconfigure)
+ if command -v phpdismod >/dev/null 2>&1; then
+ phpdismod -v 8.4 -s ALL colopl_bc || true
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
\ No newline at end of file
diff --git a/build/ubuntu2204_sury84/debian/rules b/build/ubuntu2204_sury84/debian/rules
new file mode 100755
index 0000000..45c990d
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/rules
@@ -0,0 +1,32 @@
+#!/usr/bin/make -f
+
+PHPIZE = phpize8.4
+PHP_CONFIG = php-config8.4
+PHP_VERSION = 8.4
+BINARY_PACKAGE = php8.4-colopl-bc
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+%:
+ dh $@
+
+override_dh_auto_configure:
+ cd ext && $(PHPIZE)
+ cd ext && ./configure --with-php-config="$$(command -v $(PHP_CONFIG))"
+
+override_dh_auto_build:
+ $(MAKE) -C ext -j$(shell nproc)
+
+override_dh_auto_test:
+ cd ext && TEST_PHP_ARGS="--show-diff -q" $(MAKE) test
+
+override_dh_auto_install:
+ extdir="$$( $(PHP_CONFIG) --extension-dir )"; \
+ pkgdir="$(CURDIR)/debian/$(BINARY_PACKAGE)"; \
+ install -d "$$pkgdir$$extdir" "$$pkgdir/etc/php/$(PHP_VERSION)/mods-available"; \
+ install -m 0644 ext/modules/colopl_bc.so "$$pkgdir$$extdir/colopl_bc.so"; \
+ printf '%s\n' '; priority=20' 'extension=colopl_bc' > "$$pkgdir/etc/php/$(PHP_VERSION)/mods-available/colopl_bc.ini"
+
+override_dh_auto_clean:
+ if [ -f ext/Makefile ]; then $(MAKE) -C ext clean || true; fi
+ rm -rf ext/modules ext/autom4te.cache
\ No newline at end of file
diff --git a/build/ubuntu2204_sury84/debian/source/format b/build/ubuntu2204_sury84/debian/source/format
new file mode 100644
index 0000000..9f67427
--- /dev/null
+++ b/build/ubuntu2204_sury84/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
\ No newline at end of file
diff --git a/compose.yaml b/compose.yaml
index d1569f4..4cf6c89 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -3,7 +3,7 @@ services:
image: ${SHELL_IMAGE:-shell}
# environment:
# - CONFIGURE_OPTS=--enable-pdo --enable-mysqlnd --with-pdo-mysql
- # - LCOV_OPTS=--ignore-errors unused --exclude=/ext/third_party/* --ignore-errors unused --exclude=/workspaces/pskel/ext/third_party/*
+ # - LCOV_OPTS=--ignore-errors unused --exclude=/ext/third_party/*
build:
context: ./
dockerfile: ./Dockerfile
diff --git a/composer.json b/composer.json
index 4e34c95..b7dcde9 100644
--- a/composer.json
+++ b/composer.json
@@ -28,7 +28,7 @@
"php-ext": {
"extension-name": "colopl_bc",
"build-path": "ext",
- "download-url-method": ["pre-packaged-binary", "composer-default"],
+ "download-url-method": ["pre-packaged-binary", "pre-packaged-source", "composer-default"],
"configure-options": [
{
"name": "enable-colopl_bc",
@@ -36,7 +36,7 @@
}
]
},
- "license": "PHP-3.01",
+ "license": "BSD-3-Clause",
"authors": [
{
"name": "Go Kudo",
diff --git a/ext/.gitignore b/ext/.gitignore
index 6f644f8..dc89e86 100644
--- a/ext/.gitignore
+++ b/ext/.gitignore
@@ -6,15 +6,19 @@ acinclude.m4
aclocal.m4
autom4te.cache
build
+config.cache
config.guess
config.h
config.h.in
config.h.in~
config.log
config.nice
+config.nice.bat
config.status
config.sub
configure
+configure.bat
+configure.js
configure~
configure.ac
configure.in
@@ -29,11 +33,16 @@ Makefile.objects
missing
mkinstalldirs
modules
+php_test_results_*.txt
+phpt.*
+run-test-info.php
run-tests.php
-tests/*/*.diff
-tests/*/*.out
-tests/*/*.php
-tests/*/*.exp
-tests/*/*.log
-tests/*/*.sh
+tests/**/*.diff
+tests/**/*.out
+tests/**/*.php
+tests/**/*.exp
+tests/**/*.log
+tests/**/*.sh
+tests/**/*.db
+tests/**/*.mem
tmp-php.ini
diff --git a/ext/colopl_bc.c b/ext/colopl_bc.c
index ebf9c16..7ce1456 100644
--- a/ext/colopl_bc.c
+++ b/ext/colopl_bc.c
@@ -3,15 +3,9 @@
| COLOPL PHP Backwards Compatibility Extension. |
+----------------------------------------------------------------------+
| Copyright (c) COLOPL, Inc. |
- | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | This source file is subject to the BSD-3-Clause license that is |
+ | bundled with this package in the file LICENSE. |
+----------------------------------------------------------------------+
| Author: Go Kudo |
+----------------------------------------------------------------------+
diff --git a/ext/colopl_bc_php70.c b/ext/colopl_bc_php70.c
index 928722d..45bff24 100644
--- a/ext/colopl_bc_php70.c
+++ b/ext/colopl_bc_php70.c
@@ -3,15 +3,9 @@
| COLOPL PHP Backwards Compatibility Extension. |
+----------------------------------------------------------------------+
| Copyright (c) COLOPL, Inc. |
- | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | This source file is subject to the BSD-3-Clause license that is |
+ | bundled with this package in the file LICENSE. |
+----------------------------------------------------------------------+
| Author: Go Kudo |
+----------------------------------------------------------------------+
@@ -26,6 +20,76 @@
#include "ext/date/php_date.h"
#include "zend_bitset.h"
+#ifndef RAND_MAX
+# define RAND_MAX (1 << 15)
+#endif
+
+#if !defined(ZTS) && (defined(HAVE_LRAND48) || defined(HAVE_RANDOM))
+enum {
+ COLOPL_BC_RAND_MAX_VALUE = 2147483647,
+ COLOPL_BC_MT_M = 397,
+ COLOPL_BC_MT_RAND_MAX_VALUE = 0x7FFFFFFF
+};
+#else
+enum {
+ COLOPL_BC_RAND_MAX_VALUE = RAND_MAX,
+ COLOPL_BC_MT_M = 397,
+ COLOPL_BC_MT_RAND_MAX_VALUE = 0x7FFFFFFF
+};
+#endif
+
+/* Emulate gcc + amd64 undefined behavior results. */
+static inline zend_long php_colopl_bc_float_to_long_amd64(zend_long min, double value)
+{
+ if (value > ((double) ZEND_LONG_MAX) || value < ((double) ZEND_LONG_MIN)) {
+ return 0;
+ }
+
+ return min + (zend_long) value;
+}
+
+static inline zend_long php_colopl_bc_rand_range(zend_long number, zend_long min, zend_long max, zend_long rand_max)
+{
+ return php_colopl_bc_float_to_long_amd64(
+ min,
+ ((double) max - (double) min + 1.0) * ((double) number / ((double) rand_max + 1.0))
+ );
+}
+
+static inline zend_long php_colopl_bc_generate_seed(void)
+{
+#ifdef PHP_WIN32
+ return (((zend_long) (time(0) * GetCurrentProcessId())) ^ ((zend_long) (1000000.0 * php_combined_lcg())));
+#else
+ return (((zend_long) (time(0) * getpid())) ^ ((zend_long) (1000000.0 * php_combined_lcg())));
+#endif
+}
+
+static inline uint32_t php_colopl_bc_mt_hi_bit(uint32_t value)
+{
+ return value & 0x80000000U;
+}
+
+static inline uint32_t php_colopl_bc_mt_lo_bit(uint32_t value)
+{
+ return value & 0x00000001U;
+}
+
+static inline uint32_t php_colopl_bc_mt_lo_bits(uint32_t value)
+{
+ return value & 0x7FFFFFFFU;
+}
+
+static inline uint32_t php_colopl_bc_mt_mix_bits(uint32_t left, uint32_t right)
+{
+ return php_colopl_bc_mt_hi_bit(left) | php_colopl_bc_mt_lo_bits(right);
+}
+
+static inline uint32_t php_colopl_bc_mt_twist(uint32_t m, uint32_t u, uint32_t v)
+{
+ return m ^ (php_colopl_bc_mt_mix_bits(u, v) >> 1) ^ ((uint32_t) (-(uint32_t) php_colopl_bc_mt_lo_bit(u)) & 0x9908b0dfU);
+}
+
/* rand.c */
#if defined(__clang__)
@@ -70,7 +134,7 @@ zend_long php_colopl_bc_rand(void)
zend_long ret;
if (!COLOPL_BC_G(rand_is_seeded)) {
- php_colopl_bc_srand(COLOPL_BC_GENERATE_SEED());
+ php_colopl_bc_srand(php_colopl_bc_generate_seed());
}
#ifdef ZTS
@@ -106,7 +170,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_srand)
ZEND_PARSE_PARAMETERS_END();
if (ZEND_NUM_ARGS() == 0) {
- seed = COLOPL_BC_GENERATE_SEED();
+ seed = php_colopl_bc_generate_seed();
}
php_colopl_bc_srand(seed);
@@ -129,7 +193,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_rand)
Z_PARAM_LONG(max)
ZEND_PARSE_PARAMETERS_END();
- PHP_COLOPL_BC_RAND_RANGE(number, min, max, PHP_COLOPL_BC_RAND_MAX);
+ number = php_colopl_bc_rand_range(number, min, max, COLOPL_BC_RAND_MAX_VALUE);
RETURN_LONG(number);
}
@@ -137,7 +201,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_getrandmax)
{
ZEND_PARSE_PARAMETERS_NONE();
- RETURN_LONG(PHP_COLOPL_BC_RAND_MAX);
+ RETURN_LONG(COLOPL_BC_RAND_MAX_VALUE);
}
/* mt_rand.c */
@@ -149,7 +213,7 @@ static inline void mt_initialize(uint32_t seed, uint32_t *state)
register int i = 1;
*s++ = seed & 0xffffffffU;
- for (; i < N; ++i) {
+ for (; i < COLOPL_BC_MT_N; ++i) {
*s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU;
r++;
}
@@ -161,14 +225,14 @@ static inline void mt_reload(void)
register uint32_t *p = state;
register int i;
- for (i = N - M; i--; ++p) {
- *p = twist(p[M], p[0], p[1]);
+ for (i = COLOPL_BC_MT_N - COLOPL_BC_MT_M; i--; ++p) {
+ *p = php_colopl_bc_mt_twist(p[COLOPL_BC_MT_M], p[0], p[1]);
}
- for (i = M; --i; ++p) {
- *p = twist(p[M-N], p[0], p[1]);
+ for (i = COLOPL_BC_MT_M; --i; ++p) {
+ *p = php_colopl_bc_mt_twist(p[COLOPL_BC_MT_M - COLOPL_BC_MT_N], p[0], p[1]);
}
- *p = twist(p[M-N], p[0], state[0]);
- COLOPL_BC_G(mt_left) = N;
+ *p = php_colopl_bc_mt_twist(p[COLOPL_BC_MT_M - COLOPL_BC_MT_N], p[0], state[0]);
+ COLOPL_BC_G(mt_left) = COLOPL_BC_MT_N;
COLOPL_BC_G(mt_next) = state;
}
@@ -206,7 +270,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_mt_srand)
ZEND_PARSE_PARAMETERS_END();
if (ZEND_NUM_ARGS() == 0) {
- seed = COLOPL_BC_GENERATE_SEED();
+ seed = php_colopl_bc_generate_seed();
}
php_colopl_bc_mt_srand((uint32_t) seed);
@@ -219,7 +283,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_mt_rand)
if (argc == 0) {
if (!COLOPL_BC_G(mt_rand_is_seeded)) {
- php_colopl_bc_mt_srand(COLOPL_BC_GENERATE_SEED());
+ php_colopl_bc_mt_srand(php_colopl_bc_generate_seed());
}
RETURN_LONG(php_colopl_bc_mt_rand() >> 1);
}
@@ -235,11 +299,11 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_mt_rand)
}
if (!COLOPL_BC_G(mt_rand_is_seeded)) {
- php_colopl_bc_mt_srand(COLOPL_BC_GENERATE_SEED());
+ php_colopl_bc_mt_srand(php_colopl_bc_generate_seed());
}
number = (zend_long) (php_colopl_bc_mt_rand() >> 1);
- PHP_COLOPL_BC_RAND_RANGE(number, min, max, PHP_COLOPL_BC_MT_RAND_MAX);
+ number = php_colopl_bc_rand_range(number, min, max, COLOPL_BC_MT_RAND_MAX_VALUE);
RETURN_LONG(number);
}
@@ -247,7 +311,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_mt_getrandmax)
{
ZEND_PARSE_PARAMETERS_NONE();
- RETURN_LONG(PHP_COLOPL_BC_MT_RAND_MAX);
+ RETURN_LONG(COLOPL_BC_MT_RAND_MAX_VALUE);
}
/* array.c */
@@ -283,7 +347,7 @@ void php_colopl_bc_array_data_shuffle(zval *array)
}
while (--n_left) {
rnd_idx = php_colopl_bc_rand();
- PHP_COLOPL_BC_RAND_RANGE(rnd_idx, 0, n_left, PHP_COLOPL_BC_RAND_MAX);
+ rnd_idx = php_colopl_bc_rand_range(rnd_idx, 0, n_left, COLOPL_BC_RAND_MAX_VALUE);
if (rnd_idx != n_left) {
temp = hash->arData[n_left];
hash->arData[n_left] = hash->arData[rnd_idx];
@@ -309,7 +373,7 @@ void php_colopl_bc_array_data_shuffle(zval *array)
}
while (--n_left) {
rnd_idx = php_colopl_bc_rand();
- PHP_COLOPL_BC_RAND_RANGE(rnd_idx, 0, n_left, PHP_COLOPL_BC_RAND_MAX);
+ rnd_idx = php_colopl_bc_rand_range(rnd_idx, 0, n_left, COLOPL_BC_RAND_MAX_VALUE);
if (rnd_idx != n_left) {
temp = hash->arData[n_left];
hash->arData[n_left] = hash->arData[rnd_idx];
@@ -380,7 +444,7 @@ void php_colopl_bc_array_data_shuffle(zval *array)
}
while (--n_left) {
rnd_idx = php_colopl_bc_rand();
- PHP_COLOPL_BC_RAND_RANGE(rnd_idx, 0, n_left, PHP_COLOPL_BC_RAND_MAX);
+ rnd_idx = php_colopl_bc_rand_range(rnd_idx, 0, n_left, COLOPL_BC_RAND_MAX_VALUE);
if (rnd_idx != n_left) {
ZVAL_COPY_VALUE(&temp, &hash->arPacked[n_left]);
ZVAL_COPY_VALUE(&hash->arPacked[n_left], &hash->arPacked[rnd_idx]);
@@ -406,7 +470,7 @@ void php_colopl_bc_array_data_shuffle(zval *array)
}
while (--n_left) {
rnd_idx = php_colopl_bc_rand();
- PHP_COLOPL_BC_RAND_RANGE(rnd_idx, 0, n_left, PHP_COLOPL_BC_RAND_MAX);
+ rnd_idx = php_colopl_bc_rand_range(rnd_idx, 0, n_left, COLOPL_BC_RAND_MAX_VALUE);
if (rnd_idx != n_left) {
ZVAL_COPY_VALUE(&temp, &hash->arPacked[n_left]);
ZVAL_COPY_VALUE(&hash->arPacked[n_left], &hash->arPacked[rnd_idx]);
@@ -470,7 +534,7 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_array_rand)
randval = php_colopl_bc_rand();
- if ((double) (randval / (PHP_COLOPL_BC_RAND_MAX + 1.0)) < (double) num_req / (double) num_avail) {
+ if ((double) randval / ((double) COLOPL_BC_RAND_MAX_VALUE + 1.0) < (double) num_req / (double) num_avail) {
/* If we are returning a single result, just do it. */
if (Z_TYPE_P(return_value) != IS_ARRAY) {
if (string_key) {
@@ -509,7 +573,7 @@ void php_colopl_bc_string_shuffle(char *str, zend_long len)
while (--n_left) {
rnd_idx = php_colopl_bc_rand();
- PHP_COLOPL_BC_RAND_RANGE(rnd_idx, 0, n_left, PHP_COLOPL_BC_RAND_MAX);
+ rnd_idx = php_colopl_bc_rand_range(rnd_idx, 0, n_left, COLOPL_BC_RAND_MAX_VALUE);
if (rnd_idx != n_left) {
temp = str[n_left];
str[n_left] = str[rnd_idx];
@@ -534,30 +598,46 @@ PHP_FUNCTION(Colopl_ColoplBc_Php70_str_shuffle)
PHP_FUNCTION(Colopl_ColoplBc_Php70_date_create)
{
- zend_function *fn;
+ zval *timezone_object = NULL;
+ char *time_str = NULL;
+ size_t time_str_len = 0;
php_date_obj *date;
- fn = zend_hash_str_find_ptr(CG(function_table), "date_create", strlen("date_create"));
- ZEND_ASSERT(fn);
- fn->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ ZEND_PARSE_PARAMETERS_START(0, 2)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_STRING(time_str, time_str_len)
+ Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, php_date_get_timezone_ce())
+ ZEND_PARSE_PARAMETERS_END();
- if (Z_TYPE_P(return_value) != IS_FALSE) {
- date = Z_PHPDATE_P(return_value);
- date->time->us = 0;
+ php_date_instantiate(php_date_get_date_ce(), return_value);
+ if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
+ zval_ptr_dtor(return_value);
+ RETURN_FALSE;
}
+
+ date = Z_PHPDATE_P(return_value);
+ date->time->us = 0;
}
PHP_FUNCTION(Colopl_ColoplBc_Php70_date_create_immutable)
{
- zend_function *fn;
+ zval *timezone_object = NULL;
+ char *time_str = NULL;
+ size_t time_str_len = 0;
php_date_obj *date;
- fn = zend_hash_str_find_ptr(CG(function_table), "date_create_immutable", strlen("date_create_immutable"));
- ZEND_ASSERT(fn);
- fn->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ ZEND_PARSE_PARAMETERS_START(0, 2)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_STRING(time_str, time_str_len)
+ Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, php_date_get_timezone_ce())
+ ZEND_PARSE_PARAMETERS_END();
- if (Z_TYPE_P(return_value) != IS_FALSE) {
- date = Z_PHPDATE_P(return_value);
- date->time->us = 0;
+ php_date_instantiate(php_date_get_immutable_ce(), return_value);
+ if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
+ zval_ptr_dtor(return_value);
+ RETURN_FALSE;
}
+
+ date = Z_PHPDATE_P(return_value);
+ date->time->us = 0;
}
diff --git a/ext/colopl_bc_php74.c b/ext/colopl_bc_php74.c
index a1e52e1..4c4cc35 100644
--- a/ext/colopl_bc_php74.c
+++ b/ext/colopl_bc_php74.c
@@ -3,15 +3,9 @@
| COLOPL PHP Backwards Compatibility Extension. |
+----------------------------------------------------------------------+
| Copyright (c) COLOPL, Inc. |
- | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | This source file is subject to the BSD-3-Clause license that is |
+ | bundled with this package in the file LICENSE. |
+----------------------------------------------------------------------+
| Author: Go Kudo |
+----------------------------------------------------------------------+
@@ -31,13 +25,18 @@
#define COLOPL_BC_TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
-#define php_colopl_bc_convert_object_to_type(op, dst, ctype) \
- ZVAL_UNDEF(dst); \
- if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), dst, ctype) == FAILURE) { \
- zend_error(E_WARNING, \
- "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name), \
- zend_get_type_by_const(ctype)); \
- } \
+static inline void php_colopl_bc_convert_object_to_type(zval *op, zval *dst, uint32_t ctype)
+{
+ ZVAL_UNDEF(dst);
+ if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), dst, ctype) == FAILURE) {
+ zend_error(
+ E_WARNING,
+ "Object of class %s could not be converted to %s",
+ ZSTR_VAL(Z_OBJCE_P(op)->name),
+ zend_get_type_by_const(ctype)
+ );
+ }
+}
static zend_never_inline zval* ZEND_FASTCALL _php_colopl_bc_zendi_convert_scalar_to_number_silent(zval *op, zval *holder)
{
diff --git a/ext/description-pak b/ext/description-pak
deleted file mode 100644
index 1c8e423..0000000
--- a/ext/description-pak
+++ /dev/null
@@ -1 +0,0 @@
-Package created with checkinstall 1.6.3
diff --git a/ext/php_colopl_bc.h b/ext/php_colopl_bc.h
index 927d406..dd3733f 100644
--- a/ext/php_colopl_bc.h
+++ b/ext/php_colopl_bc.h
@@ -3,15 +3,9 @@
| COLOPL PHP Backwards Compatibility Extension. |
+----------------------------------------------------------------------+
| Copyright (c) COLOPL, Inc. |
- | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | This source file is subject to the BSD-3-Clause license that is |
+ | bundled with this package in the file LICENSE. |
+----------------------------------------------------------------------+
| Author: Go Kudo |
+----------------------------------------------------------------------+
@@ -42,13 +36,18 @@ extern zend_module_entry colopl_bc_module_entry;
#define COLOPL_BC_PHP74_SORT_MODE_DEPRECATED 1
#define COLOPL_BC_PHP74_SORT_MODE_LOG 2
-#define PHP_COLOPL_BC_VERSION "12.0.1"
+#define PHP_COLOPL_BC_VERSION "12.1.0"
+
+enum {
+ COLOPL_BC_MT_N = 624,
+ COLOPL_BC_MT_STATE_SIZE = COLOPL_BC_MT_N + 1
+};
ZEND_BEGIN_MODULE_GLOBALS(colopl_bc)
bool rand_is_seeded;
bool mt_rand_is_seeded;
uint32_t rand_seed;
- uint32_t mt_state[N+1];
+ uint32_t mt_state[COLOPL_BC_MT_STATE_SIZE];
uint32_t *mt_next;
int mt_left;
int gnurandom_r[344];
diff --git a/ext/php_colopl_bc_php70.h b/ext/php_colopl_bc_php70.h
index 08c493e..dc9db81 100644
--- a/ext/php_colopl_bc_php70.h
+++ b/ext/php_colopl_bc_php70.h
@@ -3,15 +3,9 @@
| COLOPL PHP Backwards Compatibility Extension. |
+----------------------------------------------------------------------+
| Copyright (c) COLOPL, Inc. |
- | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | This source file is subject to the BSD-3-Clause license that is |
+ | bundled with this package in the file LICENSE. |
+----------------------------------------------------------------------+
| Author: Go Kudo |
+----------------------------------------------------------------------+
@@ -22,35 +16,6 @@
#include "php_colopl_bc.h"
-#ifndef RAND_MAX
-# define RAND_MAX (1<<15)
-#endif
-
-#if !defined(ZTS) && (defined(HAVE_LRAND48) || defined(HAVE_RANDOM))
-# define PHP_COLOPL_BC_RAND_MAX 2147483647
-#else
-# define PHP_COLOPL_BC_RAND_MAX RAND_MAX
-#endif
-
-/* Emulate gcc + amd64 undefined behavior results. */
-static inline zend_long float_to_long_amd64(zend_long min, double f)
-{
- if (f > ((double) ZEND_LONG_MAX) || f < ((double) ZEND_LONG_MIN)) {
- return 0;
- }
-
- return min + (zend_long) f;
-}
-
-# define PHP_COLOPL_BC_RAND_RANGE(__n, __min, __max, __tmax) \
- (__n) = float_to_long_amd64(__min, ((double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
-
-#ifdef PHP_WIN32
-# define COLOPL_BC_GENERATE_SEED() (((zend_long) (time(0) * GetCurrentProcessId())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
-#else
-# define COLOPL_BC_GENERATE_SEED() (((zend_long) (time(0) * getpid())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
-#endif
-
/* rand.c */
PHPAPI void php_colopl_bc_srand(zend_long seed);
@@ -110,18 +75,6 @@ PHPAPI zend_long php_colopl_bc_rand(void);
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-#define PHP_COLOPL_BC_MT_RAND_MAX ((zend_long) (0x7FFFFFFF)) /* (1<<31) - 1 */
-
-#define N (624) /* length of state vector */
-#define M (397) /* a period parameter */
-#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */
-#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */
-#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */
-#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
-
-#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(uint32_t)(loBit(u))) & 0x9908b0dfU))
-
PHPAPI void php_colopl_bc_mt_srand(uint32_t seed);
PHPAPI uint32_t php_colopl_bc_mt_rand(void);
diff --git a/ext/php_colopl_bc_php74.h b/ext/php_colopl_bc_php74.h
index d3a48ab..19f50d2 100644
--- a/ext/php_colopl_bc_php74.h
+++ b/ext/php_colopl_bc_php74.h
@@ -3,15 +3,9 @@
| COLOPL PHP Backwards Compatibility Extension. |
+----------------------------------------------------------------------+
| Copyright (c) COLOPL, Inc. |
- | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | This source file is subject to the BSD-3-Clause license that is |
+ | bundled with this package in the file LICENSE. |
+----------------------------------------------------------------------+
| Author: Go Kudo |
+----------------------------------------------------------------------+
diff --git a/library.php b/library.php
index 58e9db2..84c8475 100644
--- a/library.php
+++ b/library.php
@@ -1,7 +1,11 @@
= 80000 && !\extension_loaded('colopl_bc')) {
+ if (\PHP_VERSION_ID >= 80000 && \PHP_VERSION_ID < 80100) {
+ \user_error('colopl_bc supports PHP 7.4 or PHP 8.1 and later; PHP 8.0 is not supported', \E_USER_ERROR);
+ }
+
+ if (\PHP_VERSION_ID >= 80100 && !\extension_loaded('colopl_bc')) {
\user_error('colopl_bc extension is not loaded', \E_USER_ERROR);
}
}
diff --git a/library_test.sh b/library_test.sh
index e95cce5..66e03ca 100755
--- a/library_test.sh
+++ b/library_test.sh
@@ -4,7 +4,11 @@ export USE_ZEND_ALLOC=1
export USE_TRACKED_ALLOC=0
export ZEND_DONT_UNLOAD_MODULES=1
cd "/project"
- if php -r 'exit((\PHP_VERSION_ID >= 80000) ? 0 : 1);'; then
+ if php -r 'exit((\PHP_VERSION_ID >= 80000 && \PHP_VERSION_ID < 80100) ? 0 : 1);'; then
+ echo 'colopl_bc does not support PHP 8.0' >&2
+ exit 1
+ fi
+ if php -r 'exit((\PHP_VERSION_ID >= 80100) ? 0 : 1);'; then
cd "ext"
phpize
./configure
diff --git a/phpunit.xml b/phpunit.xml
index 56284b9..4f66f6c 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -1,25 +1,24 @@
+ colors="true"
+ cacheDirectory=".phpunit.cache"
+ beStrictAboutCoverageMetadata="true">
tests
-
+
+
+
+
library.php
src
-
-
-
-
+
diff --git a/pskel.sh b/pskel.sh
index 411098f..bf5fbe0 100755
--- a/pskel.sh
+++ b/pskel.sh
@@ -2,23 +2,310 @@
set -e
+get_pskel_root_dir() {
+ PSKEL_PATH="${0}"
+
+ case "${PSKEL_PATH}" in
+ */*)
+ ;;
+ *)
+ PSKEL_PATH="$(command -v "${PSKEL_PATH}")"
+ ;;
+ esac
+
+ if command -v readlink >/dev/null 2>&1; then
+ PSKEL_PATH="$(readlink -f "${PSKEL_PATH}" 2>/dev/null || printf '%s' "${PSKEL_PATH}")"
+ fi
+
+ CDPATH='' cd -- "$(dirname -- "${PSKEL_PATH}")" && pwd
+}
+
+find_workspace_dir_from_pwd() {
+ SEARCH_DIR="${PWD}"
+
+ while test -n "${SEARCH_DIR}"; do
+ if test -f "${SEARCH_DIR}/pskel.sh" && test -f "${SEARCH_DIR}/.pskel/LICENSE.template"; then
+ echo "${SEARCH_DIR}"
+ return 0
+ fi
+
+ if test "${SEARCH_DIR}" = "/"; then
+ break
+ fi
+
+ SEARCH_DIR="$(dirname -- "${SEARCH_DIR}")"
+ done
+
+ return 1
+}
+
+get_workspace_dir() {
+ if test -n "${PSKEL_WORKSPACE_DIR}" && test -d "${PSKEL_WORKSPACE_DIR}"; then
+ echo "${PSKEL_WORKSPACE_DIR}"
+ elif PWD_WORKSPACE_DIR="$(find_workspace_dir_from_pwd 2>/dev/null)" && test -n "${PWD_WORKSPACE_DIR}"; then
+ echo "${PWD_WORKSPACE_DIR}"
+ elif test -d "${CODESPACE_VSCODE_FOLDER}"; then
+ echo "${CODESPACE_VSCODE_FOLDER}"
+ elif test -d "/workspace"; then
+ echo "/workspace"
+ elif test -d "/workspaces/pskel"; then
+ echo "/workspaces/pskel"
+ else
+ PSKEL_ROOT_DIR="$(get_pskel_root_dir)" || return 1
+ if test -f "${PSKEL_ROOT_DIR}/pskel.sh"; then
+ echo "${PSKEL_ROOT_DIR}"
+ else
+ echo "Error: Workspace root not found." >&2
+ return 1
+ fi
+ fi
+}
+
+
+get_project_license_template_path() {
+ PSKEL_ROOT_DIR="$(get_pskel_root_dir)" || return 1
+ LICENSE_TEMPLATE_PATH="${PSKEL_ROOT_DIR}/.pskel/LICENSE.template"
+
+ if test -f "${LICENSE_TEMPLATE_PATH}"; then
+ echo "${LICENSE_TEMPLATE_PATH}"
+ else
+ echo "Error: LICENSE template not found." >&2
+ return 1
+ fi
+}
+
+escape_sed_replacement() {
+ printf '%s' "${1}" | sed -e 's/[\\/&]/\\&/g'
+}
+
+slugify_vendor_name() {
+ printf '%s' "${1}" \
+ | tr '[:upper:]' '[:lower:]' \
+ | sed \
+ -e 's/[^a-z0-9._-]/-/g' \
+ -e 's/-\{2,\}/-/g' \
+ -e 's/^[._-]*//' \
+ -e 's/[._-]*$//'
+}
+
+create_project_license() {
+ LICENSE_TEMPLATE_PATH="$(get_project_license_template_path)" || return 1
+ WORKSPACE_DIR="$(get_workspace_dir)" || return 1
+ LICENSE_YEAR="$(date -u "+%Y")"
+ LICENSE_YEAR_ESCAPED="$(escape_sed_replacement "${LICENSE_YEAR}")"
+ EXT_VENDOR_DISPLAY_ESCAPED="$(escape_sed_replacement "${EXT_VENDOR_DISPLAY}")"
+
+ sed \
+ -e "s/%YEAR%/${LICENSE_YEAR_ESCAPED}/g" \
+ -e "s/%VENDOR%/${EXT_VENDOR_DISPLAY_ESCAPED}/g" \
+ "${LICENSE_TEMPLATE_PATH}" > "${WORKSPACE_DIR}/LICENSE"
+}
+
+create_project_composer_manifest() {
+ WORKSPACE_DIR="$(get_workspace_dir)" || return 1
+ EXT_COMPOSER_PATH="${PSKEL_TMP_DIR}/${EXT_NAME}/composer.json"
+
+ if ! test -f "${EXT_COMPOSER_PATH}"; then
+ echo "Error: composer.json template not found." >&2
+ return 1
+ fi
+
+ EXT_COMPOSER_PATH="${EXT_COMPOSER_PATH}" \
+ PROJECT_COMPOSER_PATH="${WORKSPACE_DIR}/composer.json" \
+ EXT_NAME="${EXT_NAME}" \
+ /usr/local/bin/php -r '
+ $sourcePath = getenv("EXT_COMPOSER_PATH");
+ $targetPath = getenv("PROJECT_COMPOSER_PATH");
+ $extensionName = getenv("EXT_NAME");
+
+ $manifest = json_decode((string) file_get_contents($sourcePath), true);
+ if (!is_array($manifest)) {
+ fwrite(STDERR, "Error: Failed to parse composer.json template.\n");
+ exit(1);
+ }
+
+ if (!isset($manifest["php-ext"]) || !is_array($manifest["php-ext"])) {
+ $manifest["php-ext"] = [];
+ }
+
+ $manifest["php-ext"]["extension-name"] = $extensionName;
+ $manifest["php-ext"]["build-path"] = "ext";
+ $manifest["php-ext"]["download-url-method"] = [
+ "pre-packaged-binary",
+ "pre-packaged-source",
+ "composer-default",
+ ];
+
+ $encoded = json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
+ if (!is_string($encoded)) {
+ fwrite(STDERR, "Error: Failed to encode project composer.json.\n");
+ exit(1);
+ }
+
+ file_put_contents($targetPath, $encoded . PHP_EOL);
+ ' || return 1
+
+ rm -f "${EXT_COMPOSER_PATH}"
+}
+
get_ext_dir() {
- PSKEL_EXT_DIR="/ext"
-
- if test -d "${CODESPACE_VSCODE_FOLDER}"; then
- echo "[Pskel] GitHub Codespace workspace detected, using \"${CODESPACE_VSCODE_FOLDER}/ext\"." >&2
- PSKEL_EXT_DIR="${CODESPACE_VSCODE_FOLDER}/ext"
- elif test -d "/workspaces/pskel/ext"; then
- echo "[Pskel] Development Containers workspace detected, using \"/workspaces/pskel/ext\"." >&2
- PSKEL_EXT_DIR="/workspaces/pskel/ext"
+ WORKSPACE_DIR="$(get_workspace_dir 2>/dev/null || true)"
+
+ if test -n "${WORKSPACE_DIR}" && test -d "${WORKSPACE_DIR}/ext"; then
+ if test -f "${WORKSPACE_DIR}/ext/.gitkeep" && test "$(cat "${WORKSPACE_DIR}/ext/.gitkeep")" = "pskel_uninitialized" && test "${1}" != "--no-init"; then
+ echo "[Pskel] Uninitialized project detected, initializing default skeleton." >&2
+ cmd_init "skeleton" >&2
+ fi
+ echo "[Pskel] Workspace extension directory detected, using \"${WORKSPACE_DIR}/ext\"." >&2
+ PSKEL_EXT_DIR="${WORKSPACE_DIR}/ext"
elif test -f "/ext/.gitkeep" && test "$(cat "/ext/.gitkeep")" = "pskel_uninitialized" && test "${1}" != "--no-init"; then
echo "[Pskel] Uninitialized project detected, initializing default skeleton." >&2
cmd_init "skeleton" >&2
+ PSKEL_EXT_DIR="/ext"
+ elif test -d "/ext"; then
+ PSKEL_EXT_DIR="/ext"
+ else
+ echo "Error: Extension directory not found." >&2
+ return 1
fi
echo "${PSKEL_EXT_DIR}"
}
+get_in_tree_ext_dir() {
+ echo "/usr/src/php/ext/colopl_bc"
+}
+
+sync_ext_into_php_source() {
+ SOURCE_DIR="${1}"
+ TARGET_DIR="$(get_in_tree_ext_dir)"
+
+ rm -rf "${TARGET_DIR}"
+ mkdir -p "${TARGET_DIR}"
+
+ rsync -a \
+ --exclude ".git/" \
+ --exclude "autom4te.cache/" \
+ --exclude "build/" \
+ --exclude "modules/" \
+ --exclude "*.dep" \
+ --exclude "*.la" \
+ --exclude "*.lo" \
+ --exclude "*.o" \
+ --exclude "Makefile" \
+ --exclude "Makefile.fragments" \
+ --exclude "Makefile.global" \
+ --exclude "Makefile.objects" \
+ --exclude "config.h" \
+ --exclude "config.h.in" \
+ --exclude "config.nice" \
+ --exclude "config.status" \
+ --exclude "configure" \
+ --exclude "configure.ac" \
+ --exclude "libtool" \
+ --exclude "run-tests.php" \
+ --exclude "*~" \
+ "${SOURCE_DIR}/" "${TARGET_DIR}/"
+
+ echo "${TARGET_DIR}"
+}
+
+generate_ext_source_hash() {
+ SOURCE_DIR="${1}"
+
+ (
+ cd "${SOURCE_DIR}"
+ find . \
+ \( -path "./autom4te.cache" -o -path "./autom4te.cache/*" -o -path "./build" -o -path "./build/*" -o -path "./modules" -o -path "./modules/*" \) -prune -o \
+ -type f \
+ ! -name "*.dep" \
+ ! -name "*.la" \
+ ! -name "*.lo" \
+ ! -name "*.o" \
+ ! -name "Makefile" \
+ ! -name "Makefile.fragments" \
+ ! -name "Makefile.global" \
+ ! -name "Makefile.objects" \
+ ! -name "config.h" \
+ ! -name "config.h.in" \
+ ! -name "config.nice" \
+ ! -name "config.status" \
+ ! -name "configure" \
+ ! -name "configure.ac" \
+ ! -name "libtool" \
+ ! -name "run-tests.php" \
+ ! -name "*~" \
+ -print \
+ | LC_ALL=C sort \
+ | while IFS= read -r FILE; do
+ sha256sum "${FILE}"
+ done \
+ | sha256sum \
+ | cut -d' ' -f1 \
+ | cut -c1-16
+ )
+}
+
+get_php_build_key_file() {
+ echo "/usr/local/include/${1}-php/.pskel-build-key"
+}
+
+php_build_is_current() {
+ PREFIX="${1}"
+ BUILD_KEY="${2}"
+ BUILD_KEY_FILE="$(get_php_build_key_file "${PREFIX}")"
+
+ if ! test -x "/usr/local/bin/${PREFIX}-php"; then
+ return 1
+ fi
+
+ if ! test -f "${BUILD_KEY_FILE}"; then
+ return 1
+ fi
+
+ test "$(cat "${BUILD_KEY_FILE}")" = "${BUILD_KEY}"
+}
+
+mark_php_build() {
+ PREFIX="${1}"
+ BUILD_KEY="${2}"
+ INCLUDE_DIR="/usr/local/include/${PREFIX}-php"
+
+ if ! test -d "${INCLUDE_DIR}"; then
+ mkdir -p "${INCLUDE_DIR}"
+ fi
+
+ printf '%s\n' "${BUILD_KEY}" > "${INCLUDE_DIR}/.pskel-build-key"
+}
+
+clear_php_build() {
+ PREFIX="${1}"
+
+ rm -f "/usr/local/bin/${PREFIX}-php" "/usr/local/bin/${PREFIX}-phpize" "/usr/local/bin/${PREFIX}-php-config"
+ rm -rf "/usr/local/include/${PREFIX}-php"
+}
+
+run_in_tree_static_tests() {
+ PHP_BIN="${1}"
+ TESTS_DIR="${2}"
+
+ if ! "${PHP_BIN}" -m | grep -qx "colopl_bc"; then
+ echo "Error: colopl_bc is not built into ${PHP_BIN}" >&2
+ return 1
+ fi
+
+ (
+ if test -n "${TEST_PHP_ARGS}"; then
+ eval "set -- ${TEST_PHP_ARGS}"
+ else
+ set --
+ fi
+
+ set -- "$@" --show-diff -q -p "${PHP_BIN}" "${TESTS_DIR}"
+ "${PHP_BIN}" "/usr/src/php/run-tests.php" "$@"
+ )
+}
+
cmd_usage() {
cat << EOF
Usage: ${0} [task] ...
@@ -35,7 +322,7 @@ cmd_init() {
case "${1}" in
-h|--help)
cat << EOF
-Usage: ${0} init [extension_name] [ext_skel.php options...]
+Usage: ${0} init [vendor_name] [ext_skel.php options...]
EOF
return 0
;;
@@ -45,20 +332,72 @@ EOF
;;
esac
- mkdir -p "/tmp/pskel_extension_tmp"
- if test "$(/usr/local/bin/php -r 'echo PHP_VERSION_ID;')" -lt "80500"; then
- /usr/local/bin/php "/usr/src/php/ext/ext_skel.php" --ext "${1}" --dir "/tmp/pskel_extension_tmp" "${@}"
+ EXT_NAME="${1}"
+ shift
+
+ if test -n "${1}" && test "${1}" = "${1#-}"; then
+ EXT_VENDOR_DISPLAY="${1}"
+ shift
else
- if test -z "${2}"; then
- EXT_VENDOR="pskel"
- else
- EXT_VENDOR="${2}"
+ EXT_VENDOR_DISPLAY="pskel"
+ fi
+
+ PSKEL_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/pskel_extension_tmp.XXXXXX")"
+ cleanup_pskel_tmp_dir() {
+ if test -n "${PSKEL_TMP_DIR}" && test -d "${PSKEL_TMP_DIR}"; then
+ rm -rf "${PSKEL_TMP_DIR}"
fi
- /usr/local/bin/php "/usr/src/php/ext/ext_skel.php" --vendor "${EXT_VENDOR}" --ext "${1}" --dir "/tmp/pskel_extension_tmp" "${@}"
+ }
+ trap cleanup_pskel_tmp_dir EXIT HUP INT TERM
+
+ EXT_VENDOR="$(slugify_vendor_name "${EXT_VENDOR_DISPLAY}")"
+
+ case "${EXT_NAME}" in
+ *[!-a-z0-9_.]*)
+ echo "Error: Extension name must only contain lowercase letters, numbers, hyphens, underscores, and dots." >&2
+ return 1
+ ;;
+ esac
+
+ if test -z "${EXT_VENDOR}"; then
+ echo "Error: Vendor name must contain at least one ASCII letter or number." >&2
+ return 1
+ fi
+
+ if test "$(/usr/local/bin/php -r 'echo PHP_VERSION_ID;')" -lt "80500"; then
+ /usr/local/bin/php "/usr/src/php/ext/ext_skel.php" --ext "${EXT_NAME}" --dir "${PSKEL_TMP_DIR}" "${@}"
+ cat > "${PSKEL_TMP_DIR}/${EXT_NAME}/composer.json" << COMPOSER_EOF
+{
+ "name": "${EXT_VENDOR}/${EXT_NAME}",
+ "type": "php-ext",
+ "license": "BSD-3-Clause",
+ "description": "Describe your extension here",
+ "require": {
+ "php": "~8.1.0"
+ },
+ "php-ext": {
+ "extension-name": "${EXT_NAME}",
+ "configure-options": [
+ {
+ "name": "enable-${EXT_NAME}",
+ "needs-value": false,
+ "description": "whether to enable ${EXT_NAME} support"
+ }
+ ]
+ }
+}
+COMPOSER_EOF
+ else
+ /usr/local/bin/php "/usr/src/php/ext/ext_skel.php" --vendor "${EXT_VENDOR}" --ext "${EXT_NAME}" --dir "${PSKEL_TMP_DIR}" "${@}"
fi
+
+ create_project_composer_manifest
+ create_project_license
+
PSKEL_EXT_DIR="$(get_ext_dir --no-init)"
- rm -rf "/tmp/pskel_extension_tmp/${1}/.gitkeep"
- rsync -av "/tmp/pskel_extension_tmp/${1}/" "${PSKEL_EXT_DIR}/"
+ rm -f "${PSKEL_EXT_DIR}/composer.json"
+ rm -rf "${PSKEL_TMP_DIR}/${EXT_NAME}/.gitkeep"
+ cp -a "${PSKEL_TMP_DIR}/${EXT_NAME}/." "${PSKEL_EXT_DIR}/"
rm -rf "${PSKEL_EXT_DIR}/.gitkeep"
}
@@ -66,13 +405,25 @@ cmd_test() {
case "${1}" in
-h|--help)
cat << EOF
-Usage: ${0} test [test_type|php_binary_name]
+Usage: ${0} test [debug|debug-static|gcov|valgrind|msan|asan|ubsan|php_binary_name]
Environment variables:
CFLAGS, CPPFLAGS: Compilation flags
TEST_PHP_ARGS: Test flags
EOF
return 0
;;
+ debug-static)
+ CC="$(command -v "gcc")"
+ CXX="$(command -v "g++")"
+ PSKEL_EXT_DIR="$(get_ext_dir)"
+ sync_ext_into_php_source "${PSKEL_EXT_DIR}" >/dev/null
+ CACHE_KEY_SUFFIX="$(generate_ext_source_hash "${PSKEL_EXT_DIR}")"
+ CONFIGURE_OPTS="${CONFIGURE_OPTS} --enable-colopl_bc"
+ build_php_if_not_exists "debug-static"
+ CMD="$(basename "${CC}")-debug-static-php"
+ run_in_tree_static_tests "$(command -v "${CMD}")" "$(get_in_tree_ext_dir)/tests"
+ return 0
+ ;;
debug|gcov|valgrind)
CC="$(command -v "gcc")"
CXX="$(command -v "g++")"
@@ -148,36 +499,41 @@ EOF
build_php_if_not_exists() {
PREFIX="$(basename "${CC}")-${1}"
+ BUILD_KEY="$(generate_cache_key "${1}" "${CC}")"
+
+ if php_build_is_current "${PREFIX}" "${BUILD_KEY}"; then
+ return 0
+ fi
+
+ clear_php_build "${PREFIX}"
if test -n "${GITHUB_ACTIONS}" && test -d "${PHP_CACHE_DIR}"; then
- if check_and_restore_cached_php "${PREFIX}" "${1}" "${CC}" "${CONFIGURE_OPTS}"; then
+ if check_and_restore_cached_php "${PREFIX}" "${BUILD_KEY}"; then
return 0
fi
+
+ clear_php_build "${PREFIX}"
fi
- if ! command -v "${PREFIX}-php" >/dev/null 2>&1; then
- CC="${CC}" \
- CXX="${CXX}" \
- CFLAGS="-DZEND_TRACK_ARENA_ALLOC" \
- CPPFLAGS="${CFLAGS}" \
- LDFLAGS="${LDFLAGS}" \
- CONFIGURE_OPTS="${CONFIGURE_OPTS} --enable-debug $(php -r "echo (bool)PHP_ZTS ? '--enable-zts' : '';") --enable-option-checking=fatal --disable-phpdbg --disable-cgi --disable-fpm --enable-cli --without-pcre-jit --disable-opcache-jit --disable-zend-max-execution-timers" \
- cmd_build "${PREFIX}"
-
- if test -n "${GITHUB_ACTIONS}" && test -d "${PHP_CACHE_DIR}"; then
- cache_php_build "${PREFIX}" "${1}" "${CC}"
- fi
+ CC="${CC}" \
+ CXX="${CXX}" \
+ CFLAGS="-DZEND_TRACK_ARENA_ALLOC" \
+ CPPFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}" \
+ CONFIGURE_OPTS="${CONFIGURE_OPTS} --enable-debug $(php -r "echo (bool)PHP_ZTS ? '--enable-zts' : '';") --enable-option-checking=fatal --disable-phpdbg --disable-cgi --disable-fpm --enable-cli --without-pcre-jit --disable-opcache-jit --disable-zend-max-execution-timers" \
+ cmd_build "${PREFIX}"
+
+ mark_php_build "${PREFIX}" "${BUILD_KEY}"
+
+ if test -n "${GITHUB_ACTIONS}" && test -d "${PHP_CACHE_DIR}"; then
+ cache_php_build "${PREFIX}" "${BUILD_KEY}"
fi
}
check_and_restore_cached_php() {
PREFIX="${1}"
- BUILD_TYPE="${2}"
- COMPILER="${3}"
- CONFIGURE_OPTS_LOCAL="${4}"
-
- CACHE_KEY="$(generate_cache_key "${BUILD_TYPE}" "${COMPILER}")"
- CACHE_DIR="${PHP_CACHE_DIR}/${CACHE_KEY}"
+ BUILD_KEY="${2}"
+ CACHE_DIR="${PHP_CACHE_DIR}/${BUILD_KEY}"
if test -f "${CACHE_DIR}/.build_complete"; then
for BIN in php phpize php-config; do
@@ -190,9 +546,11 @@ check_and_restore_cached_php() {
ln -sf "${CACHE_DIR}/usr/local/include/${PREFIX}-php" "/usr/local/include/${PREFIX}-php"
fi
- echo "[Pskel > Cache] Restored PHP header and binary: ${PREFIX}-php" >&2
+ if php_build_is_current "${PREFIX}" "${BUILD_KEY}"; then
+ echo "[Pskel > Cache] Restored PHP header and binary: ${PREFIX}-php" >&2
- return 0
+ return 0
+ fi
fi
return 1
@@ -204,6 +562,7 @@ generate_cache_key() {
PHP_VERSION="$(php -r 'echo PHP_VERSION;')"
PHP_ZTS="$(php -r 'echo (bool)PHP_ZTS ? "zts" : "nts";')"
+ ARCH="$(uname -m)"
if test -n "${CONTAINER_IMAGE_HASH}"; then
IMAGE_HASH="${CONTAINER_IMAGE_HASH}"
@@ -214,16 +573,18 @@ generate_cache_key() {
fi
fi
- echo "php-${PHP_VERSION}-${PHP_ZTS}-${BUILD_TYPE}-${COMPILER}-${IMAGE_HASH}"
+ EXTRA_KEY=""
+ if test -n "${CACHE_KEY_SUFFIX}"; then
+ EXTRA_KEY="-${CACHE_KEY_SUFFIX}"
+ fi
+
+ echo "php-${PHP_VERSION}-${PHP_ZTS}-${BUILD_TYPE}-${COMPILER}-${ARCH}-${IMAGE_HASH}${EXTRA_KEY}"
}
cache_php_build() {
PREFIX="${1}"
- BUILD_TYPE="${2}"
- COMPILER="${3}"
-
- CACHE_KEY="$(generate_cache_key "${BUILD_TYPE}" "${COMPILER}")"
- CACHE_DIR="${PHP_CACHE_DIR}/${CACHE_KEY}"
+ BUILD_KEY="${2}"
+ CACHE_DIR="${PHP_CACHE_DIR}/${BUILD_KEY}"
mkdir -p "${CACHE_DIR}/usr/local/bin"
@@ -288,6 +649,40 @@ EOF
${LCOV_OPTS} \
--exclude "/usr/local/include/*" \
--output-file "${PSKEL_EXT_DIR}/lcov.info"
+
+ # Convert lcov 2.0 FNL/FNA records to legacy FN/FNDA for CI compatibility.
+ awk 'BEGIN { _n = 0 }
+ /^FNL:/ {
+ split($0, a, /[,:]/)
+ _start[a[2]] = a[3]
+ next
+ }
+ /^FNA:/ {
+ idx = ""
+ cnt = ""
+ rest = $0
+ sub(/^FNA:/, "", rest)
+ split(rest, b, /,/)
+ idx = b[1]
+ cnt = b[2]
+ sub(/^[^,]*,[^,]*,/, "", rest)
+ _fn[_n] = "FN:" _start[idx] "," rest
+ _fnda[_n] = "FNDA:" cnt "," rest
+ _n++
+ next
+ }
+ /^FNF:/ {
+ for (i = 0; i < _n; i++) print _fn[i]
+ for (i = 0; i < _n; i++) print _fnda[i]
+ _n = 0
+ print
+ next
+ }
+ { print }
+ ' "${PSKEL_EXT_DIR}/lcov.info" > "${PSKEL_EXT_DIR}/lcov.info.tmp" \
+ && cat "${PSKEL_EXT_DIR}/lcov.info.tmp" > "${PSKEL_EXT_DIR}/lcov.info" \
+ && rm -f "${PSKEL_EXT_DIR}/lcov.info.tmp"
+
lcov --list "${PSKEL_EXT_DIR}/lcov.info"
}
diff --git a/tests/Extension/PHP70Test.php b/tests/Extension/PHP70Test.php
index 5dd9d02..25b4ba4 100644
--- a/tests/Extension/PHP70Test.php
+++ b/tests/Extension/PHP70Test.php
@@ -111,7 +111,7 @@ public function testMtSRand(): void
public function testMtSRandNull(): void
{
- /* PHP 8.1 does not support null -> 0 auto casting. */
+ /* Keep the legacy null-to-zero cast explicit across supported runtimes. */
$seed = (int) \null;
\Colopl\ColoplBc\Php70\mt_srand($seed);
diff --git a/third_party/valgrind b/third_party/valgrind
index c15bcfe..b80fd12 160000
--- a/third_party/valgrind
+++ b/third_party/valgrind
@@ -1 +1 @@
-Subproject commit c15bcfe15bd785a528725eebb7d985fcb8a86bed
+Subproject commit b80fd124192df64c168b4bbd8ef68a3c0abbba28