Tier 0 · Story 10Complete
The build action compiles your Tyhp source files into PHP code. It runs the full compilation pipeline — parse, bind, check, optional package.tyhpdef generation, and emit — then writes the compiled PHP output files to the configured output directory.
tyhp build [options]
TYHP8021) and a missing tyhp/compiler pin (TYHP7702) are among those warnings.extra.tyhp.require pins onto root require-dev and Composer-update those packages. Same write path as tyhp composer sync. Ordinary tyhp build never auto-updates Composer. See CLI: Composer.suppressWarnings in tyhp.json). Errors are never hidden.The build action performs the following steps in order:
composer.json plus vendor/composer/installed.json for stale extra.tyhp.require pins (TYHP7701) and a missing tyhp/compiler pin (TYHP7702). Default: explain; missing extras fail the compile; --fix writes require-dev and Composer-updates (never on an ordinary build). See CLI: Composer."type": "library" — always write package.tyhpdef and additive-merge extra.tyhp.package into composer.json in the publish directory (output.publishPath, default: the project root next to tyhp.json). build.generateTyhpdef is ignored."type": "application" — if build.generateTyhpdef is true, write only package.tyhpdef (no extra.tyhp.package). If false or unset, write nothing.TYHP7505 and skip writing those artifacts.extra.tyhp.package already exists on that composer.json, the build adds missing keys and array items only; it does not remove or change existing entries.tyhpdef/. See CLI: Tyhpdef Generation.package.tyhpdef keeps the library's Tyhp surface: attributes, class-level type, in-package global use, and #[\Tyhp\GenericRuntime] on every emitted generic class/method/function. Consumers use \Tyhp\Generic::bind at foreign sites rather than helper names. internal symbols are omitted.build.generateSourcemap is true, also write a sibling .php.map (Source Map v3) and append a //# sourceMappingURL= comment to each PHP file. When build.updateComposer is true, also update composer.json in output.publishPath with Tyhp runtime package requires. When output.publishContent is set, copy those extra files into output.publishPath.Multi-target gated PHP output (--php-targets) is a generate_tyhpdef flag, not part of tyhp build. tyhp build evaluates declare(php=…) / #[\Tyhp\Php] in loaded tyhpdefs against output.phpVersion ("8.2" through "8.5" for tyhpdef/php). See CLI: Source Map Generation.
The build action reads configuration from the tyhp.json project file. Key configuration sections include:
"TYHP8027"). Errors are never hidden. CLI --suppress-warnings replaces the JSON array.{name}-style interpolation.composer.json (including library extra.tyhp.package) and package.tyhpdef (default: ".", the project root). Supports interpolation, for example "./publish/{version}".output.publishPath before compiling (default: false). Refused when publishPath is the project root.output.publishPath after emit. src / dst / exclude interpolate; dst may also use per-file variables such as {fileName}. See Project Options List.tyhp generate_tyhpdef. For tyhpdef/php / tyhpdef/php-ext-*, it also selects which version-gated APIs are visible (8.2–8.5 matrix). {phpVersion.id} in other keys is the Tyhp PHP id ("8.2" → 802). See CLI: Lint.true, write a .php.map file next to each compiled .php file and append //# sourceMappingURL= (default: false).true with sourcemaps on, embed original .tyhp text in each map's sourcesContent (default: false).package.tyhpdef in the publish directory when true. Libraries always emit package.tyhpdef and additive-merge extra.tyhp.package on publish-directory composer.json; this key is ignored for "type": "library".output.publishPath with PSR-4 autoloading for the compiled PHP (default: false)."halfUp").clone ... with on readonly properties for PHP 8.2–8.4 (default: false). PHP 8.5+ does not need this flag.Null safety, required type annotations, and narrowing mixed before use are unconditional. The checker section only exposes resource limits and tooling knobs:
{
"include": ["./src/**/*.tyhp", "./src/**/*.php"],
"exclude": ["./src/legacy/**"],
"output": {
"path": "./src",
"publishPath": "./publish/{version}",
"publishClean": false,
"publishContent": [
{ "src": "README.md" },
{ "src": "LICENSE", "dst": "LICENSE.txt" },
{ "src": "docs/**/*.md", "dst": "docs", "exclude": ["docs/drafts/**"] }
],
"phpVersion": "8.4",
"strictTypes": true
},
"build": {
"updateComposer": true
},
"checker": {
"templateStringMaxStates": 256
},
"psr4": {
"App\\": "src/"
}
}
{version} comes from the project-root composer.json next to tyhp.json. Add a "version" field there if tyhp init did not. See String interpolation.
Tyhp supports incremental compilation using an AST cache. When you rebuild a project, files that have not changed since the last build are loaded from the cache rather than being re-parsed. This significantly speeds up rebuild times for large projects. The binder and checker still run on all files to ensure cross-file consistency.
Build state is persisted between runs. If no source files or configuration have changed, the build exits early with a "Nothing to build" message. Use --clean to force a full rebuild by clearing the output directory and build state.
Errors and warnings are displayed in a format similar to other compiled languages:
src/Models/User.tyhp(42,5): error TYHP4003: Member modifier 'static' is not allowed on interface methods
src/Services/Auth.tyhp(15,10): error TYHP3003: Symbol 'InvalidUser' not found
Build failed with 2 errors.
Files: 42 source files
Duration: 0.91s (parse: 0.45s, bind: 0.12s, check: 0.34s)
Errors: 2
Warnings: 0
Some Tyhp features require small runtime PHP packages to function. When build.updateComposer is enabled, the build action automatically adds the necessary Composer dependencies based on the features used in your code:
output.phpVersion). Optional extensions are tyhpdef/php-ext-*.Package MAJOR for compiled tyhp/* helpers is the target PHP (804.x for PHP 8.4), not the compiler ceiling. Each of those packages has its own X.Y. Applications pin 80N.X.Y; libraries or PHP majors with that package's X (803.0.* || 804.0.* || 805.0.* while it is on 0.y). tyhpdef/* packages pin their composer.json version (not 80N.X.Y). See the Composer Runtime Packages page.