Skip to content

Commit

Permalink
Merge pull request #34 from asgrim/docs-for-maintainers
Browse files Browse the repository at this point in the history
Added initial documentation for maintainers
  • Loading branch information
asgrim authored Sep 16, 2024
2 parents 3eab4b1 + 42287d7 commit dd9904f
Show file tree
Hide file tree
Showing 2 changed files with 255 additions and 34 deletions.
63 changes: 29 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,48 @@
# 🥧 PIE (PHP Installer for Extensions)

You will need PHP 8.1 or newer to run PIE, but PIE can install an extension to any installed PHP version.
You will need PHP 8.1 or newer to run PIE, but PIE can install an extension to
any installed PHP version.

## Installing
If you are an extension maintainer wanting to add PIE support to your extension,
please read [extension-maintainers](./docs/extension-maintainers.md).

## Usage
## Installing an extension using PIE

You can download an extension ready to be built or installed using the `download` command. For example, to download the
`example_pie_extension` extension, you would run:
You can install an extension using the `install` command. For example, to
install the `example_pie_extension` extension, you would run:

```shell
$ bin/pie download asgrim/example-pie-extension
You are running PHP 8.3.7
Target PHP installation: 8.3.7 nts, on Linux/OSX/etc x86_64 (from /usr/bin/php8.3)
Found package: asgrim/example-pie-extension:1.0.1 which provides ext-example_pie_extension
Extracted asgrim/example-pie-extension:1.0.1 source to: /tmp/pie_downloader_6645f07a28bec9.66045489/asgrim-example-pie-extension-769f906
$
$ bin/pie install example/example-pie-extension
This command may need elevated privileges, and may prompt you for your password.
You are running PHP 8.3.10
Target PHP installation: 8.3.10 nts, on Linux/OSX/etc x86_64 (from /usr/bin/php8.3)
Found package: example/example-pie-extension:1.0.1 which provides ext-example_pie_extension
phpize complete.
Configure complete.
Build complete: /tmp/pie_downloader_66e0b1de73cdb6.04069773/example-example-pie-extension-769f906/modules/example_pie_extension.so
Install complete: /usr/lib/php/20230831/example_pie_extension.so
You must now add "extension=example_pie_extension" to your php.ini
$
```

If you are trying to install an extension for a different version of PHP, you may specify this on non-Windows systems
with the `--with-php-config` option like:
### Using PIE to install an extension for a different PHP version

```shell
bin/pie download --with-php-config=/usr/bin/php-config7.2 my/extension
```

On all platforms, you may provide a path to the `php` executable itself using the `--with-php-path` option. This is an
example on Windows where PHP 8.1 is used to run PIE, but we want to download the extension for PHP 8.3:
If you are trying to install an extension for a different version of PHP, you
may specify this on non-Windows systems with the `--with-php-config` option:

```shell
> C:\php-8.1.7\php.exe bin/pie download --with-php-path=C:\php-8.3.6\php.exe asgrim/example-pie-extension
You are running PHP 8.1.7
Target PHP installation: 8.3.6 ts, vs16, on Windows x86_64 (from C:\php-8.3.6\php.exe)
Found package: asgrim/example-pie-extension:1.0.1 which provides ext-example_pie_extension
Extracted asgrim/example-pie-extension:1.0.1 source to: C:\path\to\temp\pie_downloader_66547faa7db3d7.06129230
bin/pie install --with-php-config=/usr/bin/php-config7.2 my/extension
```

And this is a very similar example (using PHP 8.1 to run PIE to download a PHP 8.3 extension) on a non-Windows platform:
On Windows, you may provide a path to the `php` executable itself using the
`--with-php-path` option. This is an example on Windows where PHP 8.1 is used
to run PIE, but we want to download the extension for PHP 8.3:

```shell
$ php8.1 bin/pie download --with-php-path=/usr/bin/php8.3 asgrim/example-pie-extension
You are running PHP 8.1.28
Target PHP installation: 8.3.7 nts, on Linux/OSX/etc x86_64 (from /usr/bin/php8.3)
Found package: asgrim/example-pie-extension:1.0.1 which provides ext-example_pie_extension
Extracted asgrim/example-pie-extension:1.0.1 source to: /tmp/pie_downloader_66547da1e6c685.25242810/asgrim-example-pie-extension-769f906
> C:\php-8.3.6\php.exe bin/pie install --with-php-path=C:\php-8.1.7\php.exe example/example-pie-extension
```

## Developing

### Testing
## Extensions that support PIE

### Building and Deploying
A list of extensions that support PIE can be found on
[https://packagist.org/extensions](https://packagist.org/extensions).
226 changes: 226 additions & 0 deletions docs/extension-maintainers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# PIE for Extension Maintainers

Adding PIE support for your extension is relatively straightforward, and the
flow is quite similar to adding a regular PHP package into Packagist.

## Add a `composer.json` to your extension

The first step to adding PIE support is adding a `composer.json` to your
extension repository. Most of the typical fields are the same, with a few
notable exceptions:

* The `type` MUST be either `php-ext` for a PHP Module (this will be most
extensions), or `php-ext-zend` for a Zend Extension.
* An additional `php-ext` section MAY exist.
* The Composer package name (i.e. the top level `name` field) should follow
the usual Composer package name format, i.e. `<vendor>/<package>`.
* However, please note that the Composer package name for a PIE extension
cannot share the same Composer package name as a regular PHP package, even
if they have different `type` fields.

### The `php-ext` definition

#### `extension-name`

The `extension-name` SHOULD be specified, and must conform to the usual extension
name regular expression, which is defined in
[\Php\Pie\ExtensionName::VALID_PACKAGE_NAME_REGEX](../src/ExtensionName.php).
If the `extension-name` is not specified, the `extension-name` will be derived
from the Composer package name, with the vendor prefix removed. For example,
given a `composer.json` with:

```json
{
"name": "myvendor/myextension"
}
```

The extension name would be derived as `myextension`. The `myvendor/` vendor
prefix is removed.

The `extension-name` SHOULD NOT be prefixed with `ext-` as is a convention in
Composer when using `require`.

An example of `extension-name` being used:

```json
{
"name": "xdebug/xdebug",
"php-ext": {
"extension-name": "xdebug"
}
}
```

#### `priority`

`priority` is currently not used, but will form part of the `ini` filename to
control ordering of extensions, if the target platform uses it.

#### `support-zts`

Indicates whether the extension supports Zend Thread-Safe (ZTS) mode or not.

#### `configure-options`

This is a list of parameters that may be passed to the `./configure` command.
Each item of the list is a JSON object with:

* `name`, the parameter name itself
* `description`, a helpful description of what the parameter does
* optionally, `needs-value`, a boolean to tell PIE whether the parameter is a
simple flag (typically used for `--enable-this-flag` type parameters), or if
the parameter should have a value specified (typically used for
`--with-library-path=...` type parameters, where a value must be given by
the end user)

When an end user is installing an extension with PIE, they may specify any
defined `configure-options` that are passed to `./configure`. For example, if
an extension defines the following `composer.json`:

```json
{
"name": "myvendor/myext",
"php-ext": {
"extension-name": "myext",
"configure-options": [
{
"name": "enable-my-flag",
"description": "Should my flag be enabled",
"needs-value": false
},
{
"name": "with-some-lib",
"description": "Specify the path to some-lib",
"needs-value": true
}
]
}
}
```

Then the `pie build` or `pie install` commands may be invoked in the following
ways to achieve the desired configuration:

* `pie install myvendor/myext`
* This will simply invoke `./configure` without any parameters
* `pie install myvendor/myext --enable-my-flag`
* This will invoke `./configure --enable-my-flag`
* `pie install myvendor/myext --with-some-lib=/path/to/somelib`
* This will invoke `./configure --with-some-lib=/path/to/somelib`
* `pie install myvendor/myext --enable-my-flag --with-some-lib=/path/to/somelib`
* This will invoke `./configure --enable-my-flag --with-some-lib=/path/to/somelib`

Note that it is not possible for end users of PIE to specify configuration
options that have not been defined in your extension's `configure-options`
definition. Using the same example above `composer.json`, invoking PIE with
an invalid option, such as `pie install myvendor/myext --something-else` will
result in an error `The "--something-else" option does not exist.`.

If an end user does not specify a flag defined in the `configure-options`
definition, it will simply not be passed to `./configure`. There is no way to
specify a default value in the `configure-options` definition.

## Submit the extension to Packagist

Once you have committed your `composer.json` to your repository, you may then
submit it to Packagist in the same way as any other package.

* Head to [https://packagist.org/packages/submit](https://packagist.org/packages/submit)
* Enter the URL of your repository, and follow the instructions.

## Windows Support

In order to support Windows users, you must publish pre-built DLLs, as PIE does
not currently support building DLLs on the fly. The expected workflow for
Windows-compatible releases is:

- The release is made on GitHub (only GitHub is supported at the moment)
- A CI pipeline runs to build the release assets, e.g. in a GitHub Action
- The resulting build assets are published to the GitHub release in a ZIP file

The name of the ZIP file, and the DLL contained within must be:

* `php_{extension-name}-{tag}-{php-maj/min}-{ts|nts}-{compiler}-{arch}.zip`
* Example: `php_xdebug-3.3.2-8.3-ts-vs16-x86_64.zip`

The descriptions of these items:

* `extension-name` the name of the extension, e.g. `xdebug`
* `tag` for example `3.3.0alpha3` - defined by the tag/release you have made
* `php-maj/min` - for example `8.3` for PHP 8.3.*
* `compiler` - usually something like `vc6`, `vs16` - fetch from
'PHP Extension Build' flags in `php -i`
* `ts|nts` - Thread-safe or non-thread safe.
* `arch` - for example `x86_64`.
* Windows: `Architecture` from `php -i`
* non-Windows: check `PHP_INT_SIZE` - 4 for 32-bit, 8 for 64-bit.

### Contents of the Windows ZIP

The pre-built ZIP should contain at minimum a DLL named in the same way as the
ZIP itself, for example
`php_{extension-name}-{tag}-{php-maj/min}-{ts|nts}-{compiler}-{arch}.dll`.
The `.dll` will be moved into the PHP extensions path, and renamed, e.g.
to `C:\path\to\php\ext\php_{extension-name}.dll`. The ZIP file may include
additional resources, such as:

* `php_{extension-name}.pdb` - this will be moved alongside
the `C:\path\to\php\ext\php_{extension-name}.dll`
* `*.dll` - any other `.dll` would be moved alongside `C:\path\to\php\php.exe`
* Any other file, which would be moved
into `C:\path\to\php\extras\{extension-name}\.`

### Automation of the Windows publishing

PHP provides a [set of GitHub Actions](https://github.com/php/php-windows-builder)
that enable extension maintainers to build and release the Windows compatible
assets. An example workflow that uses these actions:

```yaml
name: Publish Windows Releases
on:
release:
types: [published]

permissions:
contents: write

jobs:
get-extension-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.extension-matrix.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get the extension matrix
id: extension-matrix
uses: php/php-windows-builder/extension-matrix@v1
build:
needs: get-extension-matrix
runs-on: ${{ matrix.os }}
strategy:
matrix: ${{fromJson(needs.get-extension-matrix.outputs.matrix)}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build the extension
uses: php/php-windows-builder/extension@v1
with:
php-version: ${{ matrix.php-version }}
arch: ${{ matrix.arch }}
ts: ${{ matrix.ts }}
release:
runs-on: ubuntu-latest
needs: build
if: ${{ github.event_name == 'release' }}
steps:
- name: Upload artifact to the release
uses: php/php-windows-builder/release@v1
with:
release: ${{ github.event.release.tag_name }}
token: ${{ secrets.GITHUB_TOKEN }}
```
Source: [https://github.com/php/php-windows-builder?tab=readme-ov-file#example-workflow-to-build-and-release-an-extension](https://github.com/php/php-windows-builder?tab=readme-ov-file#example-workflow-to-build-and-release-an-extension)

0 comments on commit dd9904f

Please sign in to comment.