Nexus Forge execution contracts
nxforge compiles and validates a Nexus Forge document, emits an owned Nexus Script
Live document, and releases the compilation session before preparing its single
task root. Group, Package, and Project run their children in declaration order.
Command tasks render a Mustache Template and launch a tool. Render
and filesystem tasks execute within Nexus Forge.
Declared path fields use / separators on every host. Backslashes in those
fields are rejected. Resolved paths and source selections retain /, including
paths supplied to child tools. An integration for a tool that requires native
separators converts its path arguments at invocation. Arbitrary arguments,
command text, URLs, and rendered file contents are not path-normalized.
Package and Project contracts
Package and Project use the same ordered execution as Group, including
nesting, composition, target selection, preparation, and failure propagation.
A Pascal compiler invocation is an explicit NXPC or FPC child. NXPC
selects our compiler and defaults to nxpc; FPC selects upstream Free Pascal
and defaults to fpc. Initial compiler bootstrap uses explicit stock FPC paths. A Package containing
no build operations is valid and performs no compilation.
| Contract | Group | Package | Project |
|---|---|---|---|
| Ordered build children | Yes | Yes | Yes |
Required nonblank Id |
No | Yes | Yes |
Version, Author, Description, License |
No | Optional | Optional |
Requires catalog references |
No | Optional | Optional |
Outputs text array |
No | Optional | Optional |
UnitPaths, IncludePaths, LibraryPaths text arrays |
Ordinary data | Optional contract fields | Ordinary data |
| Recipe-defined data properties | Yes | No | Yes |
The shared definitions and semantic validator are owned by nxpackage. Nexus Forge
extends the definitions with executable children and allows recipe-defined data
properties on Group and Project. These properties use ordinary composition and
references; Nexus Forge does not interpret them as operations or compiler settings.
Recognized Project contract properties retain their validation rules, and
operation definitions continue to reject unknown properties. The package editor and Nexus Forge
use the same read-only contract checks. Neither follows descriptor locations,
fetches dependencies, selects versions, or builds Requires entries implicitly.
Each nonempty Requires list names records in the single index imported by its
supplying document, including requirements inherited through composition.
LoadForgeDocument returns an owned Live document after compilation and
validation, without preparing tools or reading generated outputs. TNXPackageDocument can inspect the same Nexus Forge
descriptor without executing it. A declared output is a contract, not a freshness
cache or an implicit existence test. Add explicit validation children when build
success depends on verifying outputs. Failure of a final validation fails the
whole build and prevents every following child from starting; completed work
is retained. Contracts do not imply rollback.
module Library "library/Package.nxscript";
Project Application {
Id: "NXRP.Application";
Outputs: [Binary: "bin/application.exe"];
Package BuildLibrary (Library) {}
FPC Compile {
Template: "FPC.mustache";
Source: ["src/application.pas"];
EntryPoint: "src/application.pas";
UnitPaths: @Library.UnitPaths;
IncludePaths: @Library.IncludePaths;
Output: @Application.Outputs.Binary;
}
Run Check {
Template: "Run.mustache";
Executable: @Application.Outputs.Binary;
}
}
Importing a package makes its contract available; the explicit composed child
schedules its build. Contract references use ordinary Nexus Script @ syntax.
No new interpolation or placeholder syntax is involved. A language-level FPC
runtime package remains an artifact compiled by FPC, distinct from this build
contract and its operations.
Paths supplied by direct references retain the file where their value originated.
This applies to filesystem-operation paths and command Output, UnitOutput,
CompilerUtilitiesPath, UnitPaths, IncludePaths, LibraryPaths, ObjectPaths,
and Objects. A reference to an entire path array and references to individual
entries both preserve origin. Command Source arrays and EntryPoint always retain
the origin of their supplying values, including composition. Templates and tool
paths retain their existing origin semantics. A bare Executable or Compiler name
uses PATH whether supplied literally or through a reference. To run a local
program, supply an explicit path such as ./program or an absolute path.
Literal output/search paths remain relative to the operation working directory. By default that is the operation's declaring file, including children imported from a package. The CLI working-directory override supplies a common base for all operations. An operation's explicit WorkingDirectory then overrides that base. Text expressions construct a new value at the expression's source location; use direct references when an exported path must retain its original base. Path normalization changes the command context, leaving the Live document unchanged.
Run is an ordinary command operation with required Template and Executable,
optional text-array Arguments, and optional WorkingDirectory. The supplied
Run.mustache quotes the executable and each argument. It supports generated
tools and test programs without adding special process behavior to Nexus Forge.
CLI
From the repository root, build with the installed nxbuild and the native
compiler settings in NXBuild.Environment.nxscript beside the executable:
nxbuild /action=build /project=projects/forge/NexusForge.nxproject
../../worktree/nexus/NexusForge-next/x86_64-linux/Debug/nxforge /input=Build.nxscript
On Windows, use the corresponding x86_64-win64/Debug/nxforge.exe output.
Required: /input=.... Optional: /targets=Name:Value,OtherName:OtherValue and
/working-directory=.... There is no /package or /manifest argument.
Flags use the existing Nexus command-line parser; quote the entire argument when its value contains spaces. Targets are explicit; Nexus Forge does not infer host or compilation targets. The input path resolves from the launch directory. The child's default working directory is the operation document's directory. A relative working-directory override resolves from that document directory. Tool arguments remain relative to the child's working directory.
There is no dialect-selection or dialect-root CLI flag. Documents declare their dialect through existing Nexus Script resolution. Nexus Forge adds no search catalog, environment repair, or activation logic.
Language pieces
projects/forge/language/Forge.nxscript includes
projects/forge/language/definitions/*.ForgeDef.nxscript. Core, FPC,
Git, Nexus Build, PowerShell, Npm, InnoSetup, CSV, Msg2Inc, Render,
FileOperations, BuildIdentity, Group, and Environment definitions form one
effective Nexus Forge language through the included-definition view. The master does
not name individual tools.
ForgeDef is a convention selected by this include pattern, not a filename rule.
The document declaration identifies its dialect.
Live values
Nexus Forge prepares commands, file operations, and Render sources from
TNexusScriptLiveDocument. The compiler still owns parsing, composition, target
filtering, and schema validation. Execution borrows no compiled nodes.
Every selected target is available through the common $Name mechanism:
WriteTextFile Selection {
Path: "selected-target.txt";
Text: $TargetOS + "/" + $TargetCPU + "/" + $BuildConfiguration;
}
For example, invoke that document with
/targets=TargetOS:linux,TargetCPU:aarch64,BuildConfiguration:Release.
Target names are generic and case-sensitive. Nexus Forge supplies no implicit target
values; an unselected value fails when read. Selected targets are read-only.
Embedded hosts can supply other external values through TNXForge.OnReadExternal.
The same handler serves Render source documents. Reads are deferred to value
consumption, so unused external values need no provider. The CLI does not map
$Name to operating-system environment variables. A missing value or a deferred
dialect-constraint failure prevents the prepared task list from executing.
The shared JSON emitter renders Live values while retaining _nx metadata,
public declaration collections, named array entries, and bounded reference
projections. Its compiled-document artifact entry point still requires fully
materialized data; only the explicit Live entry points evaluate external values.
Shared configurations and environment data
A shared configuration file is an ordinary module. It may contain partial operation configurations and target-selected environment data:
Environment Platform TargetOS[Windows] { ExecutableSuffix: ".exe"; }
Environment Platform TargetOS[Linux] { ExecutableSuffix: ""; }
FPC CompileApplication { Template: "application.mustache"; }
FPC CompileTests { Template: "tests.mustache"; }
A consumer imports it and uses normal composition and references:
module "Shared.nxscript";
Group Build {
FPC Compile (CompileApplication) {
Source: ["app.lpr"];
EntryPoint: "app.lpr";
Output: "app" + @Platform.ExecutableSuffix;
}
FPC Test (CompileTests) {
Source: ["tests.lpr"];
EntryPoint: "tests.lpr";
Output: "tests" + @Platform.ExecutableSuffix;
}
}
Select TargetOS explicitly for this example. The completed concrete operations must satisfy the FPC contract, including Template, Source, and EntryPoint. Imported partial bases need not independently supply every required operation property. They remain module definitions, not additional commands. Existing module root selectors can limit which definitions a consumer imports.
Environment is a data definition with caller-defined properties. Its property names, suffixes, and target values carry no built-in platform meaning. Environment roots are never scheduled as commands, even if a property is named Template.
There is no separate process catalog or matching by operation kind. Two FPC tasks can inherit different templates. All tasks in a Group, Package, or Project are prepared before the first starts, including tasks within nested Groups. Declaration order is preserved; module-only roots are not scheduled. A runnable document requires one executable root: a singular task, Group, Package, or Project.
Source selections and entry points
FPC Source is a nonempty list of explicit files or filename masks, for example
Source: ["src/*.pas", "src/app.lpr"]. EntryPoint: "src/app.lpr" names the
single input passed to FPC. Partial composed configurations can contribute Source
entries without an EntryPoint; a concrete FPC operation requires both.
Nexus Forge expands command-operation Source arrays relative to the declaring operation
file. src/*.pas selects
that directory only; src/**/*.pas explicitly includes subdirectories. There is
no extension inference. Source arrays are expanded immediately before their
command runs, after preceding tasks have completed. This allows files copied or
generated by earlier tasks to be selected in the same run. Missing directories
or selections matching no files stop that task before launch and prevent later
tasks from running; earlier completed tasks are retained. Entries retain selection
order, matches are sorted, and duplicate files and directories are removed.
The command render context receives absolute file names in Source, unique
containing directories in _nx.SourcePaths, and an absolute EntryPoint.
Templates translate those directories to switches such as -Fu. Schema validation
and loading/parsing all command templates still happen before any task runs.
For source-array commands, the normalized context and template text are retained
until source expansion and final command rendering at execution time. This does
not change the compiled Nexus Script document. Scalar Source values for CSV and Render
retain their existing contracts. A Source list does not create multiple commands.
FPC searches these directories for dependencies and decides whether compiled units are usable. The selected files establish search directories, not a restriction on which other dependencies FPC may load from those directories. Nexus Forge does not hash sources, generate bootstrap programs, or compile every selected unit independently. Each explicit FPC task invokes the compiler; FPC decides whether units need rebuilding.
The NXPC and FPC definitions and their matching templates under templates/
support these optional settings:
| Property | Value | Compiler switch |
|---|---|---|
Mode |
Text | Emits -M<mode> |
Rebuild |
Boolean | True emits -B |
ObjectPaths |
Text array | Emits -Fo<path> for each path |
LibraryPaths |
Text array | Emits -Fl<path> for each path |
LinkerOptions |
Text array | Emits -k<option> for each option |
DisableDefaultConfigFiles |
Boolean | True emits -n |
CompileSystemUnit |
Boolean | True emits -Us |
LabelAndGoto |
Boolean | True emits -Sg |
OptimizationLevel |
Integer, 1 through 4 | Emits -O1 through -O4 |
GenerateReleaseUnitFiles |
Boolean | True emits -Ur |
StripSymbols |
Boolean | True emits -Xs |
ResponseFiles |
Text array | Emits @<file> for each compiler options file |
TargetOS |
Text | Emits -T<value>, e.g. -Tlinux |
Assembler |
Text | Emits -A<value>, e.g. -Aas-clang |
UseLLD |
Boolean | True emits -XLL |
PositionIndependentCode |
Boolean | True emits -Cg |
CompilerUtilitiesPath |
Text | Emits quoted -FD<path> |
WorkingDirectory |
Text | Sets the compiler process directory using ordinary Nexus Forge path rules |
ExecutableOutput |
Text | Emits quoted -FE<path> |
PackageSDKIdentity / PackageBuildIdentity |
Text | Emit -Fj / -Fk identities before response files |
EmbedPackageMetadata |
Enabled / Disabled | Emit -FJEnabled / -FJDisabled; omission keeps the compiler default (embedded) |
PackagePaths |
Text array | Emits -Fp for each package directory |
RequiredPackages |
Text array | Emits -FP after package search paths |
SmartLinkUnits / SmartLink |
Boolean | Emit -CX / -XX |
ConsoleApplication / GUIApplication |
Boolean | Emit -WC / -WG; choose one subsystem |
Omitted properties and False Boolean values emit no switch. -Ur prevents
automatic recompilation of the generated release units. These switches are
rendered by Mustache; the executor has no FPC-specific option handling.
FPC does not accept an unrestricted Arguments property. Output is optional:
the template emits -o only for a supplied, nonempty value. Without it, FPC
uses its normal output naming. Unit compilation can specify UnitOutput
(-FU) without naming an executable output. Output directories must already
exist when the compiler starts. UnitPaths and IncludePaths emit quoted
-Fu and -Fi switches respectively; relative paths use the operation's
working directory. Explicit unit paths follow the directories selected by Source.
CompilerUtilitiesPath follows the same working-directory rule. Target-filtered
configurations can supply these named settings while sharing one FPC template.
ResponseFiles entries are passed to the compiler verbatim; relative paths use
the operation's working directory. An earlier child may generate an options
file. The compiler reads it when the FPC child runs. This is FPC's existing
response-file interface, not Nexus Script syntax.
An explicit relative Compiler path containing a slash or backslash resolves
from the document supplying that property, including inherited or referenced
values, just like Executable. Absolute paths and bare tool names retain their
existing meaning. The compiler need not exist during preparation; an earlier
task can build or copy it before invocation. This path normalization supplies the
Mustache context and does not construct compiler commands.
FPC message generation
Msg2Inc runs FPC's existing message generator through examples/Msg2Inc.mustache.
It requires Template, Source (one message-file path), OutputPrefix, and
ConstantName. Optional Executable defaults to msg2inc on PATH. An explicit
relative executable path resolves from its declaring document, like other
command tools. Relative source and output paths use the operation working
directory.
The template passes the three named operands in that order, with each quoted.
The utility's default string-table mode writes OutputPrefix + "idx.inc" and
OutputPrefix + "txt.inc"; ConstantName supplies the base name for its text
constants. For compiler messages, use an output prefix ending in msg and
ConstantName: msg. Create the output directory before running the operation.
The executable may be produced by an earlier FPC task in the same Group.
No unrestricted Arguments property or tool-specific executor code is used.
Template paths and rendering
Source identifies tool input; Template identifies the Mustache command file.
A relative Template path resolves from the source file supplying its value.
Inherited values retain that origin; scalar aliases/references are followed to
the supplying value. A locally overridden Template uses its own source origin.
For a constructed string, the expression's source file supplies the origin.
Moving a configuration into a module does not make its template path relative to
the importing task.
The template receives the operation's completed properties and _nx metadata
directly, without an operation-name wrapper. Arrays, inherited values, references,
and projection limits retain normal Nexus Script JSON semantics. FPC tasks use
their own Template, Output, and UnitOutput properties.
{{_nx.CompiledAt}} exposes the entry document's compilation timestamp in
ISO 8601 UTC form, including milliseconds and a trailing Z. Operations from
the same compiled document share that timestamp. A Render operation's artifact
template receives the compiled source document's timestamp instead.
fpc "{{{EntryPoint}}}"{{#Output}} "-o{{{Output}}}"{{/Output}}{{#Defines}} -d{{{.}}}{{/Defines}}{{#_nx.SourcePaths}} "-Fu{{{.}}}"{{/_nx.SourcePaths}}
Mustache is the template language. Templates own native quoting and command
construction. Raw interpolation avoids HTML escaping. The executor uses FPC's
TProcess.CommandLine parsing and adds no shell. Spaces and & in quoted paths
are verified; shell expansion and compound commands are not implicit.
An explicit relative Executable containing / or \ resolves from the source
file supplying that property, including inherited values and scalar references.
Absolute executable paths are unchanged. Bare names such as nxbuild or
nxbuild.exe remain unchanged for PATH lookup. The child working directory does
not change this resolution. This applies to all command operations.
Nexus project compilation
NXBuild is a native Nexus Forge task that calls Nexus Build's description loader,
planner and executor in process. It uses the same engine as the standalone
Nexus Build command and does not require an nxbuild executable. Required
EntryPoint resolves from its declaring document to an absolute path.
Executable, WorkingDirectory and Template are not task properties; the
project describes the actual compiler/tool invocations and their directories.
Optional RootDirectory supplies an explicit Nexus Build project-root override.
A task uses its own property or the nearest enclosing Group/Package/Project
property. Relative overrides resolve from the document declaring the value.
An empty override restores the project's own root/default. Siblings keep their
own context. Without an override, Nexus Build uses the project's RootDirectory
property or the directory containing its .nxproject. This setting affects
NXBuild tasks only; it does not rebase Nexus Forge file operations or dependencies.
The loaded project can read $RootDirectory and $ProjectDirectory through
Nexus Build's external-value provider, without encoding paths as target selections.
Optional NXPC overrides the compiler for NXPC operations in this invocation;
FPC and other tool kinds keep their own compilers. A bare name remains a PATH
command. Explicit paths resolve from their declaring document. Omitting NXPC
retains Nexus Build's normal compiler selection.
Optional OutputRoot and OutputFile supply the entry project's $OutputRoot
and $OutputFile values. Relative Nexus Forge values resolve from their declaring
document. The nxproject explicitly uses these values in output paths/arguments;
they do not relocate sources, dependencies, or unrelated outputs. No executable
extension is appended. These settings belong to each NXBuild task and can be
shared through ordinary task composition. They introduce no command-line flags.
Each task receives its own copy of Nexus Forge's selected targets, including
TargetOS, TargetCPU, HostOS, HostCPU, BuildConfiguration and custom
selections. No forwarding properties are needed in the recipe.
| Property | Meaning | When omitted |
|---|---|---|
Targets |
Comma-separated Name:Value task-local selections |
Keep the enclosing selections |
Action |
build, validate, or plan (case-insensitive) |
build |
TargetOS |
Explicit task-local OS override | Inherit Nexus Forge's selection |
TargetCPU |
Explicit task-local CPU override | Inherit Nexus Forge's selection |
BuildConfiguration |
Explicit task-local configuration override | Inherit Nexus Forge's selection |
Targets replaces matching selections in the task's copy and adds new names.
The individual target/configuration properties, when supplied, take precedence
over Targets. Neither form changes the enclosing context or sibling tasks.
The task passes its selection object directly to the Nexus Build loader, without
serializing inherited values into command-line arguments. Nexus Forge's command-line
entry point establishes its standard defaults before creating tasks; the task
itself does not invent absent selections. Action values are validated before
any task executes.
NXBuild Application {
EntryPoint: "Application.nxproject";
}
NXBuild ReleaseTools {
EntryPoint: "Tools.nxproject";
BuildConfiguration: Release;
Targets: "Stage:release";
}
With Nexus Forge's /targets=TargetOS:win64,TargetCPU:x86_64,BuildConfiguration:Debug,
both tasks select win64/x86_64. Application inherits Debug, while ReleaseTools
selects Release and adds Stage:release. Properties still support literals,
internal references, composition and Live $ references.
The project owns its dependencies, compiler selection, published directories,
compiler options, and output locations. Nexus Build's loader and planner interpret
.nxproject files when the task executes, so earlier Nexus Forge tasks can prepare
their inputs. Nexus Build remains independent of Nexus Forge. Plan/validation output and
compiler/tool output use the normal output streams. A failed project load or
build stops the workflow before later tasks.
LLVM C and C++ compilation
Clang and LLVMAr are ordinary command operations with definition contracts
and Mustache templates; the Nexus Forge executor contains no LLVM-specific behavior.
Clang requires Template, a nonempty Source array, and an explicit
CompileOnly Boolean. The example template defaults to clang on PATH. Set
Executable to clang++ for a C++ driver. CompileOnly: True emits -c.
Omit Output to compile a source collection in one invocation: Clang writes
one object per source into WorkingDirectory, using each source's base name.
Create that directory before the compilation and select sources with distinct
base names. Source selections retain their declaring file's directory.
Supply Output to name a single object or linked binary; the template emits
-o only when it is present. CompileOnly: False compiles and links.
Target, Standard, IncludePaths, and Defines render native Clang switches.
SystemIncludePaths renders ordered -isystem paths; referenced paths retain
their declaration origin. OptimizationLevel accepts 0 through 3 and emits
-O<level>. DisableStackProtector: True emits -fno-stack-protector.
Optional SourceLanguage emits -x <language>; use assembler for assembly
inputs whose extension does not identify their language. AssemblerSymbols
is an optional text array of name=value entries, each rendered as
-Wa,-defsym,name=value for the assembler. These properties allow assembly
tasks to share the Clang template with C and C++ tasks.
Arguments supplies additional literal arguments, including linker selection
and libraries. No shell is involved. Source selections use the normal expansion
contract; output and other argument paths are interpreted in WorkingDirectory.
LLVMAr requires Template, Operation, Output, and a nonempty Objects
text array. The example template defaults to llvm-ar; Operation: "rcs"
creates or updates an indexed static archive. Optional Arguments supplies
native archiver options. Objects are explicit input arguments, not Source masks:
they may be generated by earlier tasks in the same Group. Neither this operation
nor Clang implicitly creates output directories or cleans existing artifacts.
Native tool contracts: Clang, llvm-ar.
External build tools
MSBuild, MSVC and CMake builds belong to Nexus Build. Nexus Forge invokes an explicit
NXBuild entry; the nxproject owns tool settings, arguments, and per-command
environment. The composed Nexus2D.Forge.nxscript acquires pinned sources with
Git tasks and stages the resulting libraries and headers with CopyFiles.
The upstream solution continues to own the Windows simulator build.
PowerShell remains available for explicit scripts, with EntryPoint, optional
Executable, and Arguments. The engine no longer uses it for dependency
orchestration.
Npm and InnoSetup are command operations with ForgeDef contracts and Mustache
examples in ../nexus-lab/examples/build/orchestration/. Npm.Command is a
command such as ci, install, or run, with additional tokens in Arguments;
InnoSetup.EntryPoint names the .iss file. InnoSetup Defines and Arguments
are text arrays, not semicolon-separated strings. InnoSetup requires an explicit
Quiet Boolean. Their optional Executable values override the example
templates' npm.cmd and ISCC.exe defaults.
Each operation may specify WorkingDirectory, resolved from the Nexus Forge document
directory. When omitted, the usual Nexus Forge operation directory applies. Boolean
options validated by the Nexus Forge dialect are converted to JSON booleans in the
command-render context, so Mustache sections distinguish False from True
without changing the Nexus Script JSON emitter.
CSV compilation
CSV is an ordinary native operation. Import
projects/csv/config/CSV.nxscript, compose CompileCSV, and provide Source,
SourceTemplate, and Output. Its Template builds the command; SourceTemplate is
passed to nxcsv for artifact rendering. Optional Compiler, Name, and Delimiter
values remain explicit tool arguments. Nexus Forge contains no CSV loader or SQL logic.
See NexusCSV for the command-line interface and template data.
Render artifacts
Render declares required Source, Output, and Template text values and an optional
explicit Environment definition reference. Its Template generates artifact content.
The source declares its own dialect; Nexus Forge compiles and validates it in-process
with the current target selection. The template receives the source's generic
JSON, including the combined included-definition collections. An explicit
Environment is added at Environment; a source root with that name is rejected
when the operation supplies this context. This operation renders model definitions;
it does not import external seed-data rows.
Relative Source and Template retain the origin of the supplying value, including module references and composition. Output resolves from the operation working directory. Standalone Render does not invent output directories; callers create them when needed. This Output meaning belongs to Render, not to arbitrary operation properties.
All operations prepare before any executes. Source compilation/validation or missing-template failures therefore launch no commands and write no artifacts. Execution writes the rendered bytes without trimming, including an empty file. Write failure stops subsequent operations. An invocation records SourcePath, OutputPath, Started, and Completed; it does not fabricate a process exit status. Native and Render operations can occur in the same ordered list.
See the BotHost database example for a target-selected Environment. It renders Firebird SQL with no database semantics in Nexus Forge and no separate Nexus Script executable.
Build identity
BuildIdentity is a native file operation with required Repository and
OutputDirectory paths. It can run at the root or inside Group, Package, or
Project. Literal paths use the operation working directory; referenced paths
retain their declaring source origin. No Template is required.
BuildIdentity CaptureBuildIdentity {
Repository: ".";
OutputDirectory: "build/forge-bootstrap/seed";
}
The operation runs after preceding children. It requires
OutputDirectory/source/version.pas, reads Git HEAD and tracked/untracked
non-ignored dirty state, and chooses the UTC timestamp from SOURCE_DATE_EPOCH
or the captured commit. Git must be on PATH. Epoch values must be decimal
non-negative seconds no later than 9999-12-31 23:59:59 UTC. Invalid source,
Git, or timestamp inputs fail before output files are changed.
It writes source/revision.inc, build-options.cfg (-DD and -DT), and
build-identity.json beneath OutputDirectory. The JSON fields are Revision,
Dirty, Identity, Date, Time, and SourceDateEpoch. Text is UTF-8 without a BOM,
with LF endings; Date and Time use fixed yyyy/MM/dd and HH:mm:ss UTC formats.
Identity is the full revision with an optional -dirty suffix; it does not hash
uncommitted changes. Later bootstrap and cross tasks reuse the captured files.
This bounded operation intentionally owns the current FPC output formats in
utNXForgeBuildIdentity.pas. It uses the existing process runner for Git and
the ordinary native-operation dispatch for file generation. It adds no shell,
runtime reference evaluation, or Render lifecycle change. File-write failures
stop subsequent children and can leave earlier files written, as with the other
ordered file operations.
Filesystem operations
CreateDirectory, WriteTextFile, CopyFile, CopyFiles, CompareFiles, DeletePath, and Archive execute
in Nexus Forge without Mustache or an external shell. Relative paths resolve from the
operation working directory. They use the same prepare-before-execute ordering
and stop-on-failure behavior as Render; later operations may consume files
created by earlier ones.
CreateDirectory requires Path. It creates the directory and any missing
parents. An existing directory succeeds without changing its contents. A file
at the destination or in a required parent path, or any other creation failure,
reports an error and stops later operations.
CreateDirectory SeedBin {
Path: "build/forge-bootstrap/seed/bin";
}
WriteTextFile requires Path and Text. It creates parent directories and
writes text with LF line endings, matching Task's text-file action.
CopyFiles requires SourceFolder, TargetFolder, and a nonempty Files
array of relative file names or */? masks. Names must exist. Masks expand
at execution time, so they can select files produced by preceding tasks;
a mask matching no files is allowed. Relative directory masks such as
include/*/*.h are supported. Recursive: True searches below the directories
selected by a mask; its default is False. Paths are preserved relative to
SourceFolder unless Flatten: True is explicit. Overlapping selections copy
each file once. Flattening collisions fail before copying or cleaning.
Overwrite and CleanDestination default to False, as with CopyFile.
Named-file checks and collision checks precede cleaning the destination.
Use CopyFile for an explicit source/destination rename.
CopyFiles StageLibraries {
SourceFolder: "build/lib";
TargetFolder: "stage/lib";
Files: ["core.lib", "support*.lib"];
Overwrite: True;
}
CopyFile requires Source and Destination. Overwrite, Recursive, and
CleanDestination default to false. A directory source requires Recursive;
CleanDestination removes an existing destination directory before copying.
ExcludeNames is an optional semicolon-separated, case-insensitive list of
exact file or directory names skipped during recursive copying.
On Unix, copied files retain the source's read, write and execute permission bits,
including when an existing destination is overwritten. Permission-copy errors fail
the operation. Ownership and special permission bits are not copied.
IncludeMasks optionally limits copied files to a nonempty array of filename
masks, for example ["*.pas", "*.inc"]. Each file's basename must match
at least one mask; overlapping masks copy the file only once. * matches zero
or more characters and ? matches one. Matching is case-insensitive on Windows
and case-sensitive elsewhere. Masks cannot be empty or contain path separators
or drive prefixes. Directories are traversed regardless of these masks, and
ExcludeNames still skips matching files or whole subdirectories. The filter
also applies to a single-file source. No matches succeeds without copying files;
recursive copying can still create empty directories. Omitting IncludeMasks
copies all files as before. CleanDestination still clears the entire destination
directory before the filtered copy.
CompareFiles requires nonempty Left and Right file paths. It compares all
bytes using fixed-size buffers and succeeds only when lengths and contents match.
Two empty files compare equal. Files are opened when the operation executes, so
earlier tasks can produce them. Comparison does not change either file or create
output. Missing files, directories, open/read errors, and differences stop later
tasks. Diagnostics identify both resolved paths; differences report the first
unequal byte offset, counted from zero. If one file is an identical prefix of the
other, the offset is the shorter file's length. There are no ignored byte ranges
or file-format-specific rules.
CompareFiles VerifyBootstrap {
Left: "build/forge-bootstrap/cycle2/ppcx64.exe";
Right: "build/forge-bootstrap/cycle3/ppcx64.exe";
}
DeletePath requires Path. Recursive defaults to false and MissingOk
defaults to true. A wildcard in the final path component matches files, not
directories; Recursive also searches subdirectories. A literal directory
requires Recursive unless empty.
Archive requires Operation (Zip or Unzip), Source, and Destination.
Overwrite defaults to false and Recursive defaults to true. Zip accepts a
file or directory source and uses the same ExcludeNames convention as CopyFile.
Unzip refuses entries outside its destination directory.
Package SDK metadata
PackageSDKOptions and PackageSDKManifest are native file operations allowed
at the root or inside Group, Package and Project. They currently own the standard
Nexus Pascal Win64 and Linux SDK layouts and formats; they do not compile or stage files.
PackageSDKOptions Identity {
BootstrapDirectory: "build/forge-bootstrap";
OutputDirectory: "build/forge-bootstrap/package-sdk";
Target: "x86_64-win64";
CompilerFileName: "nxpc-x86_64.exe";
}
// Compile and copy the foundation and startup artifacts here.
PackageSDKManifest Manifest {
Directory: "build/forge-bootstrap/package-sdk";
Compiler: "build/forge-bootstrap/build-tools/nxpc-x86_64.exe";
}
The required paths must be nonempty and use the ordinary Nexus Forge path rules.
Inputs are opened at execution time so previous children can produce them.
PackageSDKOptions creates the foundation identity and compiler response
files in the SDK work directory from the supplied compiler and RTL artifacts.
PackageSDKManifest validates those artifacts and writes sdk.json, containing
relative artifact paths, SDK identity and SHA-256 hashes. Use the matching Nexus Pascal
release recipes to construct the expected SDK inputs.
Compiler must run on the build machine: it is queried for its version. The
delivered SDK compiler may target another platform. Artifact validation reads
images without executing them. Invalid inputs, identity mismatches or a failed
compiler query stop later operations without replacing an existing manifest.
Package consumer builds
PackageBuildPrepare and PackageBundlePublish are native file operations at
the root or inside Group, Package and Project. examples/PackageBuild.nxscript
composes explicit work-directory cleanup, preparation, explicit compiler invocation
and publication in that order. The Win64 SDK ships this group and NXPC.mustache
under forge/. Consumers need Nexus Forge and its language definitions installed.
PackageBuildPrepare Prepare {
SDKDirectory: "sdk";
WorkDirectory: "build/package-work";
PackageDirectories: ["providers"];
}
// Compile into the prepared work directory, using its package.cfg response file.
PackageBundlePublish Publish {
WorkDirectory: "build/package-work";
OutputDirectory: "distribution";
Name: "mypackage";
Kind: Package;
}
Preparation verifies Format 2 Win64 or x86-64 glibc Linux SDK artifact hashes, resolves each
provider's selected generation, and checks NXP004/ABI-4 PCP/image pairs and exact
dependency build identities. It requires an empty work directory and writes
package.cfg plus package-build.json containing a fresh build identity and
the hashes of the selected package inputs. PackageDirectories is optional;
the SDK foundation is always included. Preparation does not perform compilation.
Publication requires Kind: Package, Console or GUI. For Console and GUI,
Name is the exact executable filename in WorkDirectory, including any extension;
publication neither adds nor removes an extension. It rejects changed
inputs, mismatched output identities, missing pairs and incompatible dependency
builds. Packages publish PCP/image pairs; applications publish their executable and the
supplied shared-library closure. Each completed generation-<id> has a hash manifest;
current.json changes atomically only after copying and validation succeed.
An I/O failure can leave an unselected generation. Existing generations remain
until explicitly removed. Builds and publication are sequential.
Provider directories may be raw PCP/image directories or published distributions. When present, their manifests are enforced, including rejection of unlisted artifacts. These operations do not acquire packages or select versions. Rebuilding a provider already consumed within a bundle requires rebuilding its dependent distribution in a new output directory.
When composing the supplied group, explicitly derive replaced children from
PackageBuild.Prepare, PackageBuild.Compile, and PackageBuild.Publish to
retain their inherited settings. Supply absolute SDK/work paths: the group
combines them into compiler and response-file paths before changing the compiler
working directory. Relative literal FPC paths use that work directory.
See the Nexus Pascal SDK guide for a complete example.
Linux consumers compose LinuxPackageBuild for providers and
LinuxPackageApplication for executables. These derive from the same ordered
group; platform linker settings remain in the recipes. Application composition
adds nxrtl and PIE/no-COPY/no-text-relocation/RELRO/eager-binding options to the
shared PIC and $ORIGIN settings. Existing array composition appends entries.
Preparation records the SDK target and writes resolved rpath-link directories
to its response file. Publication preserves executable permissions on Unix.
Execution and failure
The child inherits the developer's environment. Input is closed after launch. Standard output and error remain separate and are collected through exit.
Each invocation records its operation name, resolved template path, command, working directory, launch state, separate output, exit status, and diagnostic. On Unix, normal exits record the decoded exit code; signal termination records 128 plus the signal number and fails the operation. CLI output marks unstarted entries. Schema and template-preparation failures prevent that operation list from launching. Source-selection or final rendering failure at execution time, launch failure, or nonzero exit stops subsequent operations. Completed output remains available. Success returns exit status 0; failure 1.
Host selection and directory comparison
The Nexus Forge CLI supplies lowercase HostOS and HostCPU selections for its own
native platform unless explicitly supplied through /targets. API callers
provide their own selection context. These describe the machine executing the
workflow; TargetOS and TargetCPU can independently select a cross target.
CompareDirectories requires Left and Right directories. Optional
IncludeMasks filters filenames, and Recursive: True includes subdirectories.
It compares sorted relative file sets and every selected file byte for byte.
Missing directories, empty selections, extra/missing files, or differing bytes
fail the operation and stop later tasks. No compiler/RTL-specific logic is in
this operation.
VerifyBuildIdentity requires Compiler and IdentityFile. It checks the
compiler's -iW suffix and -iD date against the Identity and Date captured
by BuildIdentity. An invalid record, failed compiler command, or mismatching
identity/date stops the workflow before installation or promotion.
Git tasks
Git is a dedicated Nexus Forge task object, without a Mustache template. It uses the
installed git executable and structured arguments. Executable can name an
explicit installed Git; otherwise it uses PATH.
Git Source {
Operation: Checkout;
Repository: "cache/shaderc";
URL: "https://github.com/google/shaderc.git";
Revision: "24275a11d81a6b33ef345878f8a4ef929c95a116";
}
Git Inspect { Operation: Status; Repository: "cache/shaderc"; }
Checkout requires a full commit hash. A missing directory is initialized,
fetched at that revision, and checked out detached. An existing checkout is
reused only when HEAD matches. A mismatch fails without resetting, cleaning,
or replacing local work. The operation verifies HEAD; it does not require a
clean working tree. Status returns git status --short output. A failed Git
command stops the workflow.