Wiki page
[source_composer] by
mario
2015-01-20 09:54:38.
D 2015-01-20T09:54:38.572
L source_composer
N text/x-markdown
P 7d7289d1fc6d3a4402a7f57769ee2904e20fdee2
U mario
W 8428
## <kbd>*-s* `composer`</kbd> package input
<small>State: *testing*
Targets: *deb*, *rpm*, *phar*</small>
The <kbd>composer</kbd> plugin can turn composer bundles into system packages (`deb`/`rpm`). They extract libraries under `/usr/share/php/` then. Alternatively you can create local phars, or phars wrapped into system packages.
<img src="raw/c8a3139c59fbe88cd5f1844e2b2083426ada825c?m=image/png" alt="fpm -s composer packaging methods" width=850 height=222>
Normally you'd just use composer directly for joining libraries into projects. Syspackaging is meant to further fixate dependencies as globally shared libraries. Having php includes under system control can simplify deployment in a few settings.
## System packages
* <h2> Individual components </h2>
To package a dependency from within a composer-managed project directory use:
xpm -s composer -t deb,rpm gregwar/formidable
Note that fpm/xpm is meant for crafting one package at a time. So this will output exactly one `*.deb` / `*.rpm` package. If you specified more than one composer bundle name as input, they'd end up intermingled otherwise. (→ A warning will occur, and fpm aborts.)
* <h3> Pack all the things </h3>
However it's quite trivial to convert all composer dependencies at once with a shell loop:
for P in vendor/*/*; do
xpm -s composer -t deb $P
done
This will create a whole bunch of `php-vnd-pkg_0.1.2_all.deb` system packages.
* <h3> Fetch afresh </h3>
If you're not within a composer checkout, then the <kbd>-s composer</kbd> hook will of course retrieve it directly via composer and from packagist. This way you could also predefine a version:
xpm -s composer -t deb --composer-ver 2.7 new/new
Again, this will just convert one individual package. It will have its system `Depends:` field populated. But its actual dependent packages must be crafted this way too/manually. (It's most practicaly to just create an empty directory, checkout a complete package list per `composer install`, and then use the `for`-loop method to package every component in one run.)
## Pack'ging Phars
* <h2>Local phars </h2>
Instead of system packages (`-t deb` and `-t rpm`) you can also create Phar archives of "`vnd-pkg.phar`". Simply use the existing <kbd>`-t phar`</kbd> target:
xpm -s composer -t phar vendor/vnd/pkg
Such phar archives of course won't contain absolute paths. In fact all source files are assembled without any ./vnd/pkg/ prefixes. → That would be redundant because it's already obvious from the phar basename (and its archive meta data).
Using phar packages within projects of course requires a modern autoloader. Be advised that it's a super negligible performance benefit by itself. Generally classmap-based autoloaders can be faster. But if class dependencies are dispersed across files within, then there's little gain over entirely file-by-file-tapping ones.
* <h2> Phars in system packages </h2>
An interesting variation for the packaging process is to convert Composer packages into Phars wrapped in system packages. (This is labeled "matroska" mode in the plugin, btw). And it's simply available per <kbd>`--composer-phar`</kbd> flag:
xpm -s composer --composer-phar -t deb,rpm new/new
This way you'll end up with a system `phar-vnd-pkg_0.1_all.deb`/`.rpm` package. Which will install its contained `Vnd-Pkg.phar` directly under `/usr/share/php/`.
Again you'd need an autoloader that's designed for this. See [shared.phar](http://fossil.include-once.org/canonic_autoloader/) for a prototype. (A system trigger can keep the global map updated.)
* <h3> Phar options </h3>
In both cases the <kbd>[-t phar](wiki/phar)</kbd> module is used (internally) for generation. Currently and per default the composer source hook predefines the Phar format to be of the inspectable/compressed `ZIP+gz` variety. You could alternatively set the `--phar-format=phar` for native/uncompressed Phars of course.
## Notes
* <h4> Dependencies </h4>
Composer package relations are transformed into `Depends:` fields, with package names remapped to `php-vnd-pkg (>= 1.0)` for example. Not all composer versioning internas are translated however.
Still not sure if that's really sensible, as a complete transformation would require full DPKG/RPM dependency expansion (using conflicts, breaks, recommends, using `<<` or `>>` and lists/alternatives, etc). Nobody is saying dependency hell, btw; it just seems unneeded. To simplify you might want to use fpms <kbd>`--no-depends`</kbd> flag even.
Still, to make this compatible to [Debians pkg-php](http://pkg-php.alioth.debian.org/) schemes, a complete transliteration is planned.
* <h4> Autoloader building </h4>
The current version doesn't predefine any specific autoloader regeneration. This leaves room for a few options though.
* On Debian systems a package trigger watching for `/usr/share/php/` would certainly be the best option. This rebuilds any classloader after installations there.
* Preferrably use [**phpab**](https://github.com/theseer/Autoload) to build a common `autoload.phar`. It's both fast and language-compliant (case-insensitive lookups) per default.
* When generating `phar` packages, using a <kbd>--phar-stub</kbd> for a concrete and built-in autoload registration is an option. A simple `include("vnd-pkg.phar");` could then initialize dependencies explicitly.
The aforementioned `shared.phar` prototype would also work. In fact implements the package/directory trigger. (Not sure if it's working, needs to be transitioned to `fpm` build process).
**Obsolete**: Formerly `composer.lock` information was retained in each packages `composer.json` under `extra[]→lock{}`. But composer itself doesn't support rebuilding `composer.lock` or thus its autoloader. Both Debian and Fedora decided against `vendor/*/*` beneath `/usr/share/php`, and composer folks never wanted it either. Therefore the current xpm composer plugin doesn't allow that anymore. (See the attachment for a prior rough implementation of composer.lock and autoloader/installed.json reconstruction; or the opensuse workaround: [composer-add-package](https://gist.github.com/thomascube/9117025) for this).
* <h4> Phar attributes </h4>
With <kbd>--composer-phar</kbd> or the <kbd>-t phar</kbd> target, each generated archive contains an archive meta data bag. It's intended for simple application-level feature/plugin management, similar to a pre-parsed `composer.json` even. The fields `id:` and `version:`, as well as `title:`, `description:`, `author:`, `url:`, `category:` are available.
Dependencies are translated into basename `depends:` lists. A copy of composer fields is retained in a `composer: {}` instead. (Redundant, as the composer.json is also packaged within. But may be more convenient in some cases.)
## ToDo
* <h4> Classmap </h4>
For phar packages it certainly made sense to bake a class map into the Phar meta data. This might reduce extra work for future autoloaders. And obviously, should actually be implemented in the <kbd>-t phar</kbd> plugin.
<h3> Alternatives </h3>
See also [`pkg-php-tools`](https://packages.debian.org/de/sid/pkg-php-tools) for the Debian build helper (translates package names and dependency lists). Or [`php-composer-rpms`](https://github.com/siwinski/php-composer-rpms) for creating `rpm` packages (seems to be a stub though).
If you're just looking for a way to bundle up *all* project dependencies at once, then instead check out [github:clue/phar-composer](https://github.com/clue/phar-composer). It was specifically designed for that, is implemented in PHP, and provides more targetted options.
<h4> Distinct -u composer update filter </h4>
Note that the `-s composer` source plugin has a distinct purpose to the [<kbd>*-u* composer</kbd>](wiki/update_composer) filter. The -update filter only generates a stub `composer.json` and is intended for plain `phar` archives generated from <kbd>-s dir</kbd> source files or <kbd>-s src</kbd> for meta-tagged scripts. -- Both plugin types are not yet aligned in any way; so you don't want to combine them.
Z d79fdf6ba8b500cde6d32303e9b3e447