├── .github └── workflows │ ├── extension.yml │ ├── pecl.yml │ └── php.yml ├── LICENSE ├── README.md ├── extension-matrix ├── action.yml ├── config │ └── vs.json └── src │ ├── extension-matrix.sh │ ├── php-versions.sh │ └── semver │ ├── .gitignore │ ├── app.php │ ├── box.json │ ├── composer.json │ └── semver.phar ├── extension ├── BuildPhpExtension │ ├── BuildPhpExtension.psd1 │ ├── BuildPhpExtension.psm1 │ ├── config │ │ ├── stubs │ │ │ ├── apc.composer.json │ │ │ ├── http.composer.json │ │ │ ├── ibm_db2.composer.json │ │ │ ├── mongodb.composer.json │ │ │ ├── oci8.composer.json │ │ │ ├── parle.composer.json │ │ │ ├── pdo_ibm.composer.json │ │ │ ├── pdo_oci.composer.json │ │ │ ├── phalcon.composer.json │ │ │ ├── redis.composer.json │ │ │ ├── scoutapm.composer.json │ │ │ ├── var_representation.composer.json │ │ │ └── xdebug.composer.json │ │ ├── task.bat │ │ └── vs.json │ ├── images │ │ ├── php.png │ │ └── php.png.LICENSE │ ├── patches │ │ ├── base58.ps1 │ │ ├── crypto.ps1 │ │ ├── grpc.ps1 │ │ ├── hrtime.ps1 │ │ ├── lua.ps1 │ │ ├── memcache.ps1 │ │ ├── memcached.ps1 │ │ ├── oauth.ps1 │ │ ├── pdo_sqlsrv.ps1 │ │ ├── ps.ps1 │ │ ├── raphf.ps1 │ │ ├── rar.ps1 │ │ ├── request.ps1 │ │ ├── scrypt.ps1 │ │ ├── sqlsrv.ps1 │ │ ├── tensor.ps1 │ │ ├── xxtea.ps1 │ │ ├── yaf.ps1 │ │ ├── yar.ps1 │ │ └── zip.ps1 │ ├── private │ │ ├── Add-Boost.ps1 │ │ ├── Add-BuildLog.ps1 │ │ ├── Add-BuildRequirements.ps1 │ │ ├── Add-BuildTools.ps1 │ │ ├── Add-Dependencies.ps1 │ │ ├── Add-Extension.ps1 │ │ ├── Add-ExtensionDependencies.ps1 │ │ ├── Add-Extensions.ps1 │ │ ├── Add-OciDB.ps1 │ │ ├── Add-OciSdk.ps1 │ │ ├── Add-OdbcCli.ps1 │ │ ├── Add-Package.ps1 │ │ ├── Add-Patches.ps1 │ │ ├── Add-Path.ps1 │ │ ├── Add-PhpDependencies.ps1 │ │ ├── Add-StepLog.ps1 │ │ ├── Add-VS.ps1 │ │ ├── Get-ArgumentFromConfig.ps1 │ │ ├── Get-BuildDirectory.ps1 │ │ ├── Get-Extension.ps1 │ │ ├── Get-ExtensionConfig.ps1 │ │ ├── Get-ExtensionSource.ps1 │ │ ├── Get-LibrariesFromConfig.ps1 │ │ ├── Get-OlderVsVersions.ps1 │ │ ├── Get-PeclLibraryZip.ps1 │ │ ├── Get-PhpBuild.ps1 │ │ ├── Get-PhpBuildDetails.ps1 │ │ ├── Get-PhpDevelBuild.ps1 │ │ ├── Get-PhpSdk.ps1 │ │ ├── Get-PhpSrc.ps1 │ │ ├── Get-TempFiles.ps1 │ │ ├── Get-VsVersion.ps1 │ │ ├── Get-VsVersionHelper.ps1 │ │ ├── Invoke-Build.ps1 │ │ ├── Invoke-CleanupTempFIles.ps1 │ │ ├── Invoke-Tests.ps1 │ │ └── Set-GAGroup.ps1 │ └── public │ │ └── Invoke-PhpBuildExtension.ps1 └── action.yml ├── php ├── BuildPhp │ ├── BuildPhp.psd1 │ ├── BuildPhp.psm1 │ ├── config │ │ ├── ini │ │ │ ├── extensions.ini │ │ │ ├── opcache-x64.ini │ │ │ └── opcache-x86.ini │ │ ├── test_directories │ │ ├── tests.config.json │ │ ├── vc15 │ │ │ ├── x64 │ │ │ │ ├── config.nts.bat │ │ │ │ └── config.ts.bat │ │ │ └── x86 │ │ │ │ ├── config.nts.bat │ │ │ │ └── config.ts.bat │ │ ├── vs.json │ │ ├── vs16 │ │ │ ├── x64 │ │ │ │ ├── config.nts.bat │ │ │ │ └── config.ts.bat │ │ │ └── x86 │ │ │ │ ├── config.nts.bat │ │ │ │ └── config.ts.bat │ │ └── vs17 │ │ │ ├── x64 │ │ │ ├── config.nts.bat │ │ │ └── config.ts.bat │ │ │ └── x86 │ │ │ ├── config.nts.bat │ │ │ └── config.ts.bat │ ├── images │ │ ├── php.png │ │ └── php.png.LICENSE │ ├── private │ │ ├── Add-BuildRequirements.ps1 │ │ ├── Add-TestRequirements.ps1 │ │ ├── Add-VS.ps1 │ │ ├── Get-OciSdk.ps1 │ │ ├── Get-PhpBuild.ps1 │ │ ├── Get-PhpSdk.ps1 │ │ ├── Get-PhpSrc.ps1 │ │ ├── Get-PhpTestPack.ps1 │ │ ├── Get-TestSettings.ps1 │ │ ├── Get-TestsList.ps1 │ │ ├── Get-VsVersion.ps1 │ │ ├── Get-VsVersionHelper.ps1 │ │ └── Set-PhpIniForTests.ps1 │ ├── public │ │ ├── Invoke-PhpBuild.ps1 │ │ └── Invoke-PhpTests.ps1 │ ├── runner │ │ ├── task-nts.bat │ │ └── task-ts.bat │ └── tests │ │ └── BuildPhp.Tests.ps1 └── action.yml └── release └── action.yml /.github/workflows/extension.yml: -------------------------------------------------------------------------------- 1 | name: Build PHP Extension 2 | run-name: Build PHP Extension ${{ inputs.extension-url }}, ${{ inputs.extension-ref }} 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | extension-url: 7 | description: 'Extension URL' 8 | required: true 9 | extension-ref: 10 | description: 'Extension ref' 11 | required: true 12 | php-version-list: 13 | description: 'PHP versions to build' 14 | required: false 15 | arch-list: 16 | type: choice 17 | options: ['x64', 'x86', 'x64,x86'] 18 | description: 'Architectures to build' 19 | required: false 20 | default: 'x64,x86' 21 | ts-list: 22 | type: choice 23 | options: ['nts', 'ts', 'nts,ts'] 24 | description: 'Thread safety to build' 25 | required: false 26 | default: 'nts,ts' 27 | args: 28 | description: 'Configure arguments' 29 | required: false 30 | libs: 31 | description: 'Libraries' 32 | required: false 33 | run-tests: 34 | type: choice 35 | options: ['true', 'false'] 36 | description: 'Run tests after building the extension' 37 | required: false 38 | default: 'false' 39 | test-runner: 40 | description: 'Test runner to use' 41 | required: false 42 | default: 'run-tests.php' 43 | test-opcache-mode: 44 | type: choice 45 | options: ['on', 'off', 'both'] 46 | description: 'Test opcache mode' 47 | required: false 48 | default: 'off' 49 | jobs: 50 | get-extension-matrix: 51 | runs-on: ubuntu-latest 52 | outputs: 53 | matrix: ${{ steps.extension-matrix.outputs.matrix }} 54 | steps: 55 | - name: Checkout 56 | uses: actions/checkout@v4 57 | - name: Get the extension matrix 58 | id: extension-matrix 59 | uses: ./extension-matrix 60 | with: 61 | extension-url: ${{ inputs.extension-url }} 62 | extension-ref: ${{ inputs.extension-ref }} 63 | php-version-list: ${{ inputs.php-version-list }} 64 | arch-list: ${{ inputs.arch-list }} 65 | ts-list: ${{ inputs.ts-list }} 66 | 67 | extension: 68 | needs: get-extension-matrix 69 | runs-on: ${{ matrix.os }} 70 | strategy: 71 | fail-fast: false 72 | matrix: ${{fromJson(needs.get-extension-matrix.outputs.matrix)}} 73 | steps: 74 | - name: Checkout 75 | uses: actions/checkout@v4 76 | - name: Build the extension 77 | uses: ./extension 78 | with: 79 | extension-url: ${{ inputs.extension-url }} 80 | extension-ref: ${{ inputs.extension-ref }} 81 | php-version: ${{ matrix.php-version }} 82 | arch: ${{ matrix.arch }} 83 | ts: ${{ matrix.ts }} 84 | args: ${{ inputs.args }} 85 | libs: ${{ inputs.libs }} 86 | run-tests: ${{ inputs.run-tests }} 87 | test-runner: ${{ inputs.test-runner }} 88 | test-opcache-mode: ${{ inputs.test-opcache-mode }} 89 | build-directory: C:\build 90 | 91 | artifacts: 92 | runs-on: ubuntu-latest 93 | needs: extension 94 | steps: 95 | - name: Upload artifacts 96 | uses: actions/upload-artifact/merge@v4 97 | with: 98 | name: artifacts 99 | delete-merged: true 100 | -------------------------------------------------------------------------------- /.github/workflows/pecl.yml: -------------------------------------------------------------------------------- 1 | name: Build PHP Extension From PECL 2 | run-name: Build PHP Extension ${{ inputs.extension-url }}, ${{ inputs.extension-ref }} 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | extension-url: 7 | description: 'Extension URL' 8 | required: true 9 | extension-ref: 10 | description: 'Extension ref' 11 | required: true 12 | php-version-list: 13 | description: 'PHP versions to build' 14 | required: false 15 | arch-list: 16 | type: choice 17 | options: ['x64', 'x86', 'x64,x86'] 18 | description: 'Architectures to build' 19 | required: false 20 | default: 'x64,x86' 21 | ts-list: 22 | type: choice 23 | options: ['nts', 'ts', 'nts,ts'] 24 | description: 'Thread safety to build' 25 | required: false 26 | default: 'nts,ts' 27 | args: 28 | description: 'Configure arguments' 29 | required: false 30 | libs: 31 | description: 'Libraries' 32 | required: false 33 | run-tests: 34 | type: choice 35 | options: ['true', 'false'] 36 | description: 'Run tests after building the extension' 37 | required: false 38 | default: 'false' 39 | test-runner: 40 | description: 'Test runner to use' 41 | required: false 42 | default: 'run-tests.php' 43 | jobs: 44 | get-extension-matrix: 45 | runs-on: ubuntu-latest 46 | outputs: 47 | matrix: ${{ steps.extension-matrix.outputs.matrix }} 48 | steps: 49 | - name: Checkout 50 | uses: actions/checkout@v4 51 | - name: Get the extension matrix 52 | id: extension-matrix 53 | uses: ./extension-matrix 54 | with: 55 | extension-url: ${{ inputs.extension-url }} 56 | extension-ref: ${{ inputs.extension-ref }} 57 | php-version-list: ${{ inputs.php-version-list }} 58 | arch-list: ${{ inputs.arch-list }} 59 | ts-list: ${{ inputs.ts-list }} 60 | 61 | extension: 62 | needs: get-extension-matrix 63 | runs-on: ${{ matrix.os }} 64 | strategy: 65 | fail-fast: false 66 | matrix: ${{fromJson(needs.get-extension-matrix.outputs.matrix)}} 67 | steps: 68 | - name: Checkout 69 | uses: actions/checkout@v4 70 | - name: Build the extension 71 | uses: ./extension 72 | with: 73 | extension-url: ${{ inputs.extension-url }} 74 | extension-ref: ${{ inputs.extension-ref }} 75 | php-version: ${{ matrix.php-version }} 76 | arch: ${{ matrix.arch }} 77 | ts: ${{ matrix.ts }} 78 | args: ${{ inputs.args }} 79 | libs: ${{ inputs.libs }} 80 | run-tests: ${{ inputs.run-tests }} 81 | test-runner: ${{ inputs.test-runner }} 82 | build-directory: C:\build 83 | env: 84 | artifact-naming-scheme: pecl 85 | auto-detect-args: true 86 | auto-detect-libs: true 87 | no-debug-symbols-ddtrace: true 88 | 89 | artifacts: 90 | runs-on: ubuntu-latest 91 | needs: extension 92 | steps: 93 | - name: Upload artifacts 94 | uses: actions/upload-artifact/merge@v4 95 | with: 96 | name: artifacts 97 | delete-merged: true 98 | 99 | pecl-release: 100 | runs-on: ubuntu-latest 101 | needs: artifacts 102 | steps: 103 | - name: Get artifact 104 | uses: actions/download-artifact@v4 105 | with: 106 | name: artifacts 107 | path: artifacts 108 | - name: Release 109 | env: 110 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 111 | run: | 112 | ls -l artifacts 113 | extension=$(basename "${{ inputs.extension-url }}") 114 | mkdir -p /tmp/$extension/${{ inputs.extension-ref }}/ 115 | cp -a artifacts/* /tmp/$extension/${{ inputs.extension-ref }}/ 116 | cd /tmp || exit 1 117 | zip -r $extension-${{ inputs.extension-ref }}.zip $extension 118 | if ! gh release view pecl -R ${{ github.repository }}; then 119 | gh release create pecl $extension-${{ inputs.extension-ref }}.zip -t pecl -n pecl -R ${{ github.repository }} 120 | else 121 | gh release upload pecl $extension-${{ inputs.extension-ref }}.zip -R ${{ github.repository }} --clobber 122 | fi 123 | upload: 124 | runs-on: ubuntu-latest 125 | needs: pecl-release 126 | steps: 127 | - name: Upload to downloads server 128 | run: | 129 | extension=$(basename "${{ inputs.extension-url }}") 130 | url="https://github.com/${{ github.repository }}/releases/download/pecl/$extension-${{ inputs.extension-ref }}.zip" 131 | gh workflow run pecl.yml -R php/web-downloads -f url="$url" -f extension="$extension" -f ref="${{ inputs.extension-ref }}" 132 | env: 133 | GITHUB_TOKEN: ${{ secrets.WINDOWS_BUILDS_TOKEN }} 134 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: Build PHP 2 | run-name: Build PHP ${{ inputs.php-version }} 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | php-version: 7 | description: 'PHP version to build' 8 | required: true 9 | upload: 10 | type: choice 11 | options: ['true', 'false'] 12 | description: Upload artifacts to the downloads server 13 | required: false 14 | default: 'true' 15 | 16 | jobs: 17 | php: 18 | strategy: 19 | matrix: 20 | arch: [x64, x86] 21 | ts: [nts, ts] 22 | runs-on: windows-2022 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v4 26 | 27 | - name: Build 28 | uses: ./php 29 | with: 30 | php-version: ${{ github.event.inputs.php-version }} 31 | arch: ${{ matrix.arch }} 32 | ts: ${{ matrix.ts }} 33 | 34 | artifacts: 35 | runs-on: ubuntu-latest 36 | needs: php 37 | outputs: 38 | artifact-id: ${{ steps.artifacts.outputs.artifact-id }} 39 | steps: 40 | - name: Upload artifacts 41 | uses: actions/upload-artifact/merge@v4 42 | id: artifacts 43 | with: 44 | name: artifacts 45 | delete-merged: true 46 | upload: 47 | runs-on: ubuntu-latest 48 | needs: artifacts 49 | if: ${{ github.event.inputs.upload == 'true' }} 50 | steps: 51 | - name: Upload to downloads server 52 | run: | 53 | url="https://api.github.com/repos/${{ github.repository }}/actions/artifacts/${{ needs.artifacts.outputs.artifact-id }}/zip" 54 | gh workflow run php.yml -R php/web-downloads -f url="$url" -f php-version=${{ inputs.php-version }} 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.WINDOWS_BUILDS_TOKEN }} 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person 2 | obtaining a copy of this software and associated documentation 3 | files (the "Software"), to deal in the Software without 4 | restriction, including without limitation the rights to use, 5 | copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | copies of the Software, and to permit persons to whom the 7 | Software is furnished to do so, subject to the following 8 | conditions: 9 | 10 | The above copyright notice and this permission notice shall be 11 | included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 17 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-windows-builder 2 | 3 | This project provides actions to build PHP and its extensions on Windows. 4 | 5 | ## Build PHP 6 | 7 | Build a specific version of PHP, with the required architecture and thread safety. 8 | 9 | ```yaml 10 | - name: Build PHP 11 | uses: php/php-windows-builder/php@v1 12 | with: 13 | php-version: '8.4.1' 14 | arch: x64 15 | ts: nts 16 | ``` 17 | 18 | ### Inputs 19 | 20 | - `php-version` (required) - The PHP version to build. It supports values in major.minor.patch format, e.g. 7.4.25, 8.0.12, etc. 21 | - `arch` (required) - The architecture to build. It supports values `x64` and `x86`. 22 | - `ts` (required) - The thread safety to build. It supports values `ts` and `nts`. 23 | 24 | ### Example workflow to build PHP 25 | 26 | ```yaml 27 | jobs: 28 | php: 29 | strategy: 30 | matrix: 31 | arch: [x64, x86] 32 | ts: [nts, ts] 33 | runs-on: windows-2022 34 | steps: 35 | - name: Checkout 36 | uses: actions/checkout@v4 37 | 38 | - name: Build 39 | uses: php/php-windows-builder/php@v1 40 | with: 41 | php-version: '8.4.1' 42 | arch: ${{ matrix.arch }} 43 | ts: ${{ matrix.ts }} 44 | ``` 45 | 46 | The above workflow will produce the following builds for the PHP version `8.4.1` as artifacts. 47 | 48 | - nts-x64, nts-x64-AVX, ts-x64, nts-x86, ts-x86. 49 | - debug-pack and devel-pack for each the above configurations. 50 | - test pack 51 | 52 | ## Build a PHP extension 53 | 54 | Build a specific version of a PHP extension. 55 | 56 | ```yaml 57 | - name: Build the extension 58 | uses: php/php-windows-builder/extension@v1 59 | with: 60 | extension-url: https://github.com/xdebug/xdebug 61 | extension-ref: '3.3.2' 62 | php-version: '8.3' 63 | ts: nts 64 | arch: x64 65 | args: --with-xdebug 66 | libs: zlib 67 | ``` 68 | 69 | ### Inputs 70 | 71 | - `extension-url` (optional) - URL of the extension's git repository, defaults to the current repository. 72 | - `extension-ref` (required) - The git reference to build the extension, defaults to the GitHub reference that triggered the workflow. 73 | - `php-version` (required) - The PHP versions to build the extension for. 74 | - `arch` (required) - The architecture to build the extension for. 75 | - `ts` (required) - The thread safety to build the extension for. 76 | - `args` (optional) - Additional arguments to pass to the `configure` script. 77 | - `libs` (optional) - Libraries required for the extension. 78 | - `build-directory` (optional) - The directory to build the extension in, defaults to the user's temporary directory. 79 | - `run-tests` (optional) - Run the extension tests. Defaults to `true`. 80 | - `test-runner` (optional) - The test runner to use. Defaults to `run-tests.php`. 81 | - `test-opcache-mode` (optional) - Run tests with opcache `on`, `off` or `both`. Defaults to `off`. 82 | - `test-workers` (optional) - The number of workers to use when running tests. Defaults to `8`. 83 | - `auth-token` (optional) - Authentication token to use in case the extension is hosted on a private repository. 84 | 85 | Instead of having to configure all the inputs for the extension action, you can use the `extension-matrix` action to get the matrix of jobs with different input configurations. 86 | 87 | ## Get the job matrix to build a PHP extension 88 | 89 | ```yaml 90 | jobs: 91 | get-extension-matrix: 92 | runs-on: ubuntu-latest 93 | steps: 94 | - name: Checkout 95 | uses: actions/checkout@v4 96 | - name: Get the extension matrix 97 | id: extension-matrix 98 | uses: php/php-windows-builder/extension-matrix@v1 99 | with: 100 | extension-url: https://github.com/xdebug/xdebug 101 | extension-ref: '3.3.2' 102 | php-version-list: '8.2, 8.3' 103 | arch-list: 'x64, x86' 104 | ts-list: 'nts, ts' 105 | ``` 106 | 107 | ### Inputs 108 | 109 | - `extension-url` (optional) - URL of the extension's git repository, defaults to the current repository. 110 | - `extension-ref` (optional) - The git reference to build the extension, defaults to the GitHub reference that triggered the workflow. 111 | - `php-version-list` (optional) - The PHP versions to build the extension for. Defaults to the PHP versions required in the `composer.json` file. 112 | - `arch-list` (optional) - The architectures to build the extension for. Defaults to `x64, x86`. 113 | - `ts-list` (optional) - The thread safety to build the extension for. Defaults to `nts, ts`. 114 | - `allow-old-php-versions` (optional) - Allow building the extension for older PHP versions. Defaults to `false`. 115 | - `auth-token` (optional) - Authentication token to use in case the extension is hosted on a private repository. 116 | 117 | ### Outputs 118 | 119 | - `matrix` - The matrix of jobs with different input configurations. 120 | 121 | ### PHP Version Support 122 | 123 | By default, the `extension-matrix` action will use the PHP versions defined in the `php-version-list` input. 124 | 125 | If the `php-version-list` input is not provided, it will use the PHP versions required in the `composer.json` file. 126 | 127 | It will also check if a GitHub hosted Windows runner is available with the required Visual Studio version to build the extension for the PHP version. To override this for building the extension for older PHP versions, you will have to set the input `allow_old_php_versions` to `true` and add self-hosted Windows runners as specified in the table below. 128 | 129 | | PHP Version | Visual Studio Version | Windows Runner Labels | 130 | |-------------|-----------------------|-----------------------------| 131 | | 7.0 | 2015 (vc14) | windows-2012, self-hosted | 132 | | 7.1 | 2015 (vc14) | windows-2012, self-hosted | 133 | | 7.2 | 2017 (vc15) | windows-2019, github-hosted | 134 | | 7.3 | 2017 (vc15) | windows-2019, github-hosted | 135 | | 7.4 | 2017 (vc15) | windows-2019, github-hosted | 136 | | 8.0 | 2019 (vs16) | windows-2022, github-hosted | 137 | | 8.1 | 2019 (vs16) | windows-2022, github-hosted | 138 | | 8.2 | 2019 (vs16) | windows-2022, github-hosted | 139 | | 8.3 | 2019 (vs16) | windows-2022, github-hosted | 140 | | 8.4 | 2022 (vs17) | windows-2022, github-hosted | 141 | 142 | ## Release 143 | 144 | Upload the artifacts to a release. 145 | 146 | ```yaml 147 | - name: Upload artifact to the release 148 | uses: php/php-windows-builder/release@v1 149 | with: 150 | release: ${{ github.event.release.tag_name }} 151 | token: ${{ secrets.GITHUB_TOKEN }} 152 | ``` 153 | 154 | ### Inputs 155 | 156 | - `release` (required) - The release to upload the artifacts. 157 | - `token` (required) - The GitHub token to authenticate with. 158 | 159 | ### Example workflow to build and release an extension 160 | 161 | ```yaml 162 | name: Build extension 163 | on: 164 | release: 165 | types: [published] 166 | # create: # Uncomment this to run on tag/branch creation 167 | # pull_request: # Uncomment this to run on pull requests 168 | 169 | # This may be needed to be able to upload the assets to the release 170 | # See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token 171 | #permissions: 172 | # contents: write 173 | 174 | jobs: 175 | get-extension-matrix: 176 | runs-on: ubuntu-latest 177 | outputs: 178 | matrix: ${{ steps.extension-matrix.outputs.matrix }} 179 | steps: 180 | - name: Checkout 181 | uses: actions/checkout@v4 182 | - name: Get the extension matrix 183 | id: extension-matrix 184 | uses: php/php-windows-builder/extension-matrix@v1 185 | build: 186 | needs: get-extension-matrix 187 | runs-on: ${{ matrix.os }} 188 | strategy: 189 | matrix: ${{fromJson(needs.get-extension-matrix.outputs.matrix)}} 190 | steps: 191 | - name: Checkout 192 | uses: actions/checkout@v4 193 | - name: Build the extension 194 | uses: php/php-windows-builder/extension@v1 195 | with: 196 | php-version: ${{ matrix.php-version }} 197 | arch: ${{ matrix.arch }} 198 | ts: ${{ matrix.ts }} 199 | release: 200 | runs-on: ubuntu-latest 201 | needs: build 202 | if: ${{ github.event_name == 'release' }} 203 | steps: 204 | - name: Upload artifact to the release 205 | uses: php/php-windows-builder/release@v1 206 | with: 207 | release: ${{ github.event.release.tag_name }} 208 | token: ${{ secrets.GITHUB_TOKEN }} 209 | ``` 210 | 211 | ## License 212 | 213 | The scripts and documentation in this project are released under the [MIT License](LICENSE) 214 | -------------------------------------------------------------------------------- /extension-matrix/action.yml: -------------------------------------------------------------------------------- 1 | name: extension-matrix 2 | description: Get the matrix for building PHP extensions 3 | author: php 4 | 5 | branding: 6 | icon: package 7 | color: purple 8 | 9 | inputs: 10 | extension-url: 11 | description: URL to the extension repo 12 | required: false 13 | extension-ref: 14 | description: Git reference in the extension repo 15 | required: false 16 | auth-token: 17 | description: Auth token 18 | required: false 19 | php-version-list: 20 | description: PHP versions to build 21 | required: false 22 | arch-list: 23 | description: Architecture to build 24 | required: false 25 | ts-list: 26 | description: Thread safety to build 27 | required: false 28 | allow-old-php-versions: 29 | description: Allow old PHP versions 30 | required: false 31 | default: 'false' 32 | 33 | outputs: 34 | matrix: 35 | description: The matrix for building PHP extensions 36 | value: ${{ steps.get-matrix.outputs.matrix }} 37 | 38 | runs: 39 | using: composite 40 | steps: 41 | - name: Checkout 42 | uses: actions/checkout@v4 43 | 44 | - name: Setup PHP 45 | uses: shivammathur/setup-php@v2 46 | with: 47 | tools: none 48 | 49 | - name: Get Matrix 50 | id: get-matrix 51 | shell: bash 52 | run: | 53 | bash ${{ github.action_path }}/src/extension-matrix.sh 54 | env: 55 | EXTENSION_URL: ${{inputs.extension-url}} 56 | EXTENSION_REF: ${{inputs.extension-ref}} 57 | PHP_VERSION_LIST: ${{inputs.php-version-list}} 58 | ARCH_LIST: ${{inputs.arch-list}} 59 | TS_LIST: ${{inputs.ts-list}} 60 | ALLOW_OLD_PHP_VERSIONS: ${{inputs.allow-old-php-versions}} 61 | AUTH_TOKEN: ${{inputs.auth-token}} 62 | -------------------------------------------------------------------------------- /extension-matrix/config/vs.json: -------------------------------------------------------------------------------- 1 | { 2 | "7.0": { 3 | "vs": "2015", 4 | "os": "windows-2012", 5 | "type": "self-hosted" 6 | }, 7 | "7.1": { 8 | "vs": "2015", 9 | "os": "windows-2012", 10 | "type": "self-hosted" 11 | }, 12 | "7.2": { 13 | "vs": "2019", 14 | "os": "windows-2019", 15 | "type": "github-hosted" 16 | }, 17 | "7.3": { 18 | "vs": "2019", 19 | "os": "windows-2019", 20 | "type": "github-hosted" 21 | }, 22 | "7.4": { 23 | "vs": "2019", 24 | "os": "windows-2019", 25 | "type": "github-hosted" 26 | }, 27 | "8.0": { 28 | "vs": "2019", 29 | "os": "windows-2022", 30 | "type": "github-hosted" 31 | }, 32 | "8.1": { 33 | "vs": "2019", 34 | "os": "windows-2022", 35 | "type": "github-hosted" 36 | }, 37 | "8.2": { 38 | "vs": "2019", 39 | "os": "windows-2022", 40 | "type": "github-hosted" 41 | }, 42 | "8.3": { 43 | "vs": "2019", 44 | "os": "windows-2022", 45 | "type": "github-hosted" 46 | }, 47 | "8.4": { 48 | "vs": "2022", 49 | "os": "windows-2022", 50 | "type": "github-hosted" 51 | }, 52 | "master": { 53 | "vs": "2022", 54 | "os": "windows-2022", 55 | "dev": true, 56 | "type": "github-hosted" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /extension-matrix/src/extension-matrix.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 4 | 5 | . "$SCRIPT_DIR"/php-versions.sh 6 | 7 | matrix=(); 8 | 9 | [ -z "$EXTENSION_URL" ] && EXTENSION_URL="https://github.com/${GITHUB_REPOSITORY:?}" 10 | [ -z "$EXTENSION_REF" ] && EXTENSION_REF="${GITHUB_SHA:?}" 11 | 12 | [ -z "$PHP_VERSION_LIST" ] && \ 13 | PHP_VERSION_LIST="$(get_php_versions "$EXTENSION_URL" "$EXTENSION_REF")" 14 | [ -z "$ARCH_LIST" ] && ARCH_LIST="x64,x86" 15 | [ -z "$TS_LIST" ] && TS_LIST="nts,ts" 16 | 17 | IFS=',' read -r -a php_version_array <<<"${PHP_VERSION_LIST// /}" 18 | IFS=',' read -r -a arch_array <<<"${ARCH_LIST// /}" 19 | IFS=',' read -r -a ts_array <<<"${TS_LIST// /}" 20 | 21 | vs_json="$SCRIPT_DIR"/../config/vs.json 22 | filtered_versions=$(jq -r 'keys | join(" ")' "$vs_json") 23 | if [[ -z "$ALLOW_OLD_PHP_VERSIONS" || "$ALLOW_OLD_PHP_VERSIONS" == "false" ]]; then 24 | filtered_versions=$(jq -r 'to_entries | map(select(.value.type == "github-hosted") | .key) | join(" ")' "$vs_json") 25 | fi 26 | 27 | found='false' 28 | for php_version in "${php_version_array[@]}"; do 29 | if [[ " $filtered_versions " =~ $php_version ]]; then 30 | found='true' 31 | else 32 | continue 33 | fi 34 | os=$(jq -r --arg php_version "$php_version" '.[$php_version].os' "$vs_json") 35 | for arch in "${arch_array[@]}"; do 36 | for ts in "${ts_array[@]}"; do 37 | matrix+=("{\"os\": \"$os\", \"php-version\": \"$php_version\", \"arch\": \"$arch\", \"ts\": \"$ts\"}") 38 | done 39 | done 40 | done 41 | 42 | if [[ "$found" == 'false' ]]; then 43 | echo "No PHP versions found for the specified inputs" 44 | echo "Please refer to the PHP version support in the README" 45 | echo "https://github.com/php/php-windows-builder#php-version-support" 46 | exit 1 47 | fi 48 | 49 | # shellcheck disable=SC2001 50 | echo "matrix={\"include\":[$(echo "${matrix[@]}" | sed -e 's|} {|}, {|g')]}" >> "$GITHUB_OUTPUT" 51 | -------------------------------------------------------------------------------- /extension-matrix/src/php-versions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function compare_versions() { 4 | local version1="$1" 5 | local version2="$2" 6 | 7 | first_sorted=$(printf "%s\n%s\n" "$version1" "$version2" | sort -V | head -n 1) 8 | 9 | if [ "$first_sorted" == "$version1" ]; then 10 | if [ "$version1" == "$version2" ]; then 11 | echo 0 12 | else 13 | echo -1 14 | fi 15 | else 16 | echo 1 17 | fi 18 | } 19 | 20 | function filter_versions() { 21 | local min_version=$1 22 | local max_version=$2 23 | local versions=("${@:3}") 24 | local filtered=() 25 | 26 | for version in "${versions[@]}"; do 27 | low=$(compare_versions "$version" "$min_version") 28 | high=$(compare_versions "$version" "$max_version") 29 | if [ "$low" -ge 0 ] && [ "$high" -le 0 ]; then 30 | filtered+=("$version") 31 | fi 32 | done 33 | 34 | echo "${filtered[@]}" | tr ' ' ',' 35 | } 36 | 37 | function get_extension() { 38 | local directory=$1 39 | if [ -n "$EXTENSION_URL" ]; then 40 | # TODO: Remove this after PECL is deprecated 41 | if [[ "$EXTENSION_URL" = *"pecl.php.net"* ]] && [ -n "$EXTENSION_REF" ]; then 42 | extension="$(basename "$EXTENSION_URL")" 43 | curl -o "$directory/$extension-$EXTENSION_REF.tgz" -sL "https://pecl.php.net/get/$extension-$EXTENSION_REF.tgz" 44 | if ! [ -e "$directory/$extension-$EXTENSION_REF.tgz" ] || file "$directory/$extension-$EXTENSION_REF.tgz" | grep -q HTML; then 45 | extension_upper="$(echo "$extension" | tr '[:lower:]' '[:upper:]')" 46 | curl -o "$directory/$extension-$EXTENSION_REF.tgz" -sL "https://pecl.php.net/get/$extension_upper-$EXTENSION_REF.tgz" 47 | fi 48 | if ! [ -e "$directory/$extension-$EXTENSION_REF.tgz" ] || file "$directory/$extension-$EXTENSION_REF.tgz" | grep -q HTML; then 49 | echo "Extension $extension not found on PECL" 50 | exit 1 51 | fi 52 | tar -xzf "$directory/$extension-$EXTENSION_REF.tgz" -C "$directory" 53 | cp -a "$directory/$extension-$EXTENSION_REF"/* "$directory" 54 | else 55 | [ -n "$AUTH_TOKEN" ] && EXTENSION_URL="https://${AUTH_TOKEN}@${EXTENSION_URL/https:\/\/}" 56 | git -C "$directory" init 57 | git -C "$directory" remote add origin "$EXTENSION_URL" 58 | git -C "$directory" fetch --depth=1 origin "$EXTENSION_REF" 59 | git -C "$directory" checkout FETCH_HEAD 60 | fi 61 | fi 62 | } 63 | 64 | function compare_versions_using_composer() { 65 | local directory=$1 66 | local composer_json=$2 67 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 68 | vs_json="$SCRIPT_DIR"/../config/vs.json 69 | php_versions=$(jq -r 'to_entries | map(select(.value.dev != true)) | map(.key) | join(",")' "$vs_json") 70 | constraint=$(jq -r .require.php "$composer_json") 71 | php "$SCRIPT_DIR"/semver/semver.phar composer.json "$constraint" "$php_versions" 72 | } 73 | 74 | function compare_versions_using_package_xml() { 75 | local directory=$1 76 | local package_xml=$2 77 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 78 | vs_json="$SCRIPT_DIR"/../config/vs.json 79 | php_versions=$(jq -r 'to_entries | map(select(.value.dev != true)) | map(.key) | join(",")' "$vs_json") 80 | php "$SCRIPT_DIR"/semver/semver.phar package.xml "$package_xml" "$php_versions" 81 | } 82 | 83 | function get_package_json() { 84 | local directory=$1 85 | package_xmls=$(find "$directory" -name 'package*.xml') 86 | for file in $package_xmls; do 87 | grep -q '' "$file" && echo "$file" && break 88 | done 89 | } 90 | 91 | function get_php_versions() { 92 | directory=$(mktemp -d) 93 | 94 | get_extension "$directory" > /dev/null 2>&1 95 | 96 | composer_json="$(find "$directory" -name composer.json -exec sh -c 'jq -e ".type == \"php-ext\"" "$1" >/dev/null && echo "$1"' sh {} \; | head -n 1)" 97 | package_xml=$(get_package_json "$directory") 98 | if [ -n "$composer_json" ]; then 99 | compare_versions_using_composer "$directory" "$composer_json" 100 | rm -rf "$directory" 101 | elif [ -n "$package_xml" ]; then 102 | compare_versions_using_package_xml "$directory" "$package_xml" 103 | rm -rf "$directory" 104 | else 105 | echo "No composer.json with type php-ext or package.xml found" 106 | exit 1 107 | fi 108 | } 109 | -------------------------------------------------------------------------------- /extension-matrix/src/semver/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /vendor/ 3 | composer.lock 4 | -------------------------------------------------------------------------------- /extension-matrix/src/semver/app.php: -------------------------------------------------------------------------------- 1 | ' '' ''\n"; 10 | exit(1); 11 | } 12 | 13 | $file = $argv[1]; 14 | if($file === 'composer.json') { 15 | $constraint = $argv[2]; 16 | } else if($file === 'package.xml') { 17 | $package_xml = $argv[2]; 18 | $xml = simplexml_load_file($package_xml); 19 | $namespace = $xml->getNamespaces()[""] ?? "http://pear.php.net/dtd/package-2.0"; 20 | $xml->registerXPathNamespace("p", $namespace); 21 | $min = $xml->xpath("//p:php/p:min")[0] ?? null; 22 | $max = $xml->xpath("//p:php/p:max")[0] ?? null; 23 | $constraint = ''; 24 | if($min) { 25 | $constraint .= '>=' . $min; 26 | } 27 | if($max) { 28 | $constraint .= ',<=' . $max; 29 | } 30 | $constraint = ltrim($constraint, ','); 31 | } else { 32 | echo "File not found"; 33 | exit(1); 34 | } 35 | 36 | $versions = array_filter(explode(',', preg_replace('/\s+/', '', $argv[3]))); 37 | 38 | if (count($versions)) { 39 | $versionParser = new VersionParser(); 40 | $constraint = $versionParser->parseConstraints($constraint); 41 | 42 | $satisfiedVersions = []; 43 | foreach ($versions as $version) { 44 | $parsedVersion = new Constraint('=', $versionParser->normalize($version)); 45 | if ($parsedVersion->matches($constraint)) { 46 | $satisfiedVersions[] = $version; 47 | } 48 | } 49 | 50 | echo implode(',', $satisfiedVersions); 51 | } else { 52 | echo "No versions provided"; 53 | exit(1); 54 | } 55 | -------------------------------------------------------------------------------- /extension-matrix/src/semver/box.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "app.php", 3 | "output": "semver.phar", 4 | "files": ["vendor/autoload.php", "app.php"], 5 | "compression": "GZ", 6 | "git-version": "package_version" 7 | } -------------------------------------------------------------------------------- /extension-matrix/src/semver/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php/composer-semver", 3 | "description": "Parse composer version constraints", 4 | "type": "project", 5 | "require": { 6 | "composer/semver": "^3" 7 | }, 8 | "license": "MIT", 9 | "authors": [ 10 | { 11 | "name": "Shivam Mathur", 12 | "email": "contact@shivammathur.com" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /extension-matrix/src/semver/semver.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/php-windows-builder/4748e423f6e6ae0cb62b91f67c145085cb4dc74d/extension-matrix/src/semver/semver.phar -------------------------------------------------------------------------------- /extension/BuildPhpExtension/BuildPhpExtension.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest. 3 | RootModule = 'BuildPhpExtension' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '1.0.0.0' 7 | 8 | # Supported PSEditions 9 | # CompatiblePSEditions = @() 10 | 11 | # ID used to uniquely identify this module 12 | GUID = '4413aabc-9413-47ae-ba2b-d4656f256abe' 13 | 14 | # Author of this module 15 | Author = 'Shivam Mathur' 16 | 17 | # Company or vendor of this module 18 | CompanyName = 'PHP' 19 | 20 | # Copyright statement for this module 21 | Copyright = 'MIT LICENSE' 22 | 23 | # Description of the functionality provided by this module 24 | Description = 'Build PHP Extension' 25 | 26 | # Minimum version of the PowerShell engine required by this module 27 | PowerShellVersion = '5.0' 28 | 29 | # Name of the PowerShell host required by this module 30 | # PowerShellHostName = '' 31 | 32 | # Minimum version of the PowerShell host required by this module 33 | # PowerShellHostVersion = '' 34 | 35 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 36 | # DotNetFrameworkVersion = '' 37 | 38 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 39 | # ClrVersion = '' 40 | 41 | # Processor architecture (None, X86, Amd64) required by this module 42 | ProcessorArchitecture = 'None' 43 | 44 | # Modules that must be imported into the global environment prior to importing this module 45 | # RequiredModules = @() 46 | 47 | # Assemblies that must be loaded prior to importing this module 48 | # RequiredAssemblies = @() 49 | 50 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 51 | # ScriptsToProcess = @() 52 | 53 | # Type files (.ps1xml) to be loaded when importing this module 54 | # TypesToProcess = @() 55 | 56 | # Format files (.ps1xml) to be loaded when importing this module 57 | # FormatsToProcess = @() 58 | 59 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 60 | # NestedModules = @() 61 | 62 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 63 | FunctionsToExport = @( 64 | # Private functions 65 | 'Add-Boost', 66 | 'Add-BuildLog', 67 | 'Add-BuildRequirements', 68 | 'Add-BuildTools', 69 | 'Add-Dependencies', 70 | 'Add-Extension', 71 | 'Add-ExtensionDependencies', 72 | 'Add-Extensions', 73 | 'Add-OciDB', 74 | 'Add-OciSdk', 75 | 'Add-OdbcCli', 76 | 'Add-Package', 77 | 'Add-Patches', 78 | 'Add-Path', 79 | 'Add-PhpDependencies', 80 | 'Add-StepLog', 81 | 'Add-Vs', 82 | 'Get-ArgumentFromConfig', 83 | 'Get-BuildDirectory', 84 | 'Get-Extension', 85 | 'Get-ExtensionConfig', 86 | 'Get-ExtensionSource', 87 | 'Get-LibrariesFromConfig', 88 | 'Get-OlderVsVersion', 89 | 'Get-PeclLibraryZip', 90 | 'Get-PhpBuild', 91 | 'Get-PhpBuildDetails', 92 | 'Get-PhpDevelBuild', 93 | 'Get-PhpSdk', 94 | 'Get-PhpSrc', 95 | 'Get-TempFiles', 96 | 'Get-VsVersionHelper', 97 | 'Get-VsVersion', 98 | 'Invoke-Build', 99 | 'Invoke-CleanupTempFiles', 100 | 'Invoke-Tests', 101 | 'Set-GAGroup', 102 | 103 | # Public functions 104 | 'Invoke-PhpBuildExtension' 105 | ) 106 | 107 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 108 | CmdletsToExport = '*' 109 | 110 | # Variables to export from this module 111 | VariablesToExport = '*' 112 | 113 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 114 | AliasesToExport = '*' 115 | 116 | # DSC resources to export from this module 117 | # DscResourcesToExport = @() 118 | 119 | # List of all modules packaged with this module 120 | # ModuleList = @() 121 | 122 | # List of all files packaged with this module 123 | # FileList = @() 124 | 125 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 126 | PrivateData = @{ 127 | 128 | PSData = @{ 129 | 130 | # Tags applied to this module. These help with module discovery in online galleries. 131 | Tags = @('php', 'build', 'extensions') 132 | 133 | # A URL to the license for this module. 134 | LicenseUri = 'https://github.com/php/php-windows-builder/blob/master/LICENSE' 135 | 136 | # A URL to the main website for this project. 137 | ProjectUri = 'https://github.com/php/php-windows-builder' 138 | 139 | # A URL to an icon representing this module. 140 | IconUri = 'https://raw.githubusercontent.com/php/php-windows-builder/master/extension/BuildPhpExtension/images/php.png' 141 | 142 | # ReleaseNotes of this module 143 | # ReleaseNotes = '' 144 | 145 | # Prerelease string of this module 146 | # Prerelease = '' 147 | 148 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save 149 | # RequireLicenseAcceptance = $false 150 | 151 | # External dependent modules of this module 152 | # ExternalModuleDependencies = @() 153 | } 154 | } 155 | 156 | # HelpInfoURI = '' 157 | 158 | # DefaultCommandPrefix = '' 159 | 160 | } 161 | 162 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/BuildPhpExtension.psm1: -------------------------------------------------------------------------------- 1 | Set-StrictMode -Version 2.0 2 | $ErrorActionPreference = 'Stop' 3 | $PSDefaultParameterValues['*:ErrorAction'] = 'Stop' 4 | $ConfirmPreference = 'None' 5 | $WarningPreference = 'Continue' 6 | $InformationPreference = 'Continue' 7 | 8 | $scripts = 9 | @(Get-ChildItem -Path $PSScriptRoot\private\*.ps1 -Depth 1) + 10 | @(Get-ChildItem -Path $PSScriptRoot\public\*.ps1 -Depth 1) 11 | 12 | foreach ($script in $scripts) { 13 | Write-Debug "Including $($script.FullName)" 14 | Import-Module $script.FullName 15 | } 16 | 17 | Export-ModuleMember -Function $scripts.Basename 18 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/apc.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "ext-apcu": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "enable-apc" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/http.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "ext-raphf": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "enable-http" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/ibm_db2.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "odbc_cli": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "with-ibm_db2=../deps" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/mongodb.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "openssl": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "enable-mongodb" 9 | }, 10 | { 11 | "name": "with-mongodb-sasl=yes" 12 | }, 13 | { 14 | "name": "with-mongodb-client-side-encryption=yes" 15 | } 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/oci8.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "instantclient": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "with-oci8-19=../deps,shared" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/parle.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "php-ext": { 3 | "configure-options": [ 4 | { 5 | "name": "enable-parle=shared" 6 | }, 7 | { 8 | "name": "disable-parle-utf32" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/pdo_ibm.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "odbc_cli": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "with-pdo-ibm=../deps" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/pdo_oci.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "instantclient": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "with-pdo-oci=../deps,shared" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/phalcon.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "ext-psr": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "enable-phalcon" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/redis.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "php-ext": { 3 | "configure-options": [ 4 | { 5 | "name": "enable-redis" 6 | }, 7 | { 8 | "name": "enable-redis-session" 9 | }, 10 | { 11 | "name": "disable-redis-igbinary" 12 | } 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/scoutapm.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "libcurl": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "enable-scoutapm" 9 | } 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/var_representation.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "php-ext": { 3 | "configure-options": [ 4 | { 5 | "name": "enable-var_representation=shared" 6 | } 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/stubs/xdebug.composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "zlib": "*" 4 | }, 5 | "php-ext": { 6 | "configure-options": [ 7 | { 8 | "name": "with-xdebug" 9 | }, 10 | { 11 | "name": "with-xdebug-compression" 12 | } 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/task.bat: -------------------------------------------------------------------------------- 1 | 2 | call phpize 2>&1 3 | call configure --with-php-build="..\deps" OPTIONS --with-mp="disable" 2>&1 4 | nmake /nologo 2>&1 5 | exit %errorlevel% 6 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/config/vs.json: -------------------------------------------------------------------------------- 1 | { 2 | "php": { 3 | "7.1": "vc14", 4 | "7.2": "vc15", 5 | "7.3": "vc15", 6 | "7.4": "vc15", 7 | "8.0": "vs16", 8 | "8.1": "vs16", 9 | "8.2": "vs16", 10 | "8.3": "vs16", 11 | "8.4": "vs17", 12 | "master": "vs17" 13 | }, 14 | "vs" : { 15 | "vc14": { 16 | "major": 14, 17 | "minorMin": 0, 18 | "minorMax": 9, 19 | "components": [ 20 | "Microsoft.VisualStudio.Component.CoreBuildTools", 21 | "Microsoft.VisualStudio.Component.VC.140", 22 | "Microsoft.VisualStudio.Component.VC.ATL", 23 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 24 | ] 25 | }, 26 | "vc15": { 27 | "major": 14, 28 | "minorMin": 10, 29 | "minorMax": 19, 30 | "components": [ 31 | "Microsoft.VisualStudio.Component.CoreBuildTools", 32 | "Microsoft.VisualStudio.Component.VC.v141.x86.x64", 33 | "Microsoft.VisualStudio.Component.VC.ATL", 34 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 35 | ] 36 | }, 37 | "vs16": { 38 | "major": 14, 39 | "minorMin": 20, 40 | "minorMax": 29, 41 | "components": [ 42 | "Microsoft.VisualStudio.Component.CoreBuildTools", 43 | "Microsoft.VisualStudio.ComponentGroup.VC.Tools.142.x86.x64", 44 | "Microsoft.VisualStudio.Component.VC.ATL", 45 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 46 | ] 47 | }, 48 | "vs17": { 49 | "major": 14, 50 | "minorMin": 30, 51 | "minorMax": null, 52 | "components": [ 53 | "Microsoft.VisualStudio.Component.CoreBuildTools", 54 | "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", 55 | "Microsoft.VisualStudio.Component.VC.ATL", 56 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 57 | ] 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/images/php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/php-windows-builder/4748e423f6e6ae0cb62b91f67c145085cb4dc74d/extension/BuildPhpExtension/images/php.png -------------------------------------------------------------------------------- /extension/BuildPhpExtension/images/php.png.LICENSE: -------------------------------------------------------------------------------- 1 | The author Colin Viebrock released the PHP logo as Creative CommonsAttribution-Share Alike 4.0 International 2 | (https://creativecommons.org/licenses/by-sa/4.0/). 3 | 4 | No changes have been made to it. 5 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/base58.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jasny/base58-php-ext/refs/heads/master/config.w32" -OutFile "config.w32" 2 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/crypto.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/bukka/php-crypto/4516e22160a32ea09b2e547ceebd9a009fc6b597/crypto_cipher.c" -OutFile "crypto_cipher.c" 2 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/bukka/php-crypto/4516e22160a32ea09b2e547ceebd9a009fc6b597/crypto_hash.c" -OutFile "crypto_hash.c" 3 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/grpc.ps1: -------------------------------------------------------------------------------- 1 | $fn = @" 2 | ARG_WITH("grpc", "grpc support", "no"); 3 | function CreateFolderIfMissing(path) { 4 | if (!path) return; 5 | if (!FSO.FolderExists(path)) { 6 | WScript.Echo("Creating " + path + "..."); 7 | FSO.CreateFolder(path); 8 | } 9 | } 10 | "@ 11 | (Get-Content config.w32) | ForEach-Object { $_.Replace('base_dir+"\\ext\\grpc', 'base_dir+"') } | Set-Content config.w32 12 | (Get-Content config.w32) | ForEach-Object { $_.Replace('FSO.CreateFolder', 'CreateFolderIfMissing') } | Set-Content config.w32 13 | (Get-Content config.w32) | ForEach-Object { $_ -replace '/D_WIN32_WINNT=0x600', '/D_WIN32_WINNT=0x600 /FS /std:c++17' } | Set-Content config.w32 14 | (Get-Content config.w32) | ForEach-Object { $_.Replace('ARG_WITH("grpc", "grpc support", "no");', $fn) } | Set-Content config.w32 15 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/hrtime.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri "https://github.com/php/pecl-datetime-hrtime/archive/53fed8cf2cf57f5df8c22e9b0bb50a44a75571c2.zip" -OutFile "$ENV:TEMP/hrtime.zip" 2 | Expand-Archive -Path "$ENV:TEMP/hrtime.zip" -DestinationPath "$ENV:TEMP" 3 | Copy-Item -Path $env:TEMP/pecl-datetime-hrtime-53fed8cf2cf57f5df8c22e9b0bb50a44a75571c2/* -Destination (Get-Location).Path -Recurse -Force 4 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/lua.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri https://raw.githubusercontent.com/laruence/php-lua/f7012e45faf6431e3c45bbfef683a6ec7180d86b/lua.c -OutFile lua.c 2 | Invoke-WebRequest -Uri https://raw.githubusercontent.com/laruence/php-lua/f7012e45faf6431e3c45bbfef683a6ec7180d86b/lua_closure.c -OutFile lua_closure.c 3 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/memcache.ps1: -------------------------------------------------------------------------------- 1 | (Get-Content src\memcache_pool.h) | ForEach-Object { $_ -replace 'win32/php_stdint.h', 'stdint.h' } | Set-Content src\memcache_pool.h 2 | (Get-Content src\memcache_binary_protocol.c) | ForEach-Object { $_ -replace 'win32/php_stdint.h', 'stdint.h' } | Set-Content src\memcache_binary_protocol.c 3 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/memcached.ps1: -------------------------------------------------------------------------------- 1 | (Get-Content php_memcached_private.h) | ForEach-Object { $_ -replace '"php_stdint.h"', '' } | Set-Content php_memcached_private.h 2 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/oauth.ps1: -------------------------------------------------------------------------------- 1 | Set-Content config.w32 -Value (Get-Content config.w32 | Where-Object { $_ -notmatch 'zlib' }) 2 | (Get-Content config.w32) | ForEach-Object { $_.Replace('CHECK_LIB("normaliz.lib", "oauth", PHP_OAUTH)', 'CHECK_LIB("normaliz.lib", "oauth", PHP_OAUTH) && CHECK_LIB("zlib.lib;zlib_a.lib", "oauth", PHP_OAUTH) && CHECK_LIB("crypt32.lib", "oauth", PHP_OAUTH)') } | Set-Content config.w32 3 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/pdo_sqlsrv.ps1: -------------------------------------------------------------------------------- 1 | (Get-Content config.w32) | ForEach-Object { $_ -replace '/sdl', '' } | Set-Content config.w32 2 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/ps.ps1: -------------------------------------------------------------------------------- 1 | Invoke-Webrequest -Uri https://raw.githubusercontent.com/steinm/ps/97cf818c3ef715a28b755b9d5b3ee5a2686356e7/config.w32 -OutFile config.w32 2 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/raphf.ps1: -------------------------------------------------------------------------------- 1 | $fn = @" 2 | ARG_ENABLE("raphf", "for raphf support", "no"); 3 | 4 | base_dir = get_define('BUILD_DIR'); 5 | WScript.Echo("Creating " + base_dir + "\\src" + "..."); 6 | FSO.CreateFolder(base_dir+"\\src"); 7 | "@ 8 | 9 | (Get-Content config.w32) | ForEach-Object { $_.Replace('ARG_ENABLE("raphf", "for raphf support", "no");', $fn) } | Set-Content config.w32 10 | (Get-Content config.w32) | ForEach-Object { $_.Replace('ADD_SOURCES', '//ADD_SOURCES') } | Set-Content config.w32 -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/rar.ps1: -------------------------------------------------------------------------------- 1 | Invoke-Webrequest -Uri https://raw.githubusercontent.com/cataphract/php-rar/253682388809e1371ff8e3180e673fc4f1c69e99/config.w32 -OutFile config.w32 -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/request.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri "https://github.com/pmjones/ext-request/archive/d55b408a1b5e465dd4e74020982edaa43a335ad3.zip" -OutFile "$ENV:TEMP/request.zip" 2 | Expand-Archive -Path "$ENV:TEMP/request.zip" -DestinationPath "$ENV:TEMP" 3 | Copy-Item -Path $env:TEMP/ext-request-d55b408a1b5e465dd4e74020982edaa43a335ad3/* -Destination (Get-Location).Path -Recurse -Force 4 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/scrypt.ps1: -------------------------------------------------------------------------------- 1 | $file = @( 2 | "crypto/params.c", 3 | "crypto/sha256.c", 4 | "crypto/sha256.h", 5 | "crypto/sysendian.h", 6 | "crypto/crypto_scrypt-nosse.c", 7 | "crypto/crypto_scrypt.h", 8 | "php_scrypt_utils.h" 9 | ) 10 | foreach ($f in $file) { 11 | (Get-Content $f) | ForEach-Object { $_ -replace '"win32/php_stdint.h"', '' } | Set-Content $f 12 | } 13 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/sqlsrv.ps1: -------------------------------------------------------------------------------- 1 | (Get-Content config.w32) | ForEach-Object { $_ -replace '/sdl', '' } | Set-Content config.w32 2 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/tensor.ps1: -------------------------------------------------------------------------------- 1 | Invoke-Webrequest -Uri https://raw.githubusercontent.com/RubixML/Tensor/9e9281957fb9223122d1ef77bf5343897492225d/ext/config.w32 -OutFile ext\config.w32 2 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/xxtea.ps1: -------------------------------------------------------------------------------- 1 | (Get-Content php_xxtea.c) | ForEach-Object { $_ -replace 'win32/php_stdint.h', 'stdint.h' } | Set-Content php_xxtea.c -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/yaf.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri "https://github.com/laruence/yaf/archive/cd933d806d0016c8cadcc0c2f0996ebdc2e5d4b8.zip" -OutFile "$ENV:TEMP/yaf.zip" 2 | Expand-Archive -Path "$ENV:TEMP/yaf.zip" -DestinationPath "$ENV:TEMP" 3 | Copy-Item -Path $env:TEMP/yaf-cd933d806d0016c8cadcc0c2f0996ebdc2e5d4b8/* -Destination (Get-Location).Path -Recurse -Force 4 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/yar.ps1: -------------------------------------------------------------------------------- 1 | (Get-Content yar_request.c) | ForEach-Object { 2 | $_ -replace 'if \(!BG\(mt_rand_is_seeded\)\) {', 3 | '#if PHP_VERSION_ID < 80200 4 | if (!BG(mt_rand_is_seeded)) { 5 | #else 6 | if (!RANDOM_G(mt19937_seeded)) { 7 | #endif' 8 | } | Set-Content yar_request.c 9 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/patches/zip.ps1: -------------------------------------------------------------------------------- 1 | Invoke-WebRequest -Uri https://raw.githubusercontent.com/pierrejoye/php_zip/master/config.w32 -OutFile config.w32 2 | $fn = @" 3 | ADD_FLAG("LDFLAGS_ZIP", "/FORCE:MULTIPLE"); 4 | AC_DEFINE('HAVE_LIBZIP', 1); 5 | "@ 6 | (Get-Content config.w32) | ForEach-Object { $_.Replace("AC_DEFINE('HAVE_LIBZIP', 1);", $fn) } | Set-Content config.w32 7 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Boost.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Boost { 2 | <# 3 | .SYNOPSIS 4 | Add boost library. 5 | #> 6 | [OutputType()] 7 | param( 8 | ) 9 | begin { 10 | } 11 | process { 12 | $url = "https://archives.boost.io/release/1.72.0/source/boost_1_72_0.zip" 13 | Invoke-WebRequest $url -OutFile "boost.zip" 14 | Expand-Archive -Path "boost.zip" -DestinationPath "../deps" 15 | } 16 | end { 17 | } 18 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-BuildLog.ps1: -------------------------------------------------------------------------------- 1 | function Add-BuildLog 2 | { 3 | <# 4 | .SYNOPSIS 5 | Add a message to the build log. 6 | .PARAMETER Mark 7 | Mark as success or failure 8 | .PARAMETER Subject 9 | Subject of the message 10 | .PARAMETER Message 11 | Message to add to the build log 12 | #> 13 | [OutputType()] 14 | param( 15 | [Parameter(Mandatory = $true, Position = 0, HelpMessage = 'Mark as success or failure')] 16 | [string] $Mark, 17 | [Parameter(Mandatory = $true, Position = 1, HelpMessage = 'Subject of the message')] 18 | [string] $Subject, 19 | [Parameter(Mandatory = $true, Position = 2, HelpMessage = 'Message to add to the build log')] 20 | [string] $Message 21 | ) 22 | begin { 23 | $tick = ([char]8730) 24 | $cross = ([char]10007) 25 | } 26 | process { 27 | if($Mark -eq 'tick') { 28 | $colorCode = 32; $MarkValue = $tick 29 | } else { 30 | $colorCode = 31; $MarkValue = $cross 31 | } 32 | $esc = [char]27 33 | $blue = "${esc}[34;1m" 34 | $grey = "${esc}[90;1m" 35 | $reset = "${esc}[0m" 36 | "$MarkValue $Subject $Message" | Out-File build.log -Append -Encoding UTF8 37 | Write-Host "${esc}[$colorCode;1m$MarkValue$reset $blue$Subject$reset $grey$Message$reset" 38 | } 39 | end { 40 | } 41 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-BuildRequirements.ps1: -------------------------------------------------------------------------------- 1 | function Add-BuildRequirements { 2 | <# 3 | .SYNOPSIS 4 | Add extension build requirements. 5 | .PARAMETER Extension 6 | Extension Name 7 | .PARAMETER ExtensionRef 8 | Extension Reference 9 | .PARAMETER PhpVersion 10 | PHP Version 11 | .PARAMETER Arch 12 | Extension Architecture 13 | .PARAMETER Ts 14 | Extension Thread Safety 15 | .PARAMETER VsVersion 16 | Visual Studio version 17 | .PARAMETER VsToolset 18 | Visual Studio toolset 19 | #> 20 | [OutputType()] 21 | param ( 22 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension Name')] 23 | [ValidateNotNull()] 24 | [ValidateLength(1, [int]::MaxValue)] 25 | [string] $Extension, 26 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Extension Reference')] 27 | [ValidateNotNull()] 28 | [ValidateLength(1, [int]::MaxValue)] 29 | [string] $ExtensionRef, 30 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Version')] 31 | [ValidateNotNull()] 32 | [ValidateLength(1, [int]::MaxValue)] 33 | [string] $PhpVersion, 34 | [Parameter(Mandatory = $true, Position=3, HelpMessage='Extension Architecture')] 35 | [ValidateNotNull()] 36 | [ValidateLength(1, [int]::MaxValue)] 37 | [string] $Arch, 38 | [Parameter(Mandatory = $true, Position=4, HelpMessage='Extension Thread Safety')] 39 | [ValidateNotNull()] 40 | [ValidateLength(1, [int]::MaxValue)] 41 | [string] $Ts, 42 | [Parameter(Mandatory = $true, Position=5, HelpMessage='Visual Studio version')] 43 | [ValidateNotNull()] 44 | [ValidateLength(1, [int]::MaxValue)] 45 | [string] $VsVersion, 46 | [Parameter(Mandatory = $true, Position=6, HelpMessage='Visual Studio toolset')] 47 | [ValidateNotNull()] 48 | [ValidateLength(1, [int]::MaxValue)] 49 | [string] $VsToolset 50 | ) 51 | begin { 52 | } 53 | process { 54 | Get-PhpSdk 55 | $config = Get-ExtensionConfig -Extension $Extension ` 56 | -ExtensionRef $ExtensionRef ` 57 | -PhpVersion $PhpVersion ` 58 | -Arch $Arch ` 59 | -Ts $Ts ` 60 | -VsVersion $VsVersion ` 61 | -VsToolset $VsToolset 62 | $buildDetails = Get-PhpBuildDetails -Config $Config 63 | $prefix = Get-PhpBuild -Config $config -BuildDetails $buildDetails 64 | Get-PhpDevelBuild -Config $config -BuildDetails $buildDetails 65 | Add-Dependencies -Config $config -Prefix $prefix 66 | return $config 67 | } 68 | end { 69 | } 70 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-BuildTools.ps1: -------------------------------------------------------------------------------- 1 | Function Add-BuildTools { 2 | <# 3 | .SYNOPSIS 4 | Add build tools. 5 | .PARAMETER Config 6 | Configuration for the extension. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | if($Config.build_tools.Count -ne 0) { 17 | Add-StepLog "Adding build tools" 18 | } 19 | $Config.build_tools | ForEach-Object { 20 | try { 21 | $tool = $_ 22 | if($null -eq (Get-Command $_ -ErrorAction SilentlyContinue)) { 23 | switch ($_) 24 | { 25 | nasm { 26 | choco install nasm -y --force 27 | Add-Path -Path "$env:ProgramFiles\NASM" 28 | } 29 | cmake { 30 | choco install cmake --installargs 'ADD_CMAKE_TO_PATH=User' -y --force 31 | } 32 | cargo { 33 | choco install rust -y --force 34 | Add-Path -Path "$env:USERPROFILE\.cargo\bin" 35 | } 36 | git { 37 | choco install git.install --params "'/GitAndUnixToolsOnPath /WindowsTerminal /NoAutoCrlf'" -y --force 38 | } 39 | Default { 40 | $program = $_ 41 | $resultLines = (choco search $_ --limit-output) -split "\`r?\`n" 42 | if($resultLines | Where-Object { $_ -match "^$program\|" }) { 43 | choco install $_ -y --force 44 | } 45 | } 46 | } 47 | } else { 48 | switch ($_) 49 | { 50 | # Check if python is actually installed. 51 | python { 52 | $pythonVersion = python --version 2>&1 53 | if($pythonVersion -match "not found") { 54 | choco install python -y --force 55 | } 56 | $pythonPath = (Get-Command python).Source 57 | $pythonHome = Split-Path $pythonPath 58 | [Environment]::SetEnvironmentVariable("PYTHONPATH", $pythonPATH, [System.EnvironmentVariableTarget]::User) 59 | $env:PYTHONPATH = $pythonPath 60 | [Environment]::SetEnvironmentVariable("PYTHONHOME", $pythonHome, [System.EnvironmentVariableTarget]::User) 61 | $env:PYTHONHOME = $pythonHome 62 | } 63 | } 64 | } 65 | Add-BuildLog tick $tool "Added" 66 | } catch { 67 | Add-BuildLog cross $tool "Failed to add $tool" 68 | throw 69 | } 70 | } 71 | } 72 | end { 73 | } 74 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Dependencies.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Dependencies { 2 | <# 3 | .SYNOPSIS 4 | Add a directory to PATH environment variable. 5 | .PARAMETER Config 6 | Configuration for the extension. 7 | .PARAMETER Prefix 8 | Extension build prefix. 9 | #> 10 | [OutputType()] 11 | param( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 13 | [PSCustomObject] $Config, 14 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Extension build prefix')] 15 | [string] $Prefix 16 | ) 17 | begin { 18 | } 19 | process { 20 | Add-PhpDependencies -Config $Config 21 | Add-ExtensionDependencies -Config $Config 22 | Add-Path -PathItem (Join-Path (Get-Location).Path ../deps/bin) 23 | Add-BuildTools -Config $Config 24 | Add-Extensions -Config $Config -Prefix $Prefix 25 | } 26 | end { 27 | } 28 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Extension.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Extension { 2 | <# 3 | .SYNOPSIS 4 | Build a PHP extension. 5 | .PAMAETER Extension 6 | Extension name. 7 | .PARAMETER Config 8 | Configuration for the extension. 9 | .PARAMETER Prefix 10 | Prefix for the builds. 11 | #> 12 | [OutputType()] 13 | param( 14 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension name')] 15 | [PSCustomObject] $Extension, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Configuration for the extension')] 17 | [PSCustomObject] $Config, 18 | [Parameter(Mandatory = $true, Position=2, HelpMessage='Extension build prefix')] 19 | [string] $Prefix 20 | ) 21 | begin { 22 | } 23 | process { 24 | Set-GAGroup start 25 | Invoke-WebRequest -Uri "https://pecl.php.net/get/$Extension" -OutFile "$Extension.tgz" 26 | $currentDirectory = (Get-Location).Path 27 | & tar -xzf "$Extension.tgz" -C $currentDirectory 28 | Set-Location "$Extension-*" 29 | $extensionBuildDirectory = Join-Path -Path (Get-Location).Path -ChildPath $config.build_directory 30 | # Apply patches only for php/php-windows-builder and shivammathur/php-windows-builder 31 | if($null -ne $env:GITHUB_REPOSITORY) { 32 | if($env:GITHUB_REPOSITORY -eq 'php/php-windows-builder' -or $env:GITHUB_REPOSITORY -eq 'shivammathur/php-windows-builder') { 33 | if(Test-Path -PATH $PSScriptRoot\..\patches\$Extension.ps1) { 34 | . $PSScriptRoot\..\patches\$Extension.ps1 35 | } 36 | } 37 | } 38 | $configW32Content = [string](Get-Content -Path "config.w32") 39 | $argument = Get-ArgumentFromConfig $Extension $configW32Content 40 | $bat_content = @() 41 | $bat_content += "" 42 | $bat_content += "call phpize 2>&1" 43 | $bat_content += "call configure --with-php-build=`"..\deps`" $argument --with-mp=`"disable`" --with-prefix=$Prefix 2>&1" 44 | $bat_content += "nmake /nologo 2>&1" 45 | $bat_content += "exit %errorlevel%" 46 | Set-Content -Encoding "ASCII" -Path $Extension-task.bat -Value $bat_content 47 | $builder = "$currentDirectory\php-sdk\phpsdk-starter.bat" 48 | $task = (Get-Item -Path "." -Verbose).FullName + "\$Extension-task.bat" 49 | $suffix = "php_" + (@( 50 | $Config.name, 51 | $Config.ref, 52 | $Config.php_version, 53 | $Config.ts, 54 | $Config.vs_version, 55 | $Config.arch 56 | ) -join "-") 57 | & $builder -c $Config.vs_version -a $Config.Arch -s $Config.vs_toolset -t $task | Tee-Object -FilePath "build-$suffix.txt" 58 | Write-Host (Get-Content "build-$suffix.txt" -Raw) 59 | $includePath = "$currentDirectory\php-dev\include" 60 | New-Item -Path $includePath\ext -Name $Extension -ItemType "directory" | Out-Null 61 | Get-ChildItem -Path (Get-Location).Path -Recurse -Include '*.h', '*.c' | Copy-Item -Destination "$includePath\ext\$Extension" 62 | Copy-Item -Path "$extensionBuildDirectory\*.dll" -Destination "$currentDirectory\php-bin\ext" -Force 63 | Copy-Item -Path "$extensionBuildDirectory\*.lib" -Destination "$currentDirectory\php-dev\lib" -Force 64 | Add-Content -Path "$currentDirectory\php-bin\php.ini" -Value "extension=$Extension" 65 | Set-Location $currentDirectory 66 | Set-GAGroup end 67 | } 68 | end { 69 | } 70 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-ExtensionDependencies.ps1: -------------------------------------------------------------------------------- 1 | Function Add-ExtensionDependencies { 2 | <# 3 | .SYNOPSIS 4 | Add a directory to PATH environment variable. 5 | .PARAMETER Config 6 | Configuration for the extension. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | if($Config.extension_libraries.Count -ne 0) { 17 | Add-StepLog "Adding libraries (third-party)" 18 | } 19 | $Config.extension_libraries | ForEach-Object { 20 | $library = $_.split('-')[0] 21 | try { 22 | switch ($_) 23 | { 24 | boost { 25 | Add-Boost 26 | } 27 | instantclient { 28 | Add-OciSdk -Config $Config 29 | } 30 | odbc_cli { 31 | Add-OdbcCli -Config $Config 32 | } 33 | Default { 34 | $url = "https://downloads.php.net/~windows/pecl/deps/$_" 35 | Invoke-WebRequest -Uri $url -OutFile $_ -UseBasicParsing 36 | Expand-Archive -Path $_ -DestinationPath "..\deps" -Force 37 | if(Test-Path "..\deps\LICENSE") { 38 | Rename-Item -Path "..\deps\LICENSE" -NewName "LICENSE.$library" 39 | } 40 | if(Test-Path "..\deps\lib\ossl-modules") { 41 | Move-Item -Path "..\deps\lib\ossl-modules\*" -Destination "..\deps\lib" 42 | Remove-Item -Path "..\deps\lib\ossl-modules" -Force -Recurse 43 | } 44 | } 45 | } 46 | Add-BuildLog tick "$library" "Added $($_ -replace '\.zip$')" 47 | } catch { 48 | Add-BuildLog cross "$library" "Failed to download $library" 49 | throw 50 | } 51 | } 52 | } 53 | end { 54 | } 55 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Extensions.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Extensions { 2 | <# 3 | .SYNOPSIS 4 | Add PHP extensions. 5 | .PARAMETER Config 6 | Configuration for the extension. 7 | .PARAMETER Prefix 8 | Prefix for the builds. 9 | #> 10 | [OutputType()] 11 | param( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 13 | [PSCustomObject] $Config, 14 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Extension build prefix')] 15 | [string] $Prefix 16 | ) 17 | begin { 18 | } 19 | process { 20 | if($config.extensions.Count -ne 0) { 21 | Add-StepLog "Adding extensions" 22 | } 23 | $config.extensions | ForEach-Object { 24 | $extension = $_ 25 | try { 26 | Add-Extension -Extension $extension -Config $Config -Prefix $Prefix 27 | Add-BuildLog tick $extension "Added" 28 | } catch { 29 | Add-BuildLog cross $extension "Failed to add $extension" 30 | throw 31 | } 32 | } 33 | } 34 | end { 35 | } 36 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-OciDB.ps1: -------------------------------------------------------------------------------- 1 | Function Add-OciDB { 2 | <# 3 | .SYNOPSIS 4 | Add OCI DB. 5 | #> 6 | [OutputType()] 7 | param( 8 | ) 9 | begin { 10 | } 11 | process { 12 | $dbUrl = 'https://download.oracle.com/otn-pub/otn_software/db-express/OracleXE213_Win64.zip' 13 | $dbZipFile = 'OracleXE213_Win64.zip' 14 | Invoke-WebRequest $dbUrl -OutFile $dbZipFile -UseBasicParsing -Verbose 15 | New-Item -ItemType Directory -Path C:\tools\oracle-setup -Force | Out-Null 16 | New-Item -ItemType Directory -Path C:\tools\oracle -Force | Out-Null 17 | Expand-Archive -Path $dbZipFile -DestinationPath C:\tools\oracle-setup -Force 18 | $rspContent = Get-Content -Path C:\tools\oracle-setup\XEInstall.rsp 19 | $rspContent = $rspContent -replace 'PASSWORD=.*', "PASSWORD=pass" 20 | $rspContent = $rspContent -replace 'INSTALLDIR=.*', "INSTALLDIR=C:\tools\oracle\" 21 | Set-Content -Path C:\tools\oracle-setup\XEInstall-new.rsp -Value $rspContent 22 | cmd.exe /c 'C:\tools\oracle-setup\setup.exe /s /v"RSP_FILE=C:\tools\oracle-setup\XEInstall-new.rsp" /v"/L*v C:\tools\oracle-setup\setup.log" /v"/qn"' 23 | } 24 | end { 25 | } 26 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-OciSdk.ps1: -------------------------------------------------------------------------------- 1 | Function Add-OciSdk { 2 | <# 3 | .SYNOPSIS 4 | Add sdk for OCI extensions. 5 | .PARAMETER Config 6 | The directory to add to PATH. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | $suffix = if ($Config.arch -eq "x64") {"windows"} else {"nt"} 17 | @('sdk', 'basic') | ForEach-Object { 18 | $url = "https://download.oracle.com/otn_software/nt/instantclient/instantclient-$_-$suffix.zip" 19 | Invoke-WebRequest $url -OutFile "instantclient-$_.zip" 20 | Expand-Archive -Path "instantclient-$_.zip" -DestinationPath "../deps" -Force 21 | } 22 | Copy-Item ../deps/instantclient_*/sdk/* -Destination "../deps" -Recurse -Force 23 | New-Item -ItemType Directory -Path "../deps/bin" -Force | Out-Null 24 | Copy-Item ../deps/instantclient_*/* -Destination "../deps" -Recurse -Force 25 | Add-Path -PathItem (Join-Path (Get-Location).Path ../deps) 26 | } 27 | end { 28 | } 29 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-OdbcCli.ps1: -------------------------------------------------------------------------------- 1 | Function Add-OdbcCli { 2 | <# 3 | .SYNOPSIS 4 | Add sdk for DB2 extension. 5 | .PARAMETER Config 6 | Configuration for the extension. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | $prefix = if ($Config.arch -eq "x64") {"ntx64"} else {"nt32"} 17 | $url = "https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/${prefix}_odbc_cli.zip" 18 | Invoke-WebRequest $url -OutFile "odbc_cli.zip" 19 | Expand-Archive -Path "odbc_cli.zip" -DestinationPath "../deps" 20 | Copy-Item ../deps/clidriver/* -Destination "../deps" -Recurse -Force 21 | } 22 | end { 23 | } 24 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Package.ps1: -------------------------------------------------------------------------------- 1 | function Add-Package { 2 | <# 3 | .SYNOPSIS 4 | Create a package for the extension. 5 | .PARAMETER Config 6 | Extension Configuration 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension Configuration')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | Add-StepLog "Packaging $($Config.name) extension" 17 | try { 18 | Set-GAGroup start 19 | $currentDirectory = (Get-Location).Path 20 | New-Item -Path $currentDirectory\artifacts -ItemType Directory -Force | Out-Null 21 | $docsFiles = @("LICENSE", "COPYRIGHT", "COPYING") 22 | $docsFiles | ForEach-Object { 23 | if(Test-Path -Path $_) { 24 | Copy-Item -Path $_ -Destination artifacts -Force 25 | } 26 | } 27 | if(Test-Path ..\deps) { 28 | Get-ChildItem -Path ..\deps -Recurse -Filter "LICENSE*" | ForEach-Object { 29 | if(Test-Path -Path $_ -PathType Leaf) { 30 | Copy-Item -Path $_.FullName -Destination artifacts -Force 31 | } 32 | } 33 | } 34 | $Config.docs | ForEach-Object { 35 | if($null -ne $_) { 36 | $directoryPath = [System.IO.Path]::GetDirectoryName($_) 37 | $targetDir = Join-Path -Path artifacts -ChildPath $directoryPath 38 | New-Item -ItemType Directory -Path $targetDir -Force | Out-Null 39 | Copy-Item -Path $_ -Destination $targetDir -Force 40 | } 41 | } 42 | Get-ChildItem -Path $Config.build_directory -Recurse -Filter "*.dll" | ForEach-Object { 43 | Copy-Item -Path $_.FullName -Destination artifacts -Force 44 | } 45 | Get-ChildItem -Path "artifacts\*.dll" | ForEach-Object { 46 | $pdbFilePath = Join-Path -Path $Config.build_directory -ChildPath ($_.BaseName + ".pdb") 47 | if (Test-Path -Path $pdbFilePath) { 48 | Copy-Item -Path $pdbFilePath -Destination artifacts -Force 49 | } 50 | } 51 | 52 | if(Test-Path ..\deps\bin) { 53 | $dllMap = Invoke-WebRequest -Uri "https://downloads.php.net/~windows/pecl/deps/dllmapping.json" 54 | Get-ChildItem -Path ..\deps\bin -Recurse -Include "*.dll" | ForEach-Object { 55 | if($dllMap.content.Contains($_.Name)) { 56 | if(-not(Test-Path "php-bin\$($_.Name)")) { 57 | Copy-Item -Path $_.FullName -Destination artifacts -Force 58 | } 59 | } 60 | } 61 | Get-ChildItem -Path ..\deps\bin -Recurse -Include "*.pdb" | ForEach-Object { 62 | if(Test-Path "artifacts\$($_.Name.Replace('.pdb', '.dll'))") { 63 | Copy-Item -Path $_.FullName -Destination artifacts -Force 64 | } 65 | } 66 | if(Test-Path (Join-Path -Path ..\deps\bin -ChildPath "*.xml")) { 67 | New-Item -ItemType Directory -Path artifacts\config -Force | Out-Null 68 | Get-ChildItem -Path ..\deps\bin -Recurse -Filter "*.xml" | ForEach-Object { 69 | Copy-Item -Path $_.FullName -Destination artifacts\config -Force 70 | } 71 | } 72 | } 73 | 74 | Set-Location $currentDirectory\artifacts 75 | if(Test-Path -Path "vc140.pdb") { 76 | Remove-Item -Path "vc140.pdb" -Force 77 | } 78 | 79 | # Keep only the extension DLL for ddtrace. 80 | if($Config.name -eq 'ddtrace') { 81 | Get-ChildItem -Filter "*.dll" | ForEach-Object { 82 | if($_.Name -ne "php_$($Config.name).dll") { 83 | Remove-Item -Path $_.FullName -Force 84 | } 85 | } 86 | } 87 | 88 | # As per https://github.com/ThePHPF/pie-design#windows-binaries 89 | $arch = $Config.arch 90 | if(-not(Test-Path -Path "php_$($Config.name).dll")) { 91 | throw "Failed to build extension" 92 | } 93 | if($env:ARTIFACT_NAMING_SCHEME -eq 'pecl') { 94 | $artifact = "php_$($Config.package_name)-$($Config.ref.ToLower())-$($Config.php_version)-$($Config.ts)-$($Config.vs_version)-$arch" 95 | } else { 96 | if($arch -eq 'x64') { 97 | $arch = 'x86_64' 98 | } 99 | $artifact = "php_$($Config.package_name)-$($Config.ref)-$($Config.php_version)-$($Config.ts)-$($Config.vs_version)-$arch" 100 | @("php_$($Config.name).dll", "php_$($Config.name).pdb") | ForEach-Object { 101 | $extension = $_.Split('.')[1] 102 | if(Test-Path -Path $_) { 103 | Move-Item -Path $_ -Destination "$artifact.$extension" -Force 104 | } 105 | } 106 | } 107 | Add-Content "artifact=$artifact.zip" -Path $env:GITHUB_OUTPUT -Encoding utf8 108 | 109 | 7z a -sdel "$artifact.zip" * 110 | 111 | Set-Location $currentDirectory 112 | New-Item -Path $currentDirectory\artifacts\logs -ItemType Directory -Force | Out-Null 113 | Copy-Item -Path build-*.txt -Destination artifacts\logs\ -Force 114 | Set-Location $currentDirectory\artifacts\logs 115 | 7z a -sdel "$artifact.zip" * 116 | Set-GAGroup end 117 | Add-BuildLog tick "Packaging" "Extension $($Config.name) packaged successfully" 118 | } catch { 119 | Add-BuildLog cross "Packaging" "Failed to package $($Config.name) extension" 120 | throw 121 | } 122 | } 123 | end { 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Patches.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Patches { 2 | <# 3 | .SYNOPSIS 4 | Add patches to the extension. 5 | .PARAMETER Extension 6 | The extension name. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $Extension 14 | ) 15 | begin { 16 | } 17 | process { 18 | # Apply patches only for php/php-windows-builder and shivammathur/php-windows-builder 19 | if($null -ne $env:GITHUB_REPOSITORY) { 20 | if($env:GITHUB_REPOSITORY -eq 'php/php-windows-builder' -or $env:GITHUB_REPOSITORY -eq 'shivammathur/php-windows-builder') { 21 | if(Test-Path -PATH $PSScriptRoot\..\patches\$Extension.ps1) { 22 | . $PSScriptRoot\..\patches\$Extension.ps1 23 | } 24 | } 25 | } 26 | } 27 | end { 28 | } 29 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-Path.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Path { 2 | <# 3 | .SYNOPSIS 4 | Add a directory to PATH environment variable. 5 | .PARAMETER PathItem 6 | The directory to add to PATH. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Path to Add')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PathItem 14 | ) 15 | begin { 16 | } 17 | process { 18 | $currentUserPath = [System.Environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::User) 19 | $machinePath = [System.Environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::Machine) 20 | $currentPath = $currentUserPath + ";" + $machinePath 21 | if (-not($currentPath.Split(';').Contains(($PathItem + ";")))) { 22 | $newUserPath = $PathItem + ";" + $currentUserPath 23 | [System.Environment]::SetEnvironmentVariable("PATH", $newUserPath, [System.EnvironmentVariableTarget]::User) 24 | $machinePath = [System.Environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::Machine) 25 | $env:PATH = $newUserPath + ";" + $machinePath 26 | } 27 | } 28 | end { 29 | } 30 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-PhpDependencies.ps1: -------------------------------------------------------------------------------- 1 | Function Add-PhpDependencies { 2 | <# 3 | .SYNOPSIS 4 | Add a directory to PATH environment variable. 5 | .PARAMETER Config 6 | Configuration for the extension. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | if($Config.php_libraries.Count -ne 0) { 17 | Add-StepLog "Adding libraries (core)" 18 | } 19 | $phpBaseUrl = 'https://downloads.php.net/~windows/php-sdk/deps' 20 | $phpTrunkBaseUrl = "https://downloads.php.net/~windows/php-sdk/deps/$($Config.vs_version)/$($Config.arch)" 21 | $phpSeries = Invoke-WebRequest -Uri "$phpBaseUrl/series/packages-$($Config.php_version)-$($Config.vs_version)-$($Config.arch)-staging.txt" -UseBasicParsing 22 | $phpTrunk = Invoke-WebRequest -Uri $phpTrunkBaseUrl -UseBasicParsing 23 | foreach ($library in $Config.php_libraries) { 24 | try { 25 | $matchesFound = $phpSeries.Content | Select-String -Pattern "(^|\n)$library.*" 26 | if ($matchesFound.Count -eq 0) { 27 | foreach ($file in $phpTrunk.Links.Href) { 28 | if ($file -match "^$library") { 29 | $matchesFound = $file | Select-String -Pattern '.*' 30 | break 31 | } 32 | } 33 | } 34 | if ($matchesFound.Count -eq 0) { 35 | throw "Failed to find $library" 36 | } 37 | $file = $matchesFound.Matches[0].Value.Trim() 38 | Invoke-WebRequest "$phpBaseUrl/$($Config.vs_version)/$($Config.arch)/$file" -OutFile $library 39 | Expand-Archive $library "../deps" 40 | Add-BuildLog tick "$library" "Added $($file -replace '\.zip$')" 41 | } catch { 42 | Add-BuildLog cross "$library" "Failed to download $library" 43 | throw 44 | } 45 | } 46 | } 47 | end { 48 | } 49 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-StepLog.ps1: -------------------------------------------------------------------------------- 1 | function Add-StepLog 2 | { 3 | <# 4 | .SYNOPSIS 5 | Add a message to the build log. 6 | .PARAMETER Message 7 | Message to add to the build log 8 | #> 9 | [OutputType()] 10 | param( 11 | [Parameter(Mandatory = $true, Position = 0, HelpMessage = 'Message to add to the step log')] 12 | [string] $Message 13 | ) 14 | begin { 15 | } 16 | process { 17 | $esc = [char]27 18 | $grey = "${esc}[90;1m" 19 | $white = "${esc}[37;1m" 20 | $reset = "${esc}[0m" 21 | "$Message" | Out-File -FilePath build.log -Append -Encoding UTF8 22 | Write-Host "`n$grey==> $reset$white$Message$reset" 23 | } 24 | end { 25 | } 26 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Add-VS.ps1: -------------------------------------------------------------------------------- 1 | function Add-Vs { 2 | <# 3 | .SYNOPSIS 4 | Add the required Visual Studio components. 5 | .PARAMETER VsConfig 6 | Visual Studio Configuration 7 | .PARAMETER VsVersion 8 | Visual Studio Version 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Visual Studio Version')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $VsVersion, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Visual Studio Configuration')] 17 | [PSCustomObject] $VsConfig 18 | ) 19 | begin { 20 | $vsWhereUrl = 'https://github.com/microsoft/vswhere/releases/latest/download/vswhere.exe' 21 | } 22 | process { 23 | Add-StepLog "Adding Visual Studio components" 24 | try 25 | { 26 | Set-GAGroup start 27 | $Config = $VsConfig.vs.$VsVersion 28 | 29 | $installerDir = Join-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio" 'Installer' 30 | $vswherePath = Join-Path $installerDir 'vswhere.exe' 31 | if (-not (Test-Path $vswherePath)) { 32 | if (-not (Test-Path $installerDir)) { 33 | New-Item -Path $installerDir -ItemType Directory -Force | Out-Null 34 | } 35 | Invoke-WebRequest -Uri $vsWhereUrl -OutFile $vswherePath -UseBasicParsing 36 | } 37 | 38 | $instances = & $vswherePath -products '*' -format json 2> $null | ConvertFrom-Json 39 | $vsInst = $instances | Select-Object -First 1 40 | 41 | $componentArgs = $Config.components | ForEach-Object { '--add'; $_ } 42 | 43 | if ($vsInst) { 44 | [string]$channel = $vsInst.installationVersion.Split('.')[0] 45 | $productId = $null 46 | if ($vsInst.catalog -and $vsInst.catalog.PSObject.Properties['productId']) { 47 | $productId = $vsInst.catalog.productId 48 | } elseif ($vsInst.PSObject.Properties['productId']) { 49 | $productId = $vsInst.productId 50 | } 51 | if ($productId -match '(Enterprise|Professional|Community)$' ) { 52 | $exe = "vs_$($Matches[1].ToLower()).exe" 53 | } else { 54 | $exe = 'vs_buildtools.exe' 55 | } 56 | 57 | $installerUrl = "https://aka.ms/vs/$channel/release/$exe" 58 | $installerPath = Join-Path $env:TEMP $exe 59 | 60 | Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -UseBasicParsing 61 | 62 | & $installerPath modify ` 63 | --installPath $vsInst.installationPath ` 64 | --quiet --wait --norestart --nocache ` 65 | @componentArgs 2>&1 | ForEach-Object { Write-Host $_ } 66 | } else { 67 | $channel = $VsVersion -replace '\D', '' 68 | $exe = 'vs_buildtools.exe' 69 | $installerUrl = "https://aka.ms/vs/$channel/release/$exe" 70 | $installerPath = Join-Path $env:TEMP $exe 71 | 72 | Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -UseBasicParsing 73 | & $installerPath ` 74 | --quiet --wait --norestart --nocache ` 75 | @componentArgs 2>&1 | ForEach-Object { Write-Host $_ } 76 | } 77 | Set-GAGroup end 78 | Add-BuildLog tick "Visual Studio" "Visual Studio components installed successfully" 79 | } catch { 80 | Add-BuildLog cross "Visual Studio" "Failed to install Visual Studio components" 81 | throw 82 | } 83 | } 84 | end { 85 | } 86 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-ArgumentFromConfig.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ArgumentFromConfig { 2 | <# 3 | .SYNOPSIS 4 | Get the Libraries from the config.w32 file 5 | .PARAMETER Extension 6 | Extension Name 7 | .PARAMETER ConfigW32Content 8 | config.w32 content 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension Name')] 13 | [string] $Extension, 14 | [Parameter(Mandatory = $true, Position=1, HelpMessage='config.w32 content')] 15 | [string] $ConfigW32Content 16 | ) 17 | begin { 18 | } 19 | process { 20 | $buildArgPrefix = $null; 21 | $dashedExtension = $Extension -replace "_", "-" 22 | if($configW32Content.contains("ARG_ENABLE(`"$dashedExtension`"") -or $configW32Content.contains("ARG_ENABLE('$dashedExtension'")) { 23 | $buildArgPrefix = "enable" 24 | } elseif($configW32Content.contains("ARG_WITH(`"$dashedExtension`"") -or $configW32Content.contains("ARG_WITH('$dashedExtension'")) { 25 | $buildArgPrefix = "with" 26 | } elseif($configW32Content.contains("ARG_ENABLE(`"$extension`"") -or $configW32Content.contains("ARG_ENABLE('$extension'")) { 27 | $buildArgPrefix = "enable" 28 | $dashedExtension = $Extension 29 | } elseif($configW32Content.contains("ARG_WITH(`"$extension`"") -or $configW32Content.contains("ARG_WITH('$extension'")) { 30 | $buildArgPrefix = "with" 31 | $dashedExtension = $Extension 32 | } 33 | 34 | $argValue=''; 35 | if($ConfigW32Content.Contains("PHP_$($Extension.ToUpper())_SHARED")) { 36 | $argValue = "shared" 37 | } 38 | 39 | $arg='' 40 | if($null -ne $buildArgPrefix) { 41 | $arg="--$buildArgPrefix-$dashedExtension" 42 | } 43 | if($argValue -ne '') { 44 | $arg="$arg=$argValue" 45 | } 46 | return $arg 47 | } 48 | end { 49 | } 50 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-BuildDirectory.ps1: -------------------------------------------------------------------------------- 1 | Function Get-BuildDirectory { 2 | <# 3 | .SYNOPSIS 4 | Get the directory to build the extension. 5 | .PARAMETER ParentBuildDirectory 6 | Parent directory to create the build directory. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $false, Position=0, HelpMessage='Parent directory to create the build directory.')] 11 | [string] $ParentBuildDirectory = "" 12 | ) 13 | begin { 14 | } 15 | process { 16 | if($ParentBuildDirectory -eq "") { 17 | if ($null -ne $env:BUILD_DIRECTORY -and $env:BUILD_DIRECTORY -ne "") { 18 | $ParentBuildDirectory = $env:BUILD_DIRECTORY 19 | } else { 20 | $ParentBuildDirectory = [System.IO.Path]::GetTempPath() 21 | } 22 | } 23 | 24 | $buildDirectory = [System.Guid]::NewGuid().ToString().substring(0, 8) 25 | 26 | $buildDirectoryPath = [System.IO.Path]::Combine($ParentBuildDirectory, $buildDirectory) 27 | 28 | New-Item "$buildDirectoryPath" -ItemType "directory" -Force > $null 2>&1 29 | 30 | return $buildDirectoryPath 31 | } 32 | end { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-Extension.ps1: -------------------------------------------------------------------------------- 1 | function Get-Extension { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP extension. 5 | .PARAMETER ExtensionUrl 6 | Extension URL 7 | .PARAMETER ExtensionRef 8 | Extension Reference 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension URL')] 13 | [string] $ExtensionUrl, 14 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Extension Reference')] 15 | [string] $ExtensionRef 16 | ) 17 | begin { 18 | } 19 | process { 20 | Add-StepLog "Fetching extension from $ExtensionUrl" 21 | try { 22 | if( 23 | ($null -eq $ExtensionUrl -or $null -eq $ExtensionRef) -or 24 | ($ExtensionUrl -eq '' -or $ExtensionRef -eq '') 25 | ) { 26 | throw "Both Extension URL and Extension Reference are required." 27 | } 28 | $currentDirectory = (Get-Location).Path 29 | if($null -ne $ExtensionUrl -and $null -ne $ExtensionRef) { 30 | if ($ExtensionUrl -like "*pecl.php.net*") { 31 | $extension = Split-Path -Path $ExtensionUrl -Leaf 32 | try { 33 | Invoke-WebRequest -Uri "https://pecl.php.net/get/$extension-$ExtensionRef.tgz" -OutFile "$extension-$ExtensionRef.tgz" -UseBasicParsing 34 | } catch {} 35 | if(-not(Test-Path "$extension-$ExtensionRef.tgz")) { 36 | try { 37 | Invoke-WebRequest -Uri "https://pecl.php.net/get/$($extension.ToUpper())-$ExtensionRef.tgz" -OutFile "$extension-$ExtensionRef.tgz" -UseBasicParsing 38 | } catch {} 39 | } 40 | & tar -xzf "$extension-$ExtensionRef.tgz" -C $currentDirectory 41 | Copy-Item -Path "$extension-$ExtensionRef\*" -Destination $currentDirectory -Recurse -Force 42 | Remove-Item -Path "$extension-$ExtensionRef" -Recurse -Force 43 | } else { 44 | if($null -ne $env:AUTH_TOKEN) { 45 | $ExtensionUrl = $ExtensionUrl -replace '^https://', "https://${Env:AUTH_TOKEN}@" 46 | } 47 | git init > $null 2>&1 48 | git remote add origin $ExtensionUrl > $null 2>&1 49 | git fetch --depth=1 origin $ExtensionRef > $null 2>&1 50 | git checkout FETCH_HEAD > $null 2>&1 51 | } 52 | } 53 | 54 | $patches = $False 55 | if(Test-Path -PATH $PSScriptRoot\..\patches\$extension.ps1) { 56 | if((Get-Content $PSScriptRoot\..\patches\$extension.ps1).Contains('config.w32')) { 57 | Add-Patches $extension 58 | $patches = $True 59 | } 60 | } 61 | 62 | $configW32 = Get-ChildItem (Get-Location).Path -Recurse -Filter "config.w32" -ErrorAction SilentlyContinue 63 | if($null -eq $configW32) { 64 | throw "No config.w32 found" 65 | } 66 | $subDirectory = $configW32.DirectoryName 67 | if((Get-Location).Path -ne $subDirectory) { 68 | Copy-Item -Path "${subDirectory}\*" -Destination $currentDirectory -Recurse -Force 69 | Remove-Item -Path $subDirectory -Recurse -Force 70 | } 71 | $configW32Content = Get-Content -Path "config.w32" 72 | $extensionLine = $configW32Content | Select-String -Pattern '\s+(ZEND_)?EXTENSION\(' | Select-Object -Last 1 73 | if($null -eq $extensionLine) { 74 | throw "No extension found in config.w32" 75 | } 76 | $name = ($extensionLine -replace '.*EXTENSION\(([^,]+),.*', '$1') -replace '["'']', '' 77 | if($name.Contains('oci8')) { 78 | $name = 'oci8_19' 79 | } elseif ([string]$configW32Content -match ($([regex]::Escape($name)) + '\s*=\s*["''](.+?)["'']')) { 80 | if($matches[1] -ne 'no') { 81 | $name = $matches[1] 82 | } 83 | } 84 | 85 | if(!$patches) { 86 | Add-Patches $name 87 | } 88 | Add-BuildLog tick $name "Fetched $name extension" 89 | return $name 90 | } catch { 91 | Add-BuildLog cross extension "Failed to fetch extension from $ExtensionUrl" 92 | throw 93 | } 94 | } 95 | end { 96 | } 97 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-ExtensionConfig.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ExtensionConfig { 2 | <# 3 | .SYNOPSIS 4 | Get the configuration for the extension. 5 | .PARAMETER Extension 6 | Extension Name 7 | .PARAMETER ExtensionRef 8 | Extension Reference 9 | .PARAMETER PhpVersion 10 | PHP Version 11 | .PARAMETER Arch 12 | Extension Architecture 13 | .PARAMETER Ts 14 | Extension Thread Safety 15 | .PARAMETER VsVersion 16 | Visual Studio version 17 | .PARAMETER VsToolset 18 | Visual Studio toolset 19 | #> 20 | [OutputType()] 21 | param( 22 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension Name')] 23 | [ValidateNotNull()] 24 | [ValidateLength(1, [int]::MaxValue)] 25 | [string] $Extension, 26 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Extension Ref')] 27 | [ValidateNotNull()] 28 | [ValidateLength(1, [int]::MaxValue)] 29 | [string] $ExtensionRef, 30 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Version')] 31 | [ValidateNotNull()] 32 | [ValidateLength(1, [int]::MaxValue)] 33 | [string] $PhpVersion, 34 | [Parameter(Mandatory = $true, Position=3, HelpMessage='Extension Architecture')] 35 | [ValidateNotNull()] 36 | [ValidateLength(1, [int]::MaxValue)] 37 | [string] $Arch, 38 | [Parameter(Mandatory = $true, Position=4, HelpMessage='Extension Thread Safety')] 39 | [ValidateNotNull()] 40 | [ValidateLength(1, [int]::MaxValue)] 41 | [string] $Ts, 42 | [Parameter(Mandatory = $true, Position=5, HelpMessage='Visual Studio version')] 43 | [ValidateNotNull()] 44 | [ValidateLength(1, [int]::MaxValue)] 45 | [string] $VsVersion, 46 | [Parameter(Mandatory = $true, Position=6, HelpMessage='Visual Studio toolset')] 47 | [ValidateNotNull()] 48 | [ValidateLength(1, [int]::MaxValue)] 49 | [string] $VsToolset 50 | ) 51 | begin { 52 | } 53 | process { 54 | try { 55 | Add-StepLog "Reading build configuration for $Extension" 56 | if(-not(Test-Path composer.json)) 57 | { 58 | if(Test-Path $PSScriptRoot\..\config\stubs\$Extension.composer.json) { 59 | Copy-Item $PSScriptRoot\..\config\stubs\$Extension.composer.json composer.json 60 | } 61 | } 62 | $ref = $ExtensionRef 63 | if ($ref -match 'refs/pull/(\d+)/merge') { 64 | $ref = $Matches[1] 65 | } 66 | $packageName = $Extension 67 | if($Extension.Contains("oci8")) { 68 | $packageName = "oci8" 69 | } 70 | if($Extension.Contains("ddtrace")) { 71 | $packageName = "datadog_trace" 72 | } 73 | $config = [PSCustomObject]@{ 74 | name = $Extension 75 | package_name = $packageName 76 | ref = $ref 77 | php_version = $PhpVersion 78 | arch = $Arch 79 | ts = $Ts 80 | vs_version = $VsVersion 81 | vs_toolset = $VsToolset 82 | debug_symbols = $True 83 | options = @() 84 | php_libraries = @() 85 | extension_libraries = @() 86 | build_tools = @() 87 | extensions = @() 88 | docs = @() 89 | build_directory = "" 90 | } 91 | $composerJson = $null 92 | if((-not(Test-Path composer.json)) -and (Test-Path $PSScriptRoot\..\config\stubs\$packageName.composer.json)) { 93 | Copy-Item $PSScriptRoot\..\config\stubs\$packageName.composer.json composer.json 94 | } 95 | if(Test-Path composer.json) { 96 | $composerJson = Get-Content composer.json -Raw | ConvertFrom-Json 97 | } 98 | if($null -ne $composerJson -and $null -ne $composerJson."php-ext") { 99 | $composerJson."php-ext"."configure-options" | ForEach-Object { 100 | $config.options += "--$( $_.name )" 101 | } 102 | } 103 | $config.options = $config.options -join " " 104 | 105 | if($null -ne $env:CONFIGURE_ARGS -and -not([string]::IsNullOrWhiteSpace($env:CONFIGURE_ARGS))) { 106 | $config.options += " $env:CONFIGURE_ARGS" 107 | } 108 | 109 | $Libraries = @() 110 | if($null -ne $env:LIBRARIES -and -not([string]::IsNullOrWhiteSpace($env:LIBRARIES))) { 111 | $Libraries = ($env:LIBRARIES -replace ' ', '') -split ',' 112 | } 113 | 114 | if($null -ne $composerJson) { 115 | $composerJson."require" | ForEach-Object { 116 | $_.PSObject.Properties | ForEach-Object { 117 | if($_.Name -match "ext-") { 118 | $requiredExtension = $_.Name.replace("ext-", "") 119 | if($_.Value -match "\d+\.\d+.*") { 120 | $requiredExtension += "-$($_.Value)" 121 | } 122 | $config.extensions += $requiredExtension 123 | } elseif(-not($_.Name -match "php")) { 124 | # If using the stub composer.json 125 | $Libraries += $_.Name 126 | } 127 | } 128 | } 129 | } 130 | 131 | $configW32Content = [string](Get-Content -Path "config.w32") 132 | if($configW32Content.contains('PATH_PROG')) { 133 | [regex]::Matches($configW32Content, 'PATH_PROG\(([''"])([^''"]+)\1') | ForEach-Object { 134 | $config.build_tools += $_.Groups[2].Value 135 | } 136 | } 137 | if($configW32Content.contains('PYTHONHOME')) { 138 | $config.build_tools += "python" 139 | } 140 | 141 | if($env:AUTO_DETECT_ARGS -eq 'true') { 142 | $argument = Get-ArgumentFromConfig $Extension $configW32Content 143 | $argumentKey = $argument.Split("=")[0] 144 | if($null -ne $argument -and -not($config.options.contains($argumentKey))) { 145 | $config.options += " $argument" 146 | } 147 | } 148 | 149 | if ([System.Environment]::GetEnvironmentVariable("no-debug-symbols-$Extension") -eq 'true') { 150 | $config.debug_symbols = $False 151 | } 152 | 153 | if($env:AUTO_DETECT_LIBS -eq 'true') { 154 | $detectedLibraries = Get-LibrariesFromConfig $Extension $VsVersion $Arch $configW32Content 155 | if($null -ne $detectedLibraries) { 156 | $LibrariesList = $Libraries 157 | $Libraries = $detectedLibraries.Split(" ") 158 | $LibrariesList | ForEach-Object { 159 | $libraryName = $_ 160 | $_ -Match '^(.+?)-\d|' | Out-Null 161 | if($Matches.Count -gt 1) { 162 | $libraryName = $Matches[1] 163 | } 164 | if (-not(($Libraries -Join ' ').Contains($libraryName))) { 165 | $Libraries += $_ 166 | } 167 | } 168 | } 169 | } 170 | 171 | if($Libraries.Count -gt 0) { 172 | $phpSeries = Invoke-WebRequest -Uri "https://downloads.php.net/~windows/php-sdk/deps/$VsVersion/$Arch" 173 | $extensionSeries = Invoke-WebRequest -Uri "https://downloads.php.net/~windows/pecl/deps" 174 | $extensionArchivesSeries = Invoke-WebRequest -Uri "https://downloads.php.net/~windows/pecl/deps/archives" 175 | } 176 | $thirdPartyLibraries = @("boost", "instantclient", "odbc_cli") 177 | $Libraries | Select-Object -Unique | ForEach-Object { 178 | if($thirdPartyLibraries.Contains($_)) { 179 | $config.extension_libraries += $_ 180 | } elseif($null -ne $_ -and -not([string]::IsNullOrWhiteSpace($_))) { 181 | if ($phpSeries.Content.ToLower().Contains($_) -and -not($config.php_libraries.Contains($_))) { 182 | $config.php_libraries += $_ 183 | } elseif (($extensionSeries.Content + $extensionArchivesSeries.Content).ToLower().Contains($_.ToLower()) -and -not($config.extension_libraries.Contains($_))) { 184 | $lib = Get-PeclLibraryZip -Library $_ -PhpVersion $PhpVersion -VsVersion $VsVersion -Arch $Arch -ExtensionSeries $extensionSeries 185 | if($null -ne $lib) { 186 | $config.extension_libraries += $lib 187 | } else { 188 | $lib = Get-PeclLibraryZip -Library $_ -PhpVersion $PhpVersion -VsVersion $VsVersion -Arch $Arch -ExtensionSeries $extensionArchivesSeries 189 | if($null -ne $lib) { 190 | $config.extension_libraries += $lib 191 | } else { 192 | throw "Library $_ not found for the PHP version $PhpVersion and Visual Studio version $VsVersion" 193 | } 194 | } 195 | } else { 196 | throw "Library $_ not found for the PHP version $PhpVersion and Visual Studio version $VsVersion" 197 | } 198 | } 199 | } 200 | 201 | # TODO: This should be implemented using composer.json once implemented 202 | $packageXml = Get-ChildItem (Get-Location).Path -Recurse -Filter "package.xml" -ErrorAction SilentlyContinue 203 | if($null -ne $packageXml) { 204 | $xml = [xml](Get-Content $packageXml.FullName) 205 | $config.docs = $xml.SelectNodes("//*[@role='doc']") | ForEach-Object { 206 | $path = $_.name 207 | $current = $_.ParentNode 208 | while ($null -ne $current -and $current.NodeType -eq "Element" -and $current.get_name() -eq "dir") { 209 | $path = $current.name + '/' + $path 210 | $current = $current.ParentNode 211 | } 212 | if ($path.StartsWith("/")) { 213 | $path = $path.TrimStart("/") 214 | } 215 | $path -replace "/", "\" 216 | } 217 | } 218 | 219 | $config.build_directory = if ($Arch -eq "x64") { "x64\" } else { "" } 220 | $config.build_directory += "Release" 221 | if ($Ts -eq "ts") { $config.build_directory += "_TS" } 222 | Set-GAGroup start 223 | foreach ($prop in $config.PSObject.Properties) { 224 | Write-Host "$($prop.Name): $($prop.Value)" 225 | } 226 | Set-GAGroup end 227 | Add-BuildLog tick $Extension "Build configuration completed" 228 | return $config 229 | } catch { 230 | Add-BuildLog cross $Extension "Failed to read build configuration for $Extension" 231 | throw 232 | } 233 | 234 | } 235 | end { 236 | } 237 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-ExtensionSource.ps1: -------------------------------------------------------------------------------- 1 | function Get-ExtensionSource { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP extension. 5 | .PARAMETER ExtensionUrl 6 | Extension URL 7 | .PARAMETER ExtensionRef 8 | Extension Reference 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $false, Position=0, HelpMessage='Extension URL')] 13 | $ExtensionUrl = '', 14 | [Parameter(Mandatory = $false, Position=1, HelpMessage='Extension Reference')] 15 | $ExtensionRef = '' 16 | ) 17 | begin { 18 | } 19 | process { 20 | if($env:GITHUB_ACTIONS -eq "true") { 21 | if($null -eq $ExtensionUrl -or $ExtensionUrl -eq '') { 22 | $ExtensionUrl = "https://github.com/$env:GITHUB_REPOSITORY" 23 | } 24 | if($null -eq $ExtensionRef -or $ExtensionRef -eq '') { 25 | if($env:GITHUB_EVENT_NAME -contains "pull_request") { 26 | $ExtensionRef = $env:GITHUB_REF 27 | } elseif($null -ne $env:GITHUB_REF_NAME) { 28 | $ExtensionRef = $env:GITHUB_REF_NAME 29 | } else { 30 | $ExtensionRef = $env:GITHUB_SHA 31 | } 32 | } 33 | } 34 | return [PSCustomObject]@{ 35 | url = $ExtensionUrl; 36 | ref = $ExtensionRef 37 | } 38 | } 39 | end { 40 | } 41 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-LibrariesFromConfig.ps1: -------------------------------------------------------------------------------- 1 | Function Get-LibrariesFromConfig { 2 | <# 3 | .SYNOPSIS 4 | Get the Libraries from the config.w32 file 5 | .PARAMETER Extension 6 | Extension 7 | .PARAMETER VsVersion 8 | Visual Studio Version 9 | .PARAMETER Arch 10 | Architecture 11 | .PARAMETER ConfigW32Content 12 | config.w32 content 13 | #> 14 | [OutputType()] 15 | param ( 16 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension')] 17 | [string] $Extension, 18 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Visual Studio Version')] 19 | [string] $VsVersion, 20 | [Parameter(Mandatory = $true, Position=2, HelpMessage='Architecture')] 21 | [string] $Arch, 22 | [Parameter(Mandatory = $true, Position=3, HelpMessage='config.w32 content')] 23 | [string] $ConfigW32Content 24 | ) 25 | begin { 26 | $jsonPath = [System.IO.Path]::Combine($PSScriptRoot, '..\config\vs.json') 27 | } 28 | process { 29 | $jsonData = ( 30 | Invoke-WebRequest -Uri "https://downloads.php.net/~windows/pecl/deps/libmapping.json" 31 | ).Content | ConvertFrom-Json 32 | 33 | $phpSeries = (Invoke-WebRequest -Uri "https://downloads.php.net/~windows/php-sdk/deps/$VsVersion/$Arch").Content.ToLower() 34 | 35 | Function Find-Library { 36 | param ( 37 | [Parameter(Mandatory=$true, Position=0)] 38 | [string]$MatchString, 39 | [Parameter(Mandatory=$true, Position=1)] 40 | [string[]]$VsVersions 41 | ) 42 | foreach ($vsVersion in $VsVersions) { 43 | foreach ($vsVersionData in $JsonData.PSObject.Properties) { 44 | if($vsVersionData.Name -eq $VsVersion) { 45 | foreach ($archData in $vsVersionData.Value.PSObject.Properties) { 46 | if($archData.Name -eq $Arch) { 47 | foreach ($libs in $archData.Value.PSObject.Properties) { 48 | if ($libs.Value -match ($MatchString.Replace('*', '.*'))) { 49 | $libs.Name -Match '^(.+?)-\d' | Out-Null 50 | if(!$phpSeries.contains($matches[1].ToLower())) { 51 | $libs.Name -Match '^(.+?-\d)' | Out-Null 52 | } 53 | return $matches[1] 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | return $null 62 | } 63 | 64 | $jsonContent = Get-Content -Path $jsonPath -Raw 65 | $VsConfig = ConvertFrom-Json -InputObject $jsonContent 66 | $VsVersions = @($VsVersion) 67 | $VsVersions += $($VsConfig.vs | Get-Member -MemberType *Property).Name | Where-Object { 68 | # vs15 and above builds are compatible. 69 | ($_ -lt $VsVersion -and $_ -ge "vc15") 70 | } 71 | 72 | $foundItems = @() 73 | $libraryFilesFound = @() 74 | [regex]::Matches($ConfigW32Content, 'CHECK_LIB\(["'']([^"'']+)["'']|["'']([^"'']+\.lib)["'']|(\w+\.lib)') | ForEach-Object { 75 | $_.Groups[1].Value.Split(';') + ($_.Groups[2].Value -Split '[^\w\.]') + ($_.Groups[3].Value -Split '[^\w\.]') | ForEach-Object { 76 | $libraryFilesFound += $_ 77 | } 78 | } 79 | $libraryFilesFound | Select-Object -Unique | ForEach-Object { 80 | if($_) { 81 | switch ($_) { 82 | libeay32.lib { $library = "openssl" } 83 | ssleay32.lib { $library = "openssl" } 84 | Default { $library = Find-Library $_ $VsVersions } 85 | } 86 | if($library -and (-not($foundItems.Contains($library)))) { 87 | $foundItems += $library.ToLower() 88 | } 89 | } 90 | } 91 | 92 | # Exceptions 93 | # Remove libsasl if the extension is mongodb 94 | if($Extension -eq "mongodb") { 95 | $foundItems = $foundItems | Where-Object {$_ -notmatch "libsasl.*"} 96 | } 97 | # Add zlib if the extension is memcached 98 | if($Extension -eq "memcached") { 99 | $foundItems += "zlib" 100 | } 101 | 102 | $highestVersions = @{} 103 | 104 | foreach ($item in $foundItems) { 105 | if ($item -match '^(.*?)-(\d+)$') { 106 | $libraryName, $version = $matches[1], $matches[2] 107 | if (-not $highestVersions.ContainsKey($libraryName) -or $highestVersions[$libraryName] -lt $version) { 108 | $highestVersions[$libraryName] = $version 109 | } 110 | } else { 111 | $highestVersions[$item] = -1 112 | } 113 | } 114 | 115 | $finalItems = @() 116 | foreach ($library in $highestVersions.Keys) { 117 | if ($highestVersions[$library] -eq -1) { 118 | $finalItems += $library 119 | } else { 120 | $finalItems += "$library-" + $highestVersions[$library] 121 | } 122 | } 123 | 124 | return $finalItems 125 | } 126 | end { 127 | } 128 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-OlderVsVersions.ps1: -------------------------------------------------------------------------------- 1 | function Get-OlderVsVersion { 2 | <# 3 | .SYNOPSIS 4 | Get the Visual Studio version. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PhpVersion 14 | ) 15 | begin { 16 | $jsonPath = [System.IO.Path]::Combine($PSScriptRoot, '..\config\vs.json') 17 | } 18 | process { 19 | $jsonContent = Get-Content -Path $jsonPath -Raw 20 | $VsConfig = ConvertFrom-Json -InputObject $jsonContent 21 | $majorMinor = $PhpVersion.Substring(0, 3) 22 | $vsList = ($VsConfig.vs | Get-Member -MemberType *Property).Name 23 | return $vsList | Where-Object { 24 | # vs15 and above builds are compatible. 25 | ($_ -lt $($VsConfig.php.$majorMinor) -and $_ -ge "vc15") 26 | } 27 | } 28 | end { 29 | } 30 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-PeclLibraryZip.ps1: -------------------------------------------------------------------------------- 1 | function Get-PeclLibraryZip { 2 | <# 3 | .SYNOPSIS 4 | Get the Visual Studio version. 5 | .PARAMETER Library 6 | Library Name 7 | .PARAMETER PhpVersion 8 | PHP Version 9 | .PARAMETER VsVersion 10 | Visual Studio version 11 | .PARAMETER Arch 12 | Architecture 13 | .PARAMETER ExtensionSeries 14 | Extension Series 15 | #> 16 | [OutputType()] 17 | param ( 18 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 19 | [ValidateNotNull()] 20 | [ValidateLength(1, [int]::MaxValue)] 21 | [string] $Library, 22 | [Parameter(Mandatory = $true, Position=1, HelpMessage='PHP Version')] 23 | [ValidateNotNull()] 24 | [ValidateLength(1, [int]::MaxValue)] 25 | [string] $PhpVersion, 26 | [Parameter(Mandatory = $true, Position=2, HelpMessage='Visual Studio version')] 27 | [ValidateNotNull()] 28 | [ValidateLength(1, [int]::MaxValue)] 29 | [string] $VsVersion, 30 | [Parameter(Mandatory = $true, Position=3, HelpMessage='Architecture')] 31 | [ValidateNotNull()] 32 | [ValidateLength(1, [int]::MaxValue)] 33 | [string] $Arch, 34 | [Parameter(Mandatory = $true, Position=4, HelpMessage='Extension Series')] 35 | [ValidateNotNull()] 36 | [PSCustomObject] $ExtensionSeries 37 | ) 38 | begin { 39 | } 40 | process { 41 | $olderVs = Get-OlderVsVersion -PhpVersion $PhpVersion 42 | foreach($vs in ((@($olderVs) + @($VsVersion)) | Sort-Object -Descending)) { 43 | $lib_name, $lib_version = ($Library -split '-')[0, 1] 44 | $key = $lib_name.toLower() + "-?([0-9].*)-$vs-$Arch\.zip" 45 | $options = @() 46 | $ExtensionSeries.Links | ForEach-Object { 47 | if($_.HREF.toLower() -match $key) { 48 | $link_matches = $matches 49 | if($null -eq $lib_version -or $matches[1] -match ('^' + $lib_version + '.*')) 50 | { 51 | if($link_matches[1].Contains('.')) { $suffix="" } else { $suffix=".0" } 52 | $versionParts = $link_matches[1] -split '-' 53 | if($null -ne $versionParts[1] -and $versionParts[1].Contains('.')) { 54 | $versionParts[0] = $versionParts[0] + $versionParts[1].Replace('.', '') 55 | } 56 | $options += @{ 57 | name = ($_.HREF -split ('/') | Select-Object -Last 1) 58 | version = ($versionParts[0] + $suffix) 59 | } 60 | } 61 | } 62 | } 63 | if($options.Count -gt 0) { 64 | $latest = $options | Sort-Object -Property { [version] $_.version } -Descending | Select-Object -First 1 65 | return $latest.name 66 | } 67 | } 68 | } 69 | end { 70 | } 71 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-PhpBuild.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpBuild { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP build. 5 | .PARAMETER Config 6 | Extension Configuration 7 | .PARAMETER BuildDetails 8 | PHP Build Details 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 13 | [PSCustomObject] $Config, 14 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Php Build Details')] 15 | [PSCustomObject] $BuildDetails 16 | ) 17 | begin { 18 | } 19 | process { 20 | try { 21 | Add-StepLog "Adding release build for PHP $( $Config.php_version )" 22 | Add-Type -Assembly "System.IO.Compression.Filesystem" 23 | $phpSemver, $baseUrl, $fallbackBaseUrl = $BuildDetails.phpSemver, $BuildDetails.baseUrl, $BuildDetails.fallbackBaseUrl 24 | $tsPart = if ($Config.ts -eq "nts") { "nts-Win32" } else { "Win32" } 25 | $binZipFile = "php-$phpSemver-$tsPart-$( $Config.vs_version )-$( $Config.arch ).zip" 26 | $binUrl = "$baseUrl/$binZipFile" 27 | $fallBackUrl = "$fallbackBaseUrl/$binZipFile" 28 | 29 | if ($Config.php_version -lt '7.4') { 30 | $fallBackUrl = $fallBackUrl.replace("vc", "VC") 31 | } 32 | 33 | try { 34 | Invoke-WebRequest $binUrl -OutFile $binZipFile 35 | } catch { 36 | try { 37 | Invoke-WebRequest $fallBackUrl -OutFile $binZipFile 38 | } catch { 39 | throw "Failed to download the build for PHP version $( $Config.php_version )." 40 | } 41 | } 42 | 43 | $currentDirectory = (Get-Location).Path 44 | $binZipFilePath = Join-Path $currentDirectory $binZipFile 45 | $binDirectoryPath = Join-Path $currentDirectory php-bin 46 | 47 | [System.IO.Compression.ZipFile]::ExtractToDirectory($binZipFilePath, $binDirectoryPath) 48 | Add-Path -PathItem $binDirectoryPath 49 | Add-Content -Path $binDirectoryPath\php.ini -Value "extension_dir=$binDirectoryPath\ext" 50 | Add-BuildLog tick PHP "PHP release build added successfully" 51 | return $binDirectoryPath 52 | } catch { 53 | Add-BuildLog cross PHP "Failed to download the PHP release build" 54 | throw 55 | } 56 | } 57 | end { 58 | } 59 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-PhpBuildDetails.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpBuildDetails { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP build Details. 5 | .PARAMETER Config 6 | Extension Configuration 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | if($Config.php_version -eq 'master') { 17 | $baseUrl = $fallbackBaseUrl = "https://github.com/shivammathur/php-builder-windows/releases/download/master" 18 | $PhpSemver = $PhpVersion 19 | } else { 20 | foreach($releaseState in @("releases", "qa")) { 21 | $baseUrl = "https://downloads.php.net/~windows/$releaseState" 22 | $fallbackBaseUrl = "https://downloads.php.net/~windows/$releaseState/archives" 23 | $releases = Invoke-WebRequest "$baseUrl/releases.json" | ConvertFrom-Json 24 | $phpSemver = $releases.$($Config.php_version).version 25 | if($null -eq $phpSemver) { 26 | $phpSemver = (Invoke-WebRequest $fallbackBaseUrl).Links | 27 | Where-Object { $_.href -match "php-($($Config.php_version).[0-9]+).*" } | 28 | ForEach-Object { $matches[1] } | 29 | Sort-Object { [System.Version]$_ } -Descending | 30 | Select-Object -First 1 31 | } 32 | if($null -ne $phpSemver) { 33 | break 34 | } 35 | } 36 | } 37 | return [PSCustomObject]@{ 38 | phpSemver = $phpSemver 39 | baseUrl = $baseUrl 40 | fallbackBaseUrl = $fallbackBaseUrl 41 | } 42 | } 43 | end { 44 | } 45 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-PhpDevelBuild.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpDevelBuild { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP build. 5 | .PARAMETER Config 6 | Extension Configuration 7 | .PARAMETER BuildDetails 8 | PHP Build Details 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Configuration for the extension')] 13 | [PSCustomObject] $Config, 14 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Php Build Details')] 15 | [PSCustomObject] $BuildDetails 16 | ) 17 | begin { 18 | } 19 | process { 20 | try { 21 | Add-StepLog "Adding developer build for PHP $($Config.php_version)" 22 | Add-Type -Assembly "System.IO.Compression.Filesystem" 23 | $phpSemver, $baseUrl, $fallbackBaseUrl = $BuildDetails.phpSemver, $BuildDetails.baseUrl, $BuildDetails.fallbackBaseUrl 24 | $tsPart = if ($Config.ts -eq "nts") {"nts-Win32"} else {"Win32"} 25 | $binZipFile = "php-devel-pack-$phpSemver-$tsPart-$($Config.vs_version)-$($Config.arch).zip" 26 | $binUrl = "$baseUrl/$binZipFile" 27 | $fallBackUrl = "$fallbackBaseUrl/$binZipFile" 28 | 29 | if($Config.php_version -lt '7.4') { 30 | $fallBackUrl = $fallBackUrl.replace("vc", "VC") 31 | } 32 | 33 | try { 34 | Invoke-WebRequest $binUrl -OutFile $binZipFile 35 | } catch { 36 | try { 37 | Invoke-WebRequest $fallBackUrl -OutFile $binZipFile 38 | } catch { 39 | throw "Failed to download the build for PHP version $($Config.php_version)." 40 | } 41 | } 42 | 43 | $currentDirectory = (Get-Location).Path 44 | $binZipFilePath = Join-Path $currentDirectory $binZipFile 45 | $binDirectoryPath = Join-Path $currentDirectory php-dev 46 | 47 | [System.IO.Compression.ZipFile]::ExtractToDirectory($binZipFilePath, $binDirectoryPath) 48 | Move-Item $binDirectoryPath/php-*/* $binDirectoryPath/ 49 | Add-Path -PathItem $binDirectoryPath 50 | Add-BuildLog tick PHP "PHP developer build added successfully" 51 | return $binDirectoryPath 52 | } catch { 53 | Add-BuildLog cross PHP "Failed to download the PHP developer build" 54 | throw 55 | } 56 | } 57 | end { 58 | } 59 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-PhpSdk.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpSdk { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP SDK. 5 | #> 6 | [OutputType()] 7 | param ( 8 | ) 9 | begin { 10 | $sdkVersion = "2.4.0" 11 | $url = "https://github.com/php/php-sdk-binary-tools/archive/php-sdk-$sdkVersion.zip" 12 | } 13 | process { 14 | Add-StepLog "Adding PHP SDK" 15 | try 16 | { 17 | Add-Type -Assembly "System.IO.Compression.Filesystem" 18 | 19 | Invoke-WebRequest $url -OutFile php-sdk.zip 20 | $currentDirectory = (Get-Location).Path 21 | $sdkZipFilePath = Join-Path $currentDirectory php-sdk.zip 22 | [System.IO.Compression.ZipFile]::ExtractToDirectory($sdkZipFilePath, $currentDirectory) 23 | Rename-Item -Path php-sdk-binary-tools-php-sdk-$sdkVersion php-sdk 24 | 25 | $sdkDirectoryPath = Join-Path $currentDirectory php-sdk 26 | $sdkBinDirectoryPath = Join-Path $sdkDirectoryPath bin 27 | $sdkMsys2DirectoryPath = Join-Path $sdkDirectoryPath msys2 28 | Add-Path -PathItem $sdkBinDirectoryPath 29 | Add-Path -PathItem $sdkMsys2DirectoryPath 30 | Add-BuildLog tick "PHP SDK" "PHP SDK Added" 31 | } catch { 32 | Add-BuildLog cross "PHP SDK" "Failed to fetch PHP SDK" 33 | throw 34 | } 35 | } 36 | end { 37 | } 38 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-PhpSrc.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpSrc { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP source code. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PhpVersion 14 | ) 15 | begin { 16 | } 17 | process { 18 | Add-Type -Assembly "System.IO.Compression.Filesystem" 19 | 20 | $baseUrl = "https://github.com/php/php-src/archive" 21 | $zipFile = "php-$PhpVersion.zip" 22 | $directory = "php-$PhpVersion-src" 23 | 24 | if ($PhpVersion.Contains(".")) { 25 | $ref = "php-$PhpVersion" 26 | $url = "$baseUrl/PHP-$PhpVersion.zip" 27 | } else { 28 | $ref = $PhpVersion 29 | $url = "$baseUrl/$PhpVersion.zip" 30 | } 31 | 32 | $currentDirectory = (Get-Location).Path 33 | $zipFilePath = Join-Path $currentDirectory $zipFile 34 | $directoryPath = Join-Path $currentDirectory $directory 35 | $srcZipFilePath = Join-Path $currentDirectory "php-$PhpVersion-src.zip" 36 | 37 | Invoke-WebRequest $url -Outfile $zipFile 38 | [System.IO.Compression.ZipFile]::ExtractToDirectory($zipFilePath, $currentDirectory) 39 | Rename-Item -Path "php-src-$ref" -NewName $directory 40 | [System.IO.Compression.ZipFile]::CreateFromDirectory($directoryPath, $srcZipFilePath) 41 | Add-BuildLog tick "php-src" "PHP source for $PhpVersion added" 42 | } 43 | end { 44 | } 45 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-TempFiles.ps1: -------------------------------------------------------------------------------- 1 | Function Get-TempFiles { 2 | $script:initialSystemState = Get-ChildItem -Path "C:\Windows\Temp" -Recurse -File | Select-Object FullName 3 | $script:initialUserState = Get-ChildItem -Path $env:TEMP -Recurse -File | Select-Object FullName 4 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-VsVersion.ps1: -------------------------------------------------------------------------------- 1 | function Get-VsVersion { 2 | <# 3 | .SYNOPSIS 4 | Get the Visual Studio version. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PhpVersion 14 | ) 15 | begin { 16 | $jsonPath = [System.IO.Path]::Combine($PSScriptRoot, '..\config\vs.json') 17 | } 18 | process { 19 | $jsonContent = Get-Content -Path $jsonPath -Raw 20 | $VsConfig = ConvertFrom-Json -InputObject $jsonContent 21 | if($PhpVersion -eq 'master') { $majorMinor = 'master'; } else { $majorMinor = $PhpVersion.Substring(0, 3); } 22 | $VsVersion = $($VsConfig.php.$majorMinor) 23 | $selectedToolset = $null 24 | try { 25 | $selectedToolset = Get-VsVersionHelper -VsVersion $VsVersion -VsConfig $VsConfig 26 | } catch { 27 | Add-Vs -VsVersion $VsVersion -VsConfig $VsConfig 28 | $selectedToolset = Get-VsVersionHelper -VsVersion $VsVersion -VsConfig $VsConfig 29 | } 30 | return [PSCustomObject]@{ 31 | vs = $VsVersion 32 | toolset = $selectedToolset 33 | } 34 | } 35 | end { 36 | } 37 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Get-VsVersionHelper.ps1: -------------------------------------------------------------------------------- 1 | function Get-VsVersionHelper { 2 | <# 3 | .SYNOPSIS 4 | Helper to get the Visual Studio version and toolset. 5 | .PARAMETER VsConfig 6 | Visual Studio Configuration 7 | .PARAMETER VsVersion 8 | Visual Studio Version 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Visual Studio Version')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $VsVersion, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Visual Studio Configuration')] 17 | [PSCustomObject] $VsConfig 18 | ) 19 | begin { 20 | } 21 | process { 22 | if($null -eq (Get-Command vswhere -ErrorAction SilentlyContinue)) { 23 | throw "vswhere is not available" 24 | } 25 | $MSVCDirectory = vswhere -latest -products * -find "VC\Tools\MSVC" 26 | $selectedToolset = $null 27 | $minor = $null 28 | foreach ($toolset in (Get-ChildItem $MSVCDirectory)) { 29 | $toolsetMajorVersion, $toolsetMinorVersion = $toolset.Name.split(".")[0,1] 30 | $requiredVs = $VsConfig.vs.$VsVersion 31 | $majorVersionCheck = [int]$requiredVs.major -eq [int]$toolsetMajorVersion 32 | $minorLowerBoundCheck = [int]$toolsetMinorVersion -ge [int]$requiredVs.minorMin 33 | $minorUpperBoundCheck = ($null -eq $requiredVs.minorMax) -or ([int]$toolsetMinorVersion -le [int]$requiredVs.minorMax) 34 | if ($majorVersionCheck -and $minorLowerBoundCheck -and $minorUpperBoundCheck) { 35 | if($null -eq $minor -or [int]$toolsetMinorVersion -gt [int]$minor) { 36 | $selectedToolset = $toolset.Name.Trim() 37 | $minor = $toolsetMinorVersion 38 | } 39 | } 40 | } 41 | 42 | if (-not $selectedToolset) { 43 | throw "toolset not available" 44 | } 45 | 46 | return $selectedToolset 47 | } 48 | end { 49 | } 50 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Invoke-Build.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-Build { 2 | <# 3 | .SYNOPSIS 4 | Build the extension 5 | .PARAMETER Config 6 | Extension Configuration 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension Configuration')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | Add-StepLog "Building $($Config.name) extension" 17 | try { 18 | Set-GAGroup start 19 | 20 | $builder = "php-sdk\phpsdk-starter.bat" 21 | $task = [System.IO.Path]::Combine($PSScriptRoot, '..\config\task.bat') 22 | 23 | $options = $Config.options 24 | if ($Config.debug_symbols) { 25 | $options += " --enable-debug-pack" 26 | } 27 | Set-Content -Path $task -Value (Get-Content -Path $task -Raw).Replace("OPTIONS", $options) 28 | 29 | $ref = $Config.ref 30 | if($env:ARTIFACT_NAMING_SCHEME -eq 'pecl') { 31 | $ref = $Config.ref.ToLower() 32 | } 33 | $suffix = "php_" + (@( 34 | $Config.name, 35 | $ref, 36 | $Config.php_version, 37 | $Config.ts, 38 | $Config.vs_version, 39 | $Config.arch 40 | ) -join "-") 41 | & $builder -c $Config.vs_version -a $Config.Arch -s $Config.vs_toolset -t $task | Tee-Object -FilePath "build-$suffix.txt" 42 | Set-GAGroup end 43 | if(-not(Test-Path "$((Get-Location).Path)\$($Config.build_directory)\php_$($Config.name).dll")) { 44 | throw "Failed to build the extension" 45 | } 46 | Add-BuildLog tick $Config.name "Extension $($Config.name) built successfully" 47 | } catch { 48 | Add-BuildLog cross $Config.name "Failed to build the extension" 49 | throw 50 | } 51 | } 52 | end { 53 | } 54 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Invoke-CleanupTempFIles.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-CleanupTempFiles { 2 | $currentSystemState = Get-ChildItem -Path "C:\Windows\Temp" -Recurse -File | Select-Object FullName 3 | $currentUserState = Get-ChildItem -Path $env:TEMP -Recurse -File | Select-Object FullName 4 | 5 | $newSystemFiles = Compare-Object -ReferenceObject $script:initialSystemState -DifferenceObject $currentSystemState -Property FullName | Where-Object {$_.SideIndicator -eq "=>"} 6 | $newUserFiles = Compare-Object -ReferenceObject $script:initialUserState -DifferenceObject $currentUserState -Property FullName | Where-Object {$_.SideIndicator -eq "=>"} 7 | $tempFiles = @($newSystemFiles) + @($newUserFiles) 8 | if($tempFiles.Count -gt 0) { 9 | Write-Host "Cleaning up temporary files" 10 | $tempFiles | ForEach-Object { 11 | Write-Host "Removing $($_.FullName)" 12 | try { 13 | Remove-Item -Path $_.FullName -Force 14 | } catch { 15 | Write-Host "Failed to remove $($_.FullName)" 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Invoke-Tests.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-Tests { 2 | <# 3 | .SYNOPSIS 4 | Build the extension 5 | .PARAMETER Config 6 | Extension Configuration 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Extension Configuration')] 11 | [PSCustomObject] $Config 12 | ) 13 | begin { 14 | } 15 | process { 16 | Add-StepLog "Running tests for $($Config.name) extension" 17 | try { 18 | $currentDirectory = (Get-Location).Path 19 | $php_dir = Join-Path $currentDirectory php-bin 20 | $env:TEST_PHP_EXECUTABLE = "$php_dir\php.exe" 21 | $env:REPORT_EXIT_STATUS = 1 22 | $env:XDEBUG_MODE = "" 23 | $env:MAGICK_CONFIGURE_PATH = "$currentDirectory\..\deps\bin" 24 | $env:PHP_AMQP_HOST="rabbitmq" 25 | $env:PHP_AMQP_SSL_HOST="rabbitmq.example.org" 26 | if($Config.name -eq 'pdo_oci') { 27 | Get-PhpSrc -PhpVersion $Config.php_version 28 | $env:PDO_TEST_DIR = "$currentDirectory\php-$($Config.php_version)-src\ext\pdo\tests" 29 | $env:PDO_OCI_TEST_DIR = "$currentDirectory\tests" 30 | } 31 | $tempOriginal = $env:TEMP 32 | Get-TempFiles 33 | $type='extension' 34 | if ((Select-String -Path 'config.w32' -Pattern 'ZEND_EXTENSION\(' -Quiet) -eq $true) { 35 | $type='zend_extension' 36 | } 37 | $extensionPath = "$currentDirectory\$($Config.build_directory)\php_$($Config.name).dll" 38 | $php_args = @( 39 | "-n", 40 | "-d $type=$extensionPath" 41 | ) 42 | $env:TEST_PHP_ARGS = $php_args -join ' ' 43 | if ($null -eq $env:TEST_RUNNER) { 44 | $env:TEST_RUNNER = 'run-tests.php' 45 | } elseif(-not(Test-Path $env:TEST_RUNNER)) { 46 | throw "Test runner $env:TEST_RUNNER does not exist." 47 | } 48 | $test_runner_args = @( 49 | '-q', 50 | '--offline', 51 | '--show-diff', 52 | '--show-slow 1000', 53 | '--set-timeout 120', 54 | '-g FAIL,XFAIL,BORK,WARN,LEAK,SKIP' 55 | ) 56 | $test_workers = 8 57 | if($null -ne $env:TEST_WORKERS -and $env:TEST_WORKERS -ne '') { 58 | $test_workers = $env:TEST_WORKERS 59 | } 60 | if($Config.php_version -ge '7.4') { 61 | $test_runner_args += ('-j' + $test_workers) 62 | } 63 | 64 | $opcacheModes = @($env:TEST_OPCACHE_MODE) 65 | if($env:TEST_OPCACHE_MODE -eq 'both') { 66 | $opcacheModes = @('on', 'off') 67 | } 68 | $success = $True 69 | foreach($opcacheMode in $opcacheModes) { 70 | $suffix = "" 71 | if($env:TEST_OPCACHE_MODE -eq 'both') { 72 | $suffix = " (opcache=$opcacheMode)" 73 | } 74 | Add-StepLog "Running tests for $($Config.name) extension$suffix" 75 | Set-GAGroup start 76 | $tempDirectory = Get-BuildDirectory $currentDirectory 77 | $env:TEMP=$tempDirectory 78 | $env:TMP=$tempDirectory 79 | $test_runner_args += '--temp-source ' + $tempDirectory; 80 | $test_runner_args += '--temp-target ' + $tempDirectory; 81 | $opcache_args = @() 82 | if($opcacheMode -eq 'on') { 83 | $opcache_args += "-d zend_extension=$php_dir\ext\php_opcache.dll" 84 | $opcache_args += "-d opcache.enable=1" 85 | $opcache_args += "-d opcache.enable_cli=1" 86 | $opcache_args += "-d opcache.optimization_level=1" 87 | } else { 88 | $opcache_args += "-d opcache.enable=0" 89 | $opcache_args += "-d opcache.enable_cli=0" 90 | $opcache_args += "-d opcache.optimization_level=0" 91 | } 92 | $phpExpression = @( 93 | 'php', 94 | $env:TEST_RUNNER, 95 | ($test_runner_args -join ' '), 96 | ($opcache_args -join ' ') 97 | ) -join ' ' 98 | Write-Host "Running tests... $phpExpression" 99 | Write-Host "TEST_PHP_ARGS $env:TEST_PHP_ARGS" 100 | Write-Host "TEST_PHP_EXECUTABLE $env:TEST_PHP_EXECUTABLE" 101 | chcp 65001 102 | Invoke-Expression $phpExpression 103 | if ($LASTEXITCODE -ne 0) { 104 | $success = $False 105 | } 106 | $env:TEMP = $tempOriginal 107 | $env:TMP = $tempOriginal 108 | Invoke-CleanupTempFiles 109 | Set-GAGroup end 110 | } 111 | if(-not $success) { 112 | throw "Failed to run tests successfully" 113 | } 114 | Add-BuildLog tick $($Config.name) "Tests run successfully" 115 | } catch { 116 | Add-BuildLog cross $($Config.name) "Failed to run tests successfully" 117 | throw 118 | } 119 | } 120 | end { 121 | } 122 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/private/Set-GAGroup.ps1: -------------------------------------------------------------------------------- 1 | Function Set-GAGroup { 2 | <# 3 | .SYNOPSIS 4 | Start or end a group in GitHub Actions. 5 | .PARAMETER Marker 6 | Start or end marker. 7 | #> 8 | [OutputType()] 9 | param( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Start or end marker')] 11 | [ValidateSet('start', 'end')] 12 | [string] $Marker 13 | ) 14 | begin { 15 | } 16 | process { 17 | if($env:GITHUB_ACTIONS -eq 'true') { 18 | if ($Marker -eq 'start') { 19 | $esc = [char]27 20 | $blue = "${esc}[34;1m" 21 | $reset = "${esc}[0m" 22 | Write-Host "::group::${blue}Logs $reset" 23 | } else { 24 | Write-Host "::endgroup::" 25 | } 26 | } 27 | } 28 | end { 29 | } 30 | } -------------------------------------------------------------------------------- /extension/BuildPhpExtension/public/Invoke-PhpBuildExtension.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-PhpBuildExtension { 2 | <# 3 | .SYNOPSIS 4 | Build PHP Extension 5 | .PARAMETER ExtensionUrl 6 | Extension URL 7 | .PARAMETER ExtensionRef 8 | Extension Reference 9 | .PARAMETER PhpVersion 10 | PHP Version 11 | .PARAMETER Arch 12 | Architecture 13 | .PARAMETER Ts 14 | Thread Safety 15 | .PARAMETER Libraries 16 | Libraries required by the extension 17 | #> 18 | [OutputType()] 19 | param ( 20 | [Parameter(Mandatory = $false, Position=0, HelpMessage='Extension URL')] 21 | [string] $ExtensionUrl = '', 22 | [Parameter(Mandatory = $false, Position=1, HelpMessage='Extension Reference')] 23 | [string] $ExtensionRef = '', 24 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Version')] 25 | [ValidateNotNull()] 26 | [ValidateLength(1, [int]::MaxValue)] 27 | [string] $PhpVersion, 28 | [Parameter(Mandatory = $true, Position=3, HelpMessage='PHP Architecture')] 29 | [ValidateNotNull()] 30 | [ValidateSet('x86', 'x64')] 31 | [string] $Arch, 32 | [Parameter(Mandatory = $true, Position=4, HelpMessage='PHP Build Type')] 33 | [ValidateNotNull()] 34 | [ValidateSet('nts', 'ts')] 35 | [string] $Ts 36 | ) 37 | begin { 38 | } 39 | process { 40 | Set-StrictMode -Off 41 | $VsData = (Get-VsVersion -PhpVersion $PhpVersion) 42 | if($null -eq $VsData.vs) { 43 | throw "PHP version $PhpVersion is not supported." 44 | } 45 | 46 | $currentDirectory = (Get-Location).Path 47 | 48 | $buildDirectory = Get-BuildDirectory 49 | 50 | Set-Location "$buildDirectory" 51 | 52 | $source = Get-ExtensionSource -ExtensionUrl $ExtensionUrl -ExtensionRef $ExtensionRef 53 | 54 | $extension = Get-Extension -ExtensionUrl $source.url -ExtensionRef $source.ref 55 | 56 | $config = Add-BuildRequirements -Extension $extension ` 57 | -ExtensionRef $source.ref ` 58 | -PhpVersion $PhpVersion ` 59 | -Arch $Arch ` 60 | -Ts $Ts ` 61 | -VsVersion $VsData.vs ` 62 | -VsToolset $VsData.toolset 63 | 64 | Invoke-Build -Config $config 65 | 66 | if($env:RUN_TESTS -eq 'true') { 67 | Invoke-Tests -Config $config 68 | } 69 | 70 | Add-Package -Config $config 71 | 72 | Set-Location $currentDirectory 73 | 74 | Move-Item -Path "$buildDirectory\artifacts" -Destination "$currentDirectory" -Force 75 | } 76 | end { 77 | } 78 | } -------------------------------------------------------------------------------- /extension/action.yml: -------------------------------------------------------------------------------- 1 | name: build-php-extension 2 | description: Build PHP Extension 3 | author: php 4 | 5 | branding: 6 | icon: package 7 | color: purple 8 | 9 | inputs: 10 | extension-url: 11 | description: URL to the extension source code 12 | required: false 13 | extension-ref: 14 | description: Git reference in the extension repo 15 | required: false 16 | auth-token: 17 | description: Auth token to fetch the extension source code 18 | required: false 19 | php-version: 20 | description: PHP version to build 21 | required: true 22 | arch: 23 | description: Architecture to build 24 | required: true 25 | ts: 26 | description: Thread safety to build 27 | required: true 28 | args: 29 | description: Additional arguments to pass to the build script 30 | required: false 31 | libs: 32 | description: Libraries required to build the extension 33 | required: false 34 | run-tests: 35 | description: Run tests after building the extension 36 | required: false 37 | default: 'true' 38 | test-runner: 39 | description: Test runner to use 40 | required: false 41 | default: 'run-tests.php' 42 | test-opcache-mode: 43 | description: Test opcache mode 44 | required: false 45 | default: 'off' 46 | test-workers: 47 | description: Test workers 48 | required: false 49 | default: '8' 50 | build-directory: 51 | description: Directory to build the extension in 52 | required: false 53 | default: 'build' 54 | 55 | runs: 56 | using: composite 57 | steps: 58 | - name: Checkout 59 | uses: actions/checkout@v4 60 | 61 | - name: Build PHP 62 | id: build 63 | shell: pwsh 64 | env: 65 | CONFIGURE_ARGS: ${{inputs.args}} 66 | LIBRARIES: ${{inputs.libs}} 67 | ARTIFACT_NAMING_SCHEME: ${{env.artifact-naming-scheme}} 68 | RUN_TESTS: ${{inputs.run-tests}} 69 | TEST_RUNNER: ${{inputs.test-runner}} 70 | TEST_OPCACHE_MODE: ${{inputs.test-opcache-mode}} 71 | TEST_WORKERS: ${{inputs.test-workers}} 72 | BUILD_DIRECTORY: ${{inputs.build-directory}} 73 | AUTH_TOKEN: ${{inputs.auth-token}} 74 | AUTO_DETECT_ARGS: ${{env.auto-detect-args}} 75 | AUTO_DETECT_LIBS: ${{env.auto-detect-libs}} 76 | run: | 77 | Import-Module ${{ github.action_path }}\BuildPhpExtension -Force 78 | Invoke-PhpBuildExtension -ExtensionUrl "${{inputs.extension-url}}" ` 79 | -ExtensionRef "${{inputs.extension-ref}}" ` 80 | -PhpVersion ${{inputs.php-version}} ` 81 | -Arch ${{inputs.arch}} ` 82 | -Ts ${{inputs.ts}} 83 | 84 | - name: Upload the build artifact 85 | uses: actions/upload-artifact@v4 86 | with: 87 | name: ${{ steps.build.outputs.artifact }} 88 | path: artifacts/* 89 | -------------------------------------------------------------------------------- /php/BuildPhp/BuildPhp.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest. 3 | RootModule = 'BuildPhp' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '1.0.0.0' 7 | 8 | # Supported PSEditions 9 | # CompatiblePSEditions = @() 10 | 11 | # ID used to uniquely identify this module 12 | GUID = '4413a8c3-9413-47ae-ba2b-d4656f256abc' 13 | 14 | # Author of this module 15 | Author = 'Shivam Mathur' 16 | 17 | # Company or vendor of this module 18 | CompanyName = 'PHP' 19 | 20 | # Copyright statement for this module 21 | Copyright = 'MIT LICENSE' 22 | 23 | # Description of the functionality provided by this module 24 | Description = 'Build PHP' 25 | 26 | # Minimum version of the PowerShell engine required by this module 27 | PowerShellVersion = '5.0' 28 | 29 | # Name of the PowerShell host required by this module 30 | # PowerShellHostName = '' 31 | 32 | # Minimum version of the PowerShell host required by this module 33 | # PowerShellHostVersion = '' 34 | 35 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 36 | # DotNetFrameworkVersion = '' 37 | 38 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 39 | # ClrVersion = '' 40 | 41 | # Processor architecture (None, X86, Amd64) required by this module 42 | ProcessorArchitecture = 'None' 43 | 44 | # Modules that must be imported into the global environment prior to importing this module 45 | # RequiredModules = @() 46 | 47 | # Assemblies that must be loaded prior to importing this module 48 | # RequiredAssemblies = @() 49 | 50 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 51 | # ScriptsToProcess = @() 52 | 53 | # Type files (.ps1xml) to be loaded when importing this module 54 | # TypesToProcess = @() 55 | 56 | # Format files (.ps1xml) to be loaded when importing this module 57 | # FormatsToProcess = @() 58 | 59 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 60 | # NestedModules = @() 61 | 62 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 63 | FunctionsToExport = @( 64 | # Private functions 65 | 'Add-BuildRequirements', 66 | 'Add-TestRequirements', 67 | 'Add-Vs', 68 | 'Get-OciSdk', 69 | 'Get-PhpBuild', 70 | 'Get-PhpSdk', 71 | 'Get-PhpSrc', 72 | 'Get-PhpTestPack', 73 | 'Get-TestSettings', 74 | 'Get-TestsList' 75 | 'Get-VsVersionHelper', 76 | 'Get-VsVersion', 77 | 'Set-PhpIniForTests' 78 | 79 | # Public functions 80 | 'Invoke-PhpBuild', 81 | 'Invoke-PhpTests' 82 | ) 83 | 84 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 85 | CmdletsToExport = '*' 86 | 87 | # Variables to export from this module 88 | VariablesToExport = '*' 89 | 90 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 91 | AliasesToExport = '*' 92 | 93 | # DSC resources to export from this module 94 | # DscResourcesToExport = @() 95 | 96 | # List of all modules packaged with this module 97 | # ModuleList = @() 98 | 99 | # List of all files packaged with this module 100 | # FileList = @() 101 | 102 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 103 | PrivateData = @{ 104 | 105 | PSData = @{ 106 | 107 | # Tags applied to this module. These help with module discovery in online galleries. 108 | Tags = @('php', 'build', 'extensions') 109 | 110 | # A URL to the license for this module. 111 | LicenseUri = 'https://github.com/php/php-windows-builder/blob/master/LICENSE' 112 | 113 | # A URL to the main website for this project. 114 | ProjectUri = 'https://github.com/php/php-windows-builder' 115 | 116 | # A URL to an icon representing this module. 117 | IconUri = 'https://raw.githubusercontent.com/php/php-windows-builder/master/php/BuildPhp/images/php.png' 118 | 119 | # ReleaseNotes of this module 120 | # ReleaseNotes = '' 121 | 122 | # Prerelease string of this module 123 | # Prerelease = '' 124 | 125 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save 126 | # RequireLicenseAcceptance = $false 127 | 128 | # External dependent modules of this module 129 | # ExternalModuleDependencies = @() 130 | } 131 | } 132 | 133 | # HelpInfoURI = '' 134 | 135 | # DefaultCommandPrefix = '' 136 | 137 | } 138 | 139 | -------------------------------------------------------------------------------- /php/BuildPhp/BuildPhp.psm1: -------------------------------------------------------------------------------- 1 | Set-StrictMode -Version 2.0 2 | $ErrorActionPreference = 'Stop' 3 | $PSDefaultParameterValues['*:ErrorAction'] = 'Stop' 4 | $ConfirmPreference = 'None' 5 | $WarningPreference = 'Continue' 6 | $InformationPreference = 'Continue' 7 | 8 | $scripts = 9 | @(Get-ChildItem -Path $PSScriptRoot\private\*.ps1 -Depth 1) + 10 | @(Get-ChildItem -Path $PSScriptRoot\public\*.ps1 -Depth 1) 11 | 12 | foreach ($script in $scripts) { 13 | Write-Debug "Including $($script.FullName)" 14 | Import-Module $script.FullName 15 | } 16 | 17 | Export-ModuleMember -Function $scripts.Basename 18 | -------------------------------------------------------------------------------- /php/BuildPhp/config/ini/extensions.ini: -------------------------------------------------------------------------------- 1 | extension=php_com_dotnet.dll 2 | extension=php_curl.dll 3 | extension=php_intl.dll 4 | extension=php_mbstring.dll 5 | extension=php_mysqli.dll 6 | extension=php_openssl.dll 7 | extension=php_pdo_mysql.dll 8 | extension=php_pdo_sqlite.dll 9 | extension=php_soap.dll 10 | extension=php_sockets.dll 11 | extension=php_sqlite3.dll 12 | -------------------------------------------------------------------------------- /php/BuildPhp/config/ini/opcache-x64.ini: -------------------------------------------------------------------------------- 1 | opcache.memory_consumption=256 2 | opcache.interned_strings_buffer=16 3 | opcache.max_accelerated_files=8000 4 | opcache.jit_buffer_size=32M 5 | opcache.revalidate_freq=60 6 | opcache.fast_shutdown=1 7 | opcache.enable=1 8 | opcache.enable_cli=1 9 | opcache.error_log=OPCACHE_ERROR_LOG_PATH 10 | opcache.log_verbosity_level=2 11 | opcache.file_cache=OPCACHE_FILE_CACHE_PATH 12 | opcache.file_cache_fallback=1 13 | -------------------------------------------------------------------------------- /php/BuildPhp/config/ini/opcache-x86.ini: -------------------------------------------------------------------------------- 1 | opcache.memory_consumption=128 2 | opcache.interned_strings_buffer=8 3 | opcache.max_accelerated_files=4000 4 | opcache.jit_buffer_size=16M 5 | opcache.revalidate_freq=60 6 | opcache.fast_shutdown=1 7 | opcache.enable=1 8 | opcache.enable_cli=1 9 | opcache.error_log=OPCACHE_ERROR_LOG_PATH 10 | opcache.log_verbosity_level=2 11 | opcache.file_cache=OPCACHE_FILE_CACHE_PATH 12 | opcache.file_cache_fallback=1 13 | -------------------------------------------------------------------------------- /php/BuildPhp/config/test_directories: -------------------------------------------------------------------------------- 1 | ext\com_dotnet\tests 2 | ext\curl\tests 3 | ext\date\tests 4 | ext\dom\tests 5 | ext\hash\tests 6 | ext\intl\tests 7 | ext\json\tests 8 | ext\libxml\tests 9 | ext\mbstring\tests 10 | ext\mysqli\tests 11 | ext\openssl\tests 12 | ext\pcre\tests 13 | ext\pdo_mysql\tests 14 | ext\pdo_sqlite\tests 15 | ext\phar\tests 16 | ext\reflection\tests 17 | ext\session\tests 18 | ext\simplexml\tests 19 | ext\soap\tests 20 | ext\spl\tests 21 | ext\sqlite3\tests 22 | ext\standard\tests 23 | ext\xmlreader\tests 24 | ext\xmlwriter\tests 25 | ext\xml\tests 26 | ext\zip\tests 27 | ext\zlib\tests 28 | Sapi\cgi\tests 29 | Sapi\cli\tests 30 | tests 31 | Zend\tests -------------------------------------------------------------------------------- /php/BuildPhp/config/tests.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "7.0": {"runner": "run-test.php", "workers": "", "progress": ""}, 3 | "7.1": {"runner": "run-test.php", "workers": "", "progress": ""}, 4 | "7.2": {"runner": "run-test.php", "workers": "", "progress": ""}, 5 | "7.3": {"runner": "run-test.php", "workers": "", "progress": ""}, 6 | "7.4": {"runner": "run-test.php", "workers": "-jNumWorkers", "progress": ""}, 7 | "8.0": {"runner": "run-test.php", "workers": "-jNumWorkers", "progress": ""}, 8 | "8.1": {"runner": "run-test.php", "workers": "-jNumWorkers", "progress": ""}, 9 | "8.2": {"runner": "run-tests.php", "workers": "-jNumWorkers", "progress": "--no-progress"}, 10 | "8.3": {"runner": "run-tests.php", "workers": "-jNumWorkers", "progress": "--no-progress"}, 11 | "8.4": {"runner": "run-tests.php", "workers": "-jNumWorkers", "progress": "--no-progress"}, 12 | "default": {"runner": "run-tests.php", "workers": "jNumWorkers", "progress": ""} 13 | } 14 | -------------------------------------------------------------------------------- /php/BuildPhp/config/vc15/x64/config.nts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vc15/x64/config.ts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vc15/x86/config.nts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vc15/x86/config.ts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs.json: -------------------------------------------------------------------------------- 1 | { 2 | "php": { 3 | "7.1": "vc14", 4 | "7.2": "vc15", 5 | "7.3": "vc15", 6 | "7.4": "vc15", 7 | "8.0": "vs16", 8 | "8.1": "vs16", 9 | "8.2": "vs16", 10 | "8.3": "vs16", 11 | "8.4": "vs17", 12 | "master": "vs17" 13 | }, 14 | "vs" : { 15 | "vc14": { 16 | "major": 14, 17 | "minorMin": 0, 18 | "minorMax": 9, 19 | "components": [ 20 | "Microsoft.VisualStudio.Component.CoreBuildTools", 21 | "Microsoft.VisualStudio.Component.VC.140", 22 | "Microsoft.VisualStudio.Component.VC.ATL", 23 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 24 | ] 25 | }, 26 | "vc15": { 27 | "major": 14, 28 | "minorMin": 10, 29 | "minorMax": 19, 30 | "components": [ 31 | "Microsoft.VisualStudio.Component.CoreBuildTools", 32 | "Microsoft.VisualStudio.Component.VC.v141.x86.x64", 33 | "Microsoft.VisualStudio.Component.VC.ATL", 34 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 35 | ] 36 | }, 37 | "vs16": { 38 | "major": 14, 39 | "minorMin": 20, 40 | "minorMax": 29, 41 | "components": [ 42 | "Microsoft.VisualStudio.Component.CoreBuildTools", 43 | "Microsoft.VisualStudio.ComponentGroup.VC.Tools.142.x86.x64", 44 | "Microsoft.VisualStudio.Component.VC.ATL", 45 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 46 | ] 47 | }, 48 | "vs17": { 49 | "major": 14, 50 | "minorMin": 30, 51 | "minorMax": null, 52 | "components": [ 53 | "Microsoft.VisualStudio.Component.CoreBuildTools", 54 | "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", 55 | "Microsoft.VisualStudio.Component.VC.ATL", 56 | "Microsoft.VisualStudio.Component.Windows10SDK.19041" 57 | ] 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /php/BuildPhp/config/vs16/x64/config.nts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--with-pdo-oci=..\..\..\..\instantclient\sdk,shared" "--with-oci8-19=..\..\..\..\instantclient\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs16/x64/config.ts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--with-pdo-oci=..\..\..\..\instantclient\sdk,shared" "--with-oci8-19=..\..\..\..\instantclient\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs16/x86/config.nts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--with-pdo-oci=..\..\..\..\instantclient\sdk,shared" "--with-oci8-19=..\..\..\..\instantclient\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs16/x86/config.ts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--with-pdo-oci=..\..\..\..\instantclient\sdk,shared" "--with-oci8-19=..\..\..\..\instantclient\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs17/x64/config.nts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs17/x64/config.ts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs17/x86/config.nts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/config/vs17/x86/config.ts.bat: -------------------------------------------------------------------------------- 1 | cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--without-analyzer" "--enable-pgi" %* -------------------------------------------------------------------------------- /php/BuildPhp/images/php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/php-windows-builder/4748e423f6e6ae0cb62b91f67c145085cb4dc74d/php/BuildPhp/images/php.png -------------------------------------------------------------------------------- /php/BuildPhp/images/php.png.LICENSE: -------------------------------------------------------------------------------- 1 | The author Colin Viebrock released the PHP logo as Creative CommonsAttribution-Share Alike 4.0 International 2 | (https://creativecommons.org/licenses/by-sa/4.0/). 3 | 4 | No changes have been made to it. 5 | -------------------------------------------------------------------------------- /php/BuildPhp/private/Add-BuildRequirements.ps1: -------------------------------------------------------------------------------- 1 | function Add-BuildRequirements { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP source code. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | .PARAMETER Arch 8 | PHP Architecture 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $PhpVersion, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='PHP Architecture')] 17 | [ValidateNotNull()] 18 | [ValidateSet('x86', 'x64')] 19 | [string] $Arch 20 | ) 21 | begin { 22 | } 23 | process { 24 | Get-OciSdk -Arch $Arch 25 | Get-PhpSdk 26 | Get-PhpSrc -PhpVersion $PhpVersion 27 | } 28 | end { 29 | } 30 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Add-TestRequirements.ps1: -------------------------------------------------------------------------------- 1 | function Add-TestRequirements { 2 | <# 3 | .SYNOPSIS 4 | Set the PHP test requirements. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | .PARAMETER Arch 8 | PHP Architecture 9 | .PARAMETER Ts 10 | PHP Build Type 11 | .PARAMETER VsVersion 12 | VS Version 13 | .PARAMETER TestsDirectory 14 | Tests Directory 15 | #> 16 | [OutputType()] 17 | param ( 18 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 19 | [ValidateNotNull()] 20 | [ValidateLength(1, [int]::MaxValue)] 21 | [string] $PhpVersion, 22 | [Parameter(Mandatory = $true, Position=1, HelpMessage='PHP Architecture')] 23 | [ValidateNotNull()] 24 | [ValidateSet('x86', 'x64')] 25 | [string] $Arch, 26 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Build Type')] 27 | [ValidateNotNull()] 28 | [ValidateSet('nts', 'ts')] 29 | [string] $Ts, 30 | [Parameter(Mandatory = $false, Position=3, HelpMessage='VS Version')] 31 | [ValidateLength(1, [int]::MaxValue)] 32 | [string] $VsVersion, 33 | [Parameter(Mandatory = $false, Position=4, HelpMessage='Tests Directory')] 34 | [ValidateLength(1, [int]::MaxValue)] 35 | [string] $TestsDirectory 36 | ) 37 | begin { 38 | } 39 | process { 40 | Get-PhpBuild -PhpVersion $PhpVersion -Arch $Arch -Ts $Ts -VsVersion $VsVersion 41 | Get-PhpTestPack -PhpVersion $PhpVersion -TestsDirectory $TestsDirectory 42 | } 43 | end { 44 | } 45 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Add-VS.ps1: -------------------------------------------------------------------------------- 1 | function Add-Vs { 2 | <# 3 | .SYNOPSIS 4 | Add the required Visual Studio components. 5 | .PARAMETER VsConfig 6 | Visual Studio Configuration 7 | .PARAMETER VsVersion 8 | Visual Studio Version 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Visual Studio Version')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $VsVersion, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Visual Studio Configuration')] 17 | [PSCustomObject] $VsConfig 18 | ) 19 | begin { 20 | $vsWhereUrl = 'https://github.com/microsoft/vswhere/releases/latest/download/vswhere.exe' 21 | } 22 | process { 23 | $Config = $VsConfig.vs.$VsVersion 24 | 25 | $installerDir = Join-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio" 'Installer' 26 | $vswherePath = Join-Path $installerDir 'vswhere.exe' 27 | if (-not (Test-Path $vswherePath)) { 28 | if (-not (Test-Path $installerDir)) { 29 | New-Item -Path $installerDir -ItemType Directory -Force | Out-Null 30 | } 31 | Invoke-WebRequest -Uri $vsWhereUrl -OutFile $vswherePath -UseBasicParsing 32 | } 33 | 34 | $instances = & $vswherePath -products '*' -format json 2> $null | ConvertFrom-Json 35 | $vsInst = $instances | Select-Object -First 1 36 | 37 | $componentArgs = $Config.components | ForEach-Object { '--add'; $_ } 38 | 39 | if ($vsInst) { 40 | [string]$channel = $vsInst.installationVersion.Split('.')[0] 41 | $productId = $null 42 | if ($vsInst.catalog -and $vsInst.catalog.PSObject.Properties['productId']) { 43 | $productId = $vsInst.catalog.productId 44 | } elseif ($vsInst.PSObject.Properties['productId']) { 45 | $productId = $vsInst.productId 46 | } 47 | if ($productId -match '(Enterprise|Professional|Community)$' ) { 48 | $exe = "vs_$($Matches[1].ToLower()).exe" 49 | } else { 50 | $exe = 'vs_buildtools.exe' 51 | } 52 | 53 | $installerUrl = "https://aka.ms/vs/$channel/release/$exe" 54 | $installerPath = Join-Path $env:TEMP $exe 55 | 56 | Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -UseBasicParsing 57 | 58 | & $installerPath modify ` 59 | --installPath $vsInst.installationPath ` 60 | --quiet --wait --norestart --nocache ` 61 | @componentArgs 2>&1 | ForEach-Object { Write-Host $_ } 62 | } else { 63 | $channel = $VsVersion -replace '\D', '' 64 | $exe = 'vs_buildtools.exe' 65 | $installerUrl = "https://aka.ms/vs/$channel/release/$exe" 66 | $installerPath = Join-Path $env:TEMP $exe 67 | 68 | Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -UseBasicParsing 69 | & $installerPath ` 70 | --quiet --wait --norestart --nocache ` 71 | @componentArgs 2>&1 | ForEach-Object { Write-Host $_ } 72 | } 73 | } 74 | end { 75 | } 76 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-OciSdk.ps1: -------------------------------------------------------------------------------- 1 | function Get-OciSdk { 2 | <# 3 | .SYNOPSIS 4 | Add the OCI SDK for building oci and pdo_oci extensions 5 | 6 | .PARAMETER Arch 7 | The architecture of the OCI sdk. 8 | #> 9 | [OutputType()] 10 | param ( 11 | [Parameter(Mandatory = $true, Position = 0, HelpMessage = 'The architecture of the OCI sdk.')] 12 | [string]$Arch 13 | ) 14 | begin { 15 | $suffix = if ($Arch -eq 'x86') { 'nt' } else { 'windows' } 16 | $url = "https://download.oracle.com/otn_software/nt/instantclient/instantclient-sdk-$suffix.zip" 17 | } 18 | process { 19 | Invoke-WebRequest $url -OutFile "instantclient-sdk.zip" 20 | Expand-Archive -Path "instantclient-sdk.zip" -DestinationPath "." 21 | Move-Item "instantclient_*" "instantclient" 22 | } 23 | end { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-PhpBuild.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpBuild { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP build. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | .PARAMETER Arch 8 | PHP Architecture 9 | .PARAMETER Ts 10 | PHP Build Type 11 | .PARAMETER VsVersion 12 | VS Version 13 | #> 14 | [OutputType()] 15 | param ( 16 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 17 | [ValidateNotNull()] 18 | [ValidateLength(1, [int]::MaxValue)] 19 | [string] $PhpVersion, 20 | [Parameter(Mandatory = $true, Position=1, HelpMessage='PHP Architecture')] 21 | [ValidateNotNull()] 22 | [ValidateSet('x86', 'x64')] 23 | [string] $Arch, 24 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Build Type')] 25 | [ValidateNotNull()] 26 | [ValidateSet('nts', 'ts')] 27 | [string] $Ts, 28 | [Parameter(Mandatory = $false, Position=3, HelpMessage='VS Version')] 29 | [ValidateLength(1, [int]::MaxValue)] 30 | [string] $VsVersion 31 | ) 32 | begin { 33 | } 34 | process { 35 | Add-Type -Assembly "System.IO.Compression.Filesystem" 36 | 37 | if($null -eq $VsVersion) { 38 | $VsVersion = (Get-VsVersion -PhpVersion $PhpVersion) 39 | if($null -eq $VsVersion) { 40 | throw "PHP version $PhpVersion is not supported." 41 | } 42 | } 43 | if($PhpVersion -eq 'master') { 44 | $fallbackBaseUrl = $baseUrl = "https://github.com/shivammathur/php-builder-windows/releases/download/master" 45 | } else { 46 | $releaseState = if ($PhpVersion -match "[a-z]") {"qa"} else {"releases"} 47 | $baseUrl = "https://downloads.php.net/~windows/$releaseState" 48 | $fallbackBaseUrl = "https://downloads.php.net/~windows/$releaseState/archives" 49 | } 50 | $tsPart = if ($Ts -eq "nts") {"nts-Win32"} else {"Win32"} 51 | $binZipFile = "php-$PhpVersion-$tsPart-$VsVersion-$Arch.zip" 52 | $binUrl = "$baseUrl/$binZipFile" 53 | $fallBackUrl = "$fallbackBaseUrl/$binZipFile" 54 | 55 | try { 56 | Invoke-WebRequest $binUrl -OutFile $binZipFile 57 | } catch { 58 | try { 59 | Invoke-WebRequest $fallBackUrl -OutFile $binZipFile 60 | } catch { 61 | throw "Failed to download the build for PHP version $PhpVersion." 62 | } 63 | } 64 | 65 | $currentDirectory = (Get-Location).Path 66 | $binZipFilePath = Join-Path $currentDirectory $binZipFile 67 | $binDirectoryPath = Join-Path $currentDirectory phpbin 68 | 69 | [System.IO.Compression.ZipFile]::ExtractToDirectory($binZipFilePath, $binDirectoryPath) 70 | } 71 | end { 72 | } 73 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-PhpSdk.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpSdk { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP SDK. 5 | #> 6 | [OutputType()] 7 | param ( 8 | ) 9 | begin { 10 | $sdkVersion = "2.4.0" 11 | $url = "https://github.com/php/php-sdk-binary-tools/archive/php-sdk-$sdkVersion.zip" 12 | } 13 | process { 14 | Invoke-WebRequest $url -OutFile php-sdk.zip 15 | Expand-Archive -Path php-sdk.zip -DestinationPath . 16 | Rename-Item -Path php-sdk-binary-tools-php-sdk-$sdkVersion php-sdk 17 | } 18 | end { 19 | } 20 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-PhpSrc.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpSrc { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP source code. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PhpVersion 14 | ) 15 | begin { 16 | } 17 | process { 18 | Add-Type -Assembly "System.IO.Compression.Filesystem" 19 | 20 | $baseUrl = "https://github.com/php/php-src/archive" 21 | $zipFile = "php-$PhpVersion.zip" 22 | $directory = "php-$PhpVersion-src" 23 | 24 | if ($PhpVersion.Contains(".")) { 25 | $ref = "php-$PhpVersion" 26 | $url = "$baseUrl/refs/tags/php-$PhpVersion.zip" 27 | } else { 28 | $ref = $PhpVersion 29 | $url = "$baseUrl/$PhpVersion.zip" 30 | } 31 | 32 | $currentDirectory = (Get-Location).Path 33 | $zipFilePath = Join-Path $currentDirectory $zipFile 34 | $directoryPath = Join-Path $currentDirectory $directory 35 | $srcZipFilePath = Join-Path $currentDirectory "php-$PhpVersion-src.zip" 36 | 37 | Invoke-WebRequest $url -Outfile $zipFile 38 | [System.IO.Compression.ZipFile]::ExtractToDirectory($zipFilePath, $currentDirectory) 39 | Rename-Item -Path "php-src-$ref" -NewName $directory 40 | [System.IO.Compression.ZipFile]::CreateFromDirectory($directoryPath, $srcZipFilePath) 41 | } 42 | end { 43 | } 44 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-PhpTestPack.ps1: -------------------------------------------------------------------------------- 1 | function Get-PhpTestPack { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP source code. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | .PARAMETER TestsDirectory 8 | Tests Directory 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $PhpVersion, 16 | [Parameter(Mandatory = $false, Position=1, HelpMessage='Tests Directory')] 17 | [ValidateLength(1, [int]::MaxValue)] 18 | [string] $TestsDirectory 19 | ) 20 | begin { 21 | } 22 | process { 23 | Add-Type -Assembly "System.IO.Compression.Filesystem" 24 | 25 | if($PhpVersion -eq 'master') { 26 | $fallbackBaseUrl = $baseUrl = "https://github.com/shivammathur/php-builder-windows/releases/download/master" 27 | } else { 28 | $releaseState = if ($PhpVersion -match "[a-z]") {"qa"} else {"releases"} 29 | $baseUrl = "https://downloads.php.net/~windows/$releaseState" 30 | $fallbackBaseUrl = "https://downloads.php.net/~windows/$releaseState/archives" 31 | } 32 | $testZipFile = "php-test-pack-$PhpVersion.zip" 33 | $testUrl = "$baseUrl/$testZipFile" 34 | $fallBackUrl = "$fallbackBaseUrl/$testZipFile" 35 | 36 | try { 37 | Invoke-WebRequest $testUrl -OutFile $testZipFile 38 | } catch { 39 | try { 40 | Invoke-WebRequest $fallBackUrl -OutFile $testZipFile 41 | } catch { 42 | throw "Failed to download the test pack for PHP version $PhpVersion." 43 | } 44 | } 45 | 46 | $currentDirectory = (Get-Location).Path 47 | $testZipFilePath = Join-Path $currentDirectory $testZipFile 48 | $testsDirectoryPath = Join-Path $currentDirectory $TestsDirectory 49 | 50 | [System.IO.Compression.ZipFile]::ExtractToDirectory($testZipFilePath, $testsDirectoryPath) 51 | } 52 | end { 53 | } 54 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-TestSettings.ps1: -------------------------------------------------------------------------------- 1 | function Get-TestSettings { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP test settings. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PhpVersion 14 | ) 15 | begin { 16 | $settings = $null 17 | } 18 | process { 19 | $workers = $Env:NUMBER_OF_PROCESSORS / 2 * 3 20 | 21 | $config = Get-Content "$PSScriptRoot\..\config\tests.config.json" -Raw | ConvertFrom-Json 22 | $majorMinorVersion = $PhpVersion.Substring(0, 3) 23 | if ($config.PSObject.Properties.Name -contains $majorMinorVersion) { 24 | $settings = $config.$majorMinorVersion 25 | } else { 26 | $settings = $config.default 27 | } 28 | 29 | $settings.workers = $settings.workers.Replace('NumWorkers', $workers) 30 | return $settings 31 | } 32 | end { 33 | $settings 34 | } 35 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-TestsList.ps1: -------------------------------------------------------------------------------- 1 | function Get-TestsList { 2 | <# 3 | .SYNOPSIS 4 | Get the PHP test list. 5 | .PARAMETER OutputFile 6 | Output file 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Output file')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $OutputFile 14 | ) 15 | begin { 16 | } 17 | process { 18 | Remove-Item $OutputFile -ErrorAction "Ignore" 19 | foreach ($line in Get-Content "$PSScriptRoot\..\config\test_directories") { 20 | $ttr = Get-ChildItem -Path $line -Filter "*.phpt" -Recurse 21 | foreach ($t in $ttr) { 22 | Add-Content $OutputFile ($t | Resolve-Path -Relative) 23 | } 24 | } 25 | } 26 | end { 27 | } 28 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-VsVersion.ps1: -------------------------------------------------------------------------------- 1 | function Get-VsVersion { 2 | <# 3 | .SYNOPSIS 4 | Get the Visual Studio version. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | #> 8 | [OutputType()] 9 | param ( 10 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 11 | [ValidateNotNull()] 12 | [ValidateLength(1, [int]::MaxValue)] 13 | [string] $PhpVersion 14 | ) 15 | begin { 16 | $jsonPath = [System.IO.Path]::Combine($PSScriptRoot, '..\config\vs.json') 17 | } 18 | process { 19 | $jsonContent = Get-Content -Path $jsonPath -Raw 20 | $VsConfig = ConvertFrom-Json -InputObject $jsonContent 21 | if($PhpVersion -eq 'master') { $majorMinor = 'master'; } else { $majorMinor = $PhpVersion.Substring(0, 3); } 22 | $VsVersion = $($VsConfig.php.$majorMinor) 23 | $selectedToolset = $null 24 | try { 25 | $selectedToolset = Get-VsVersionHelper -VsVersion $VsVersion -VsConfig $VsConfig 26 | } catch { 27 | Add-Vs -VsVersion $VsVersion -VsConfig $VsConfig 28 | $selectedToolset = Get-VsVersionHelper -VsVersion $VsVersion -VsConfig $VsConfig 29 | } 30 | return [PSCustomObject]@{ 31 | vs = $VsVersion 32 | toolset = $selectedToolset 33 | } 34 | } 35 | end { 36 | } 37 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Get-VsVersionHelper.ps1: -------------------------------------------------------------------------------- 1 | function Get-VsVersionHelper { 2 | <# 3 | .SYNOPSIS 4 | Helper to get the Visual Studio version and toolset. 5 | .PARAMETER VsConfig 6 | Visual Studio Configuration 7 | .PARAMETER VsVersion 8 | Visual Studio Version 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Visual Studio Version')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $VsVersion, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Visual Studio Configuration')] 17 | [PSCustomObject] $VsConfig 18 | ) 19 | begin { 20 | } 21 | process { 22 | if($null -eq (Get-Command vswhere -ErrorAction SilentlyContinue)) { 23 | throw "vswhere is not available" 24 | } 25 | $MSVCDirectory = vswhere -latest -products * -find "VC\Tools\MSVC" 26 | $selectedToolset = $null 27 | $minor = $null 28 | foreach ($toolset in (Get-ChildItem $MSVCDirectory)) { 29 | $toolsetMajorVersion, $toolsetMinorVersion = $toolset.Name.split(".")[0,1] 30 | $requiredVs = $VsConfig.vs.$VsVersion 31 | $majorVersionCheck = [int]$requiredVs.major -eq [int]$toolsetMajorVersion 32 | $minorLowerBoundCheck = [int]$toolsetMinorVersion -ge [int]$requiredVs.minorMin 33 | $minorUpperBoundCheck = ($null -eq $requiredVs.minorMax) -or ([int]$toolsetMinorVersion -le [int]$requiredVs.minorMax) 34 | if ($majorVersionCheck -and $minorLowerBoundCheck -and $minorUpperBoundCheck) { 35 | if($null -eq $minor -or [int]$toolsetMinorVersion -gt [int]$minor) { 36 | $selectedToolset = $toolset.Name.Trim() 37 | $minor = $toolsetMinorVersion 38 | } 39 | } 40 | } 41 | 42 | if (-not $selectedToolset) { 43 | throw "toolset not available" 44 | } 45 | 46 | return $selectedToolset 47 | } 48 | end { 49 | } 50 | } -------------------------------------------------------------------------------- /php/BuildPhp/private/Set-PhpIniForTests.ps1: -------------------------------------------------------------------------------- 1 | function Set-PhpIniForTests { 2 | <# 3 | .SYNOPSIS 4 | Set PHP INI for tests. 5 | .PARAMETER BuildDirectory 6 | Build directory 7 | .PARAMETER Opcache 8 | Opcache 9 | #> 10 | [OutputType()] 11 | param ( 12 | [Parameter(Mandatory = $true, Position=0, HelpMessage='Build directory')] 13 | [ValidateNotNull()] 14 | [ValidateLength(1, [int]::MaxValue)] 15 | [string] $BuildDirectory, 16 | [Parameter(Mandatory = $true, Position=1, HelpMessage='Specify Cache')] 17 | [ValidateSet('nocache', 'opcache')] 18 | [string] $Opcache 19 | ) 20 | begin { 21 | } 22 | process { 23 | $ini = "$BuildDirectory\phpbin\php.ini" 24 | Copy-Item "$PSScriptRoot\..\config\ini\extensions.ini" $ini 25 | Add-Content $ini "extension_dir=$BuildDirectory\phpbin\ext" 26 | if ($Opcache -eq "opcache") { 27 | New-Item "$BuildDirectory/file_cache" -ItemType "directory" > $null 2>&1 28 | $opcacheIni = Get-Content "$PSScriptRoot\..\config\ini\opcache-$Arch.ini" -Raw 29 | $opcacheIni = $opcacheIni.Replace("OPCACHE_ERROR_LOG_PATH", "$BuildDirectory\opcache_error.log") 30 | $opcacheIni = $opcacheIni.Replace("OPCACHE_FILE_CACHE_PATH", "$BuildDirectory\file_cache") 31 | Add-Content $ini $opcacheIni 32 | } 33 | } 34 | end { 35 | } 36 | } -------------------------------------------------------------------------------- /php/BuildPhp/public/Invoke-PhpBuild.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-PhpBuild { 2 | <# 3 | .SYNOPSIS 4 | Build PHP. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | .PARAMETER Arch 8 | PHP Architecture 9 | .PARAMETER Ts 10 | PHP Build Type 11 | #> 12 | [OutputType()] 13 | param ( 14 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 15 | [ValidateNotNull()] 16 | [ValidateLength(1, [int]::MaxValue)] 17 | [string] $PhpVersion, 18 | [Parameter(Mandatory = $true, Position=1, HelpMessage='PHP Architecture')] 19 | [ValidateNotNull()] 20 | [ValidateSet('x86', 'x64')] 21 | [string] $Arch, 22 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Build Type')] 23 | [ValidateNotNull()] 24 | [ValidateSet('nts', 'ts')] 25 | [string] $Ts 26 | ) 27 | begin { 28 | } 29 | process { 30 | $VsConfig = (Get-VsVersion -PhpVersion $PhpVersion) 31 | if($null -eq $VsConfig.vs) { 32 | throw "PHP version $PhpVersion is not supported." 33 | } 34 | 35 | $currentDirectory = (Get-Location).Path 36 | 37 | $tempDirectory = [System.IO.Path]::GetTempPath() 38 | 39 | $buildDirectory = [System.IO.Path]::Combine($tempDirectory, [System.Guid]::NewGuid().ToString()) 40 | 41 | New-Item "$buildDirectory" -ItemType "directory" -Force > $null 2>&1 42 | 43 | Set-Location "$buildDirectory" 44 | 45 | Add-BuildRequirements -PhpVersion $PhpVersion -Arch $Arch 46 | 47 | Copy-Item -Path $PSScriptRoot\..\config -Destination . -Recurse 48 | $buildPath = "$buildDirectory\config\$($VsConfig.vs)\$Arch\php-$PhpVersion" 49 | Move-Item "$buildDirectory\php-$PhpVersion-src" $buildPath 50 | Set-Location "$buildPath" 51 | New-Item "..\obj" -ItemType "directory" > $null 2>&1 52 | Copy-Item "..\config.$Ts.bat" 53 | 54 | $task = "$PSScriptRoot\..\runner\task-$Ts.bat" 55 | 56 | & "$buildDirectory\php-sdk\phpsdk-starter.bat" -c $VsConfig.vs -a $Arch -s $VsConfig.toolset -t $task 57 | if (-not $?) { 58 | throw "build failed with errorlevel $LastExitCode" 59 | } 60 | 61 | $artifacts = if ($Ts -eq "ts") {"..\obj\Release_TS\php-*.zip"} else {"..\obj\Release\php-*.zip"} 62 | New-Item "$currentDirectory\artifacts" -ItemType "directory" -Force > $null 2>&1 63 | xcopy $artifacts "$currentDirectory\artifacts\*" 64 | Move-Item "$buildDirectory\php-$PhpVersion-src.zip" "$currentDirectory\artifacts\" 65 | 66 | Set-Location "$currentDirectory" 67 | } 68 | end { 69 | } 70 | } -------------------------------------------------------------------------------- /php/BuildPhp/public/Invoke-PhpTests.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-PhpTests { 2 | <# 3 | .SYNOPSIS 4 | Test PHP Build. 5 | .PARAMETER PhpVersion 6 | PHP Version 7 | .PARAMETER Arch 8 | PHP Architecture 9 | .PARAMETER Ts 10 | PHP Build Type 11 | .PARAMETER Opcache 12 | Specify Cache 13 | #> 14 | [OutputType()] 15 | param ( 16 | [Parameter(Mandatory = $true, Position=0, HelpMessage='PHP Version')] 17 | [ValidateNotNull()] 18 | [ValidateLength(1, [int]::MaxValue)] 19 | [string] $PhpVersion, 20 | [Parameter(Mandatory = $true, Position=1, HelpMessage='PHP Architecture')] 21 | [ValidateNotNull()] 22 | [ValidateSet('x86', 'x64')] 23 | [string] $Arch, 24 | [Parameter(Mandatory = $true, Position=2, HelpMessage='PHP Build Type')] 25 | [ValidateNotNull()] 26 | [ValidateSet('nts', 'ts')] 27 | [string] $Ts, 28 | [Parameter(Mandatory = $true, Position=3, HelpMessage='Specify Cache')] 29 | [ValidateSet('nocache', 'opcache')] 30 | [string] $Opcache 31 | ) 32 | begin { 33 | } 34 | process { 35 | $VsVersion = (Get-VsVersion -PhpVersion $PhpVersion) 36 | if($null -eq $VsVersion) { 37 | throw "PHP version $PhpVersion is not supported." 38 | } 39 | 40 | $currentDirectory = (Get-Location).Path 41 | 42 | $tempDirectory = [System.IO.Path]::GetTempPath() 43 | 44 | $buildDirectory = [System.IO.Path]::Combine($tempDirectory, [System.Guid]::NewGuid().ToString()) 45 | 46 | $testsDirectory = "tests" 47 | 48 | New-Item "$buildDirectory" -ItemType "directory" -Force > $null 2>&1 49 | 50 | Set-Location "$buildDirectory" 51 | 52 | Add-TestRequirements -PhpVersion $PhpVersion -Arch $Arch -Ts $Ts -VsVersion $VsVersion -TestsDirectory $testsDirectory 53 | 54 | Set-PhpIniForTests -BuildDirectory $buildDirectory -Opcache $Opcache 55 | 56 | $Env:Path = "$buildDirectory\phpbin;$Env:Path" 57 | $Env:TEST_PHP_EXECUTABLE = "$buildDirectory\phpbin\php.exe" 58 | $Env:TEST_PHP_JUNIT = "$buildDirectory\test-$Arch-$Ts-$opcache.xml" 59 | $Env:SKIP_IO_CAPTURE_TESTS = 1 60 | 61 | $Env:OPENSSL_CONF = "$buildDirectory\phpbin\extras\ssl\openssl.cnf" 62 | 63 | $env:MYSQL_TEST_PORT = "3306" 64 | $Env:MYSQL_TEST_USER = "root" 65 | $Env:MYSQL_TEST_PASSWD = "" 66 | $Env:MYSQL_TEST_DB = "test" 67 | 68 | $Env:PDO_MYSQL_TEST_DSN = "mysql:host=localhost;dbname=test" 69 | $Env:PDO_MYSQL_TEST_USER = "root" 70 | $Env:PDO_MYSQL_TEST_PASS = "" 71 | 72 | Set-Location "$testsDirectory" 73 | 74 | Get-TestsList -OutputFile "tests-to-run.txt" 75 | 76 | $settings = Get-TestSettings -PhpVersion $PhpVersion 77 | 78 | php $settings.runner $settings.progress "-g" "FAIL,BORK,WARN,LEAK" "-r" "tests-to-run.txt" 79 | 80 | Copy-Item "$buildDirectory\test-$Arch-$Ts-$Opcache.xml" $currentDirectory 81 | 82 | Set-Location "$currentDirectory" 83 | } 84 | end { 85 | } 86 | } -------------------------------------------------------------------------------- /php/BuildPhp/runner/task-nts.bat: -------------------------------------------------------------------------------- 1 | set LDFLAGS="/d2:-AllowCompatibleILVersions" 2>&1 2 | call phpsdk_deps.bat -s staging -u 2>&1 3 | if errorlevel 1 exit 1 4 | call buildconf.bat 2>&1 5 | if errorlevel 1 exit 2 6 | call config.nts.bat 2>&1 7 | if errorlevel 1 exit 3 8 | nmake 2>&1 9 | if errorlevel 1 exit 4 10 | call phpsdk_pgo --init 2>&1 11 | if errorlevel 1 exit 5 12 | call phpsdk_pgo --train --scenario default 2>&1 13 | if errorlevel 1 exit 6 14 | call phpsdk_pgo --train --scenario cache 2>&1 15 | if errorlevel 1 exit 7 16 | nmake clean-pgo 2>&1 17 | if errorlevel 1 exit 8 18 | sed -i "s/enable-pgi/with-pgo/" config.nts.bat 2>&1 19 | if errorlevel 1 exit 9 20 | call config.nts.bat 2>&1 21 | if errorlevel 1 exit 10 22 | nmake && nmake snap 2>&1 23 | if errorlevel 1 exit 11 24 | -------------------------------------------------------------------------------- /php/BuildPhp/runner/task-ts.bat: -------------------------------------------------------------------------------- 1 | set LDFLAGS="/d2:-AllowCompatibleILVersions" 2>&1 2 | call phpsdk_deps.bat -s staging -u 2>&1 3 | if errorlevel 1 exit 1 4 | call buildconf.bat 2>&1 5 | if errorlevel 1 exit 2 6 | call config.ts.bat 2>&1 7 | if errorlevel 1 exit 3 8 | nmake 2>&1 9 | if errorlevel 1 exit 4 10 | call phpsdk_pgo --init 2>&1 11 | if errorlevel 1 exit 5 12 | call phpsdk_pgo --train --scenario default 2>&1 13 | if errorlevel 1 exit 6 14 | call phpsdk_pgo --train --scenario cache 2>&1 15 | if errorlevel 1 exit 7 16 | nmake clean-pgo 2>&1 17 | if errorlevel 1 exit 8 18 | sed -i "s/enable-pgi/with-pgo/" config.ts.bat 2>&1 19 | if errorlevel 1 exit 9 20 | call config.ts.bat 2>&1 21 | if errorlevel 1 exit 10 22 | nmake && nmake snap 2>&1 23 | if errorlevel 1 exit 11 24 | -------------------------------------------------------------------------------- /php/BuildPhp/tests/BuildPhp.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModulePath = Split-Path -Path $PSScriptRoot -Parent 2 | $ModuleName = Split-Path -Path $ModulePath -Leaf 3 | 4 | # Make sure one or multiple versions of the module are not loaded 5 | Get-Module -Name $ModuleName | Remove-Module 6 | 7 | # Import the module and store the information about the module 8 | $ModuleInformation = Import-Module -Name "$ModulePath\$ModuleName.psd1" -PassThru 9 | $ModuleInformation | Format-List 10 | 11 | # Get the functions present in the Manifest 12 | $ExportedFunctions = $ModuleInformation.ExportedFunctions.Values.Name 13 | 14 | # Get the functions present in the Public folder 15 | $PS1Functions = Get-ChildItem -Path "$ModulePath\Public\*.ps1" 16 | 17 | Describe "$ModuleName Module - Testing Manifest File (.psd1)" { 18 | Context "Manifest" { 19 | It "Should contain RootModule" { 20 | $ModuleInformation.RootModule | Should Not BeNullOrEmpty 21 | } 22 | 23 | It "Should contain ModuleVersion" { 24 | $ModuleInformation.Version | Should Not BeNullOrEmpty 25 | } 26 | 27 | It "Should contain GUID" { 28 | $ModuleInformation.Guid | Should Not BeNullOrEmpty 29 | } 30 | 31 | It "Should contain Author" { 32 | $ModuleInformation.Author | Should Not BeNullOrEmpty 33 | } 34 | 35 | It "Should contain Description" { 36 | $ModuleInformation.Description | Should Not BeNullOrEmpty 37 | } 38 | 39 | It "Compare the count of Function Exported and the PS1 files found" { 40 | $status = $ExportedFunctions.Count -eq $PS1Functions.Count 41 | $status | Should Be $true 42 | } 43 | 44 | It "Compare the missing function" { 45 | If ($ExportedFunctions.count -ne $PS1Functions.count) { 46 | $Compare = Compare-Object -ReferenceObject $ExportedFunctions -DifferenceObject $PS1Functions.Basename 47 | $Compare.InputObject -Join ',' | Should BeNullOrEmpty 48 | } 49 | } 50 | } 51 | } 52 | 53 | Get-Module -Name $ModuleName | Remove-Module -------------------------------------------------------------------------------- /php/action.yml: -------------------------------------------------------------------------------- 1 | name: build-php 2 | description: Build PHP 3 | author: php 4 | 5 | branding: 6 | icon: package 7 | color: purple 8 | 9 | inputs: 10 | php-version: 11 | description: PHP version to build 12 | required: true 13 | arch: 14 | description: Architecture to build 15 | required: true 16 | ts: 17 | description: Thread safety to build 18 | required: true 19 | 20 | runs: 21 | using: composite 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Build PHP 27 | shell: pwsh 28 | run: | 29 | Import-Module ${{ github.action_path }}\BuildPhp -Force 30 | Invoke-PhpBuild -PhpVersion ${{inputs.php-version}} ` 31 | -Arch ${{inputs.arch}} ` 32 | -Ts ${{inputs.ts}} 33 | 34 | - name: Upload artifacts 35 | uses: actions/upload-artifact@v4 36 | with: 37 | name: artifacts-${{inputs.php-version}}-${{inputs.arch}}-${{inputs.ts}} 38 | path: artifacts/* 39 | -------------------------------------------------------------------------------- /release/action.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | description: Upload the artifacts to a release 3 | author: php 4 | 5 | branding: 6 | icon: package 7 | color: purple 8 | 9 | inputs: 10 | release: 11 | description: 'Git reference for the release' 12 | required: true 13 | token: 14 | description: 'GitHub token' 15 | required: true 16 | 17 | runs: 18 | using: composite 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | 23 | - name: Get artifacts 24 | uses: actions/download-artifact@v4 25 | with: 26 | path: artifacts 27 | merge-multiple: true 28 | 29 | - name: Upload artifacts 30 | shell: bash 31 | env: 32 | GITHUB_TOKEN: ${{ inputs.token }} 33 | run: gh release upload ${{ inputs.release }} artifacts/php* --clobber 34 | --------------------------------------------------------------------------------