Skip to content

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.