NextPDF backport boot and discovery
Build tooling — NOT a runtime dependency. This page explains how the builder starts on a maintainer or continuous integration (CI) host. Downstream applications never load this code.
At a glance
Section titled “At a glance”The builder does not use a framework, a dependency-injection container, or service-provider auto-discovery. Instead, PHP command-line interface (CLI) scripts are wired with require_once and Composer’s PSR-4 autoloader. Here, “discovery” has two specific meanings: which source repositories the merge stage reads, and how the orchestrator selects the Rector configuration for the target.
Build pipeline overview
Section titled “Build pipeline overview”The orchestrator is scripts/build.php. It starts the build, then runs five stages in order. Each stage is gated, so the first failure stops the build:
- Merge sources — copy the source repositories into one tree.
- Run Rector downgrade — run one pass for PHP 8.1; run two passes plus fix-ups for PHP 7.4.
- Generate
composer.json— write the generated package manifest with itsreplacemap. - Copy static assets — copy the license and a generated changelog.
- Validate output — count emitted PHP files; the authoritative syntax gate runs later in CI.
Verified against scripts/build.php (run(), step()). See /integrations/backport/configuration/ for rule-selection details and /integrations/backport/production-usage/ for the CI gate.
Discovery of source modules
Section titled “Discovery of source modules”Source discovery is not manifest-driven. scripts/merge-sources.php uses a fixed map keyed by repository name and selected by the target.
For the PHP 8.1 target, the map includes nextpdf (core), nextpdf-Artisan, nextpdf-compat-legacy, nextpdf-Laravel, nextpdf-Symfony, nextpdf-CodeIgniter, and nextpdf-Pro when Pro is included. For the PHP 7.4 target, the map collapses to nextpdf only. The builder resolves each repository as a sibling directory under the --source-dir root. It validates every expected repository before copying anything. If one is missing, the merge aborts and reports its name and path. Verified against scripts/merge-sources.php (MergeSources::__construct(), run()).
The merge places core at src/ and each adapter under its namespaced subdirectory (src/Artisan/, src/Laravel/, and so on). Pro goes into a separate pro/src/ tree so the build can emit it as its own package. Verified against MergeSources (mergeCore(), mergeArtisan(), mergePro()).
Boot sequence
Section titled “Boot sequence”scripts/build.phpruns under the CLI Server Application Programming Interface (SAPI). Itrequire_oncesmerge-sources.phpandadjust-composer.php.- The CLI entry point reads options with
getopt()—--version,--source-dir,--output-dir,--target,--dry-run,--no-pro. - A
Buildinstance is constructed. The constructor validates--targetagainst['php74', 'php81']and raisesInvalidArgumentExceptionfor an invalid value before any work begins. For the PHP 7.4 target, it forces core-only output and disables Pro. Build::run()executes the five stages and exits with status 0 on success, or 1 on the first failure.
Verified against scripts/build.php (CLI entry point, Build::__construct(), run()).
Container bindings
Section titled “Container bindings”Not applicable. The builder is a CLI tool. It has no dependency-injection container and no framework service container. Wiring uses explicit require_once calls, plus Composer PSR-4 autoloading of NextPDF\Backport\ (rules) and NextPDF\Backport\Scripts\ (scripts). Verified against composer.jsonautoload and the require_once statements in scripts/build.php.
Configuration resolution order
Section titled “Configuration resolution order”There is no configuration file. Configuration comes from CLI flags resolved against the defaults baked into the script:
- The CLI flag, if provided.
- The default in the
getopt()parsing block (for example, target defaults tophp81, and version defaults to2.0.0). - Behavior that the constructor derives from the target (PHP 7.4 forces core-only and no Pro, regardless of
--no-pro).
Verified against scripts/build.php (CLI entry point and Build::__construct()). The full flag reference is in /integrations/backport/configuration/.
Diagnostics
Section titled “Diagnostics”The orchestrator provides its own diagnostics. Run a dry run (composer build:dry) to print the source repositories that would be read and each stage’s intent, without writing anything. Every stage prints a success check mark or a named failure. There is no separate diagnose subcommand and no bin/ entry point. The builder runs through scripts/build.php or its Composer-script aliases. Verified against scripts/build.php (step(), the dryRun branches), scripts/merge-sources.php (run() dry-run path), and composer.jsonscripts.
See also
Section titled “See also”- /integrations/backport/overview/ — what the builder is and what it produces.
- /integrations/backport/integration/ — the build-host integration contract.
- /integrations/backport/configuration/ — Rector configurations and the flag reference.
- /integrations/backport/troubleshooting/ — stage-by-stage failure reference.