Skip to content

nxbuild

nxbuild loads a universal Nexus Script Project, resolves its complete dependency graph, inherits published directories, and executes producers before consumers. Projects can publish existing sources, generate resources, compile libraries or applications, or simply group other projects. A source-only project needs no build operations.

NXPC steps build with the Nexus Pascal compiler and default to nxpc (or the NXPC environment override). FPC steps retain genuine upstream Free Pascal support, including the initial 3.2.2 bootstrap, and default to fpc (or PP). An explicit CompilerPath overrides either default. Nexus product descriptors use NXPC and the shared Tools.NXPC.CompilerPath setting.

Installed tool configuration

NXBuild.Environment.nxscript lives beside nxbuild and nxforge in the per-user installation's bin directory. It is ordinary Nexus Script, containing the Tools environment: Nexus Pascal, LLVM, MSVC, Windows SDK, MSBuild, CMake and Ninja. Setup populates installation-specific paths. Edit this file to use different tool installations; updates and repairs preserve user edits.

Import the environment explicitly. A local module at the declared path is used when present; otherwise this specific module filename resolves beside the running tool. Other module paths retain normal Nexus Script resolution. Installed dialects resolve under <installation>/scripts when absent relative to the project. $NXBuildBin and $NXBuildRoot expose the running tool's bin directory and its parent installation directory. Nexus Build supplies native HostOS and HostCPU when the caller has not supplied them; the selected TargetOS/TargetCPU still describe the output.

No settings are applied simply because a project contains an NXPC, LLVM or MSVC operation. Select the settings through references or inheritance:

dialect "projects/nxbuild/language/nxbuild.Language.nxscript";
module Tools "NXBuild.Environment.nxscript";

Project Hello {
    Id: "Example.Hello";
    NXPC Application (Tools.Defaults.Pascal) {
        SourceFiles: ["hello.pas"];
        OutputPath: "build";
    }
}

Tools.Defaults.C and Tools.Defaults.CPP configure Clang; the latter uses clang++ for C++ standard-library linkage. Tools.Defaults.Native configures MSVC, Tools.Defaults.Solution MSBuild, and Tools.Defaults.Project CMake. These are ordinary composable definitions, and their names are not build rules. The supplied native profiles cover Windows x64 and Linux x64. Cross builds still need explicit matching target settings and SDKs/sysroots. The Windows intrinsic headers come from the configured LLVM installation before the MSVC headers.

Nexus Forge and the project inspector use the same Nexus Build-owned environment loader. Nexus Forge's NXBuild task therefore uses the same settings as a standalone invocation; it does not need to supply compiler, LLVM or SDK locations. Callers embedding the loader should install this file beside their own executable too.

Nexus's own source recipes import Nexus.Environment.nxscript. That separate module imports Tools and defines only source-development locations under Development, including OutputRoot and NXPCSource. End-user projects do not depend on the Nexus checkout or those development paths.

Publishing raw bootstrap tools creates the environment template if absent and keeps an existing file. Configure local SDK/tool paths before using those tools for source builds. For runtime-package projects, Tools.NXPC.PackageSDKIdentity must match SDKIdentity in the selected package SDK's sdk.json. Setup maintains that value for installed releases; a developer replacing a compiler/SDK directly must update it along with the replacement.

Project descriptions and discovery

A .nxproject contains one Project root with a nonempty, opaque Id. Version, Author, Description and License are optional metadata. The root label supplies Name. RootDirectory defaults to the descriptor's directory; a relative root resolves from that descriptor. Build inputs, local lookup paths and publications resolve against the publishing project's root.

An explicit /root-directory=<path> overrides the entry project's root. The loader exposes the same setting as RootDirectory for native callers. Relative overrides resolve from the descriptor's directory. Dependencies retain their own project roots. The existing Nexus Script external-value mechanism supplies $RootDirectory (the resolved root) and $ProjectDirectory (the entry descriptor's directory) for path expressions. These are loader context, not required target selections. An ordinary build needs no override.

Native callers may set the loader's OutputRoot and OutputFile. Recipes read these through $OutputRoot and $OutputFile; output paths and compiler arguments must explicitly use those values. OutputRoot defaults to the resolved project root; a relative override resolves from that root. OutputFile is explicit, resolves from the output root, and has no inferred name or extension. These inputs apply to the entry project and do not relocate dependency outputs or change the source root. The project's ordinary OutputRoot data property remains recipe data, and can reference $OutputRoot when invocation-controlled output is wanted.

The planner's native NXPC setting overrides the executable of every Nexus Pascal operation in that invocation, including dependencies. It leaves FPC and other tools unchanged and does not mutate the project description. When omitted, the existing CompilerPath, environment, and bare-command defaults apply. These native settings do not add command-line flags or modify the process environment.

Nexus path fields use / separators on every host, including Windows. Backslashes in declared paths are rejected. Resolved paths, source selections, and generated compiler path arguments retain /. Windows-native paths obtained from the OS or tool discovery are normalized when received; arbitrary tool arguments retain their original text.

A project requires records from explicitly imported ProjectIndex catalogs:

// Projects.nxscript, beside the consumer.
dialect "path/to/nxbuild.Language.nxscript";
ProjectIndex Projects {
    ProjectReference Archives {
        Id: "Local.Archives";
        Descriptor: "libraries/Archives.nxproject";
    }
}
// libraries/Archives.nxproject
dialect "path/to/nxbuild.Language.nxscript";
Project Archives {
    Id: "Local.Archives";
    Publishes Directories {
        Sources: ["src"];
        Headers: ["include"];
        Objects: ["path/to/external/output/objects"];
        Libraries: ["path/to/external/output/libraries"];
    }
}
// Consumer.nxproject
dialect "path/to/nxbuild.Language.nxscript";
module Projects "Projects.nxscript";
Project Consumer {
    Id: "Local.Consumer";
    Requires: [@Projects.Archives];
    FPC Application {
        SourceFiles: ["main.lpr"];
        OutputPath: "path/to/external/output/application";
    }
}

A named module selects the root with that name; it does not rename the root. Descriptor locators resolve from the catalog declaring them. nxbuild checks that the loaded project's Id matches its record, diagnoses missing projects and cycles, and rejects two descriptors claiming the same identity in one graph. Discovery uses local descriptors, without downloading dependencies.

Every requirement contributes all four directory categories recursively. A shared diamond dependency builds once per invocation. There are no category imports, filters or re-export declarations. Paths from a dependency retain their publisher's context, including target-selected variants and generated directories that do not exist yet.

Publication Pascal operation (NXPC / FPC) LLVM operation
Sources -Fu unit lookup Available in the resolved environment
Headers -Fi and -I includes -I includes
Objects -Fo object lookup Available for explicitly named inputs
Libraries -Fl library lookup -L during linking

A directory publication does not compile its contents or select linker inputs. Keep object filenames, library names and Pascal link directives explicit. For a practical explanation with NXArchive and Nexus Gear examples, see C/C++ dependencies in Pascal projects. SourceFiles is an operation's explicit compilation/link input list. It retains its order and repeated entries. Source masks expand at execution after required producers have run, so generated inputs are supported.

Operations are direct children in declaration order: FPC, LLVM, or Process. OutputPath supplies their working/output directory unless a Process specifies Directory. Configure every real build's output outside the source tree. The source-development environment's Development.OutputRoot defaults under the external worktree; set it to a unique worktree directory for isolated validation. Migrated repository descriptions establish the Nexus workspace root explicitly, keeping that setting consistent across differently located publishers.

SourceRoot and OutputRoot are ordinary reference values. Operations explicitly select their inputs and output directory. The native tool chooses output names; Clang-specific naming flags can be supplied through RawOptions or ConfigFiles.

Nexus Pascal compiler-native packages remain independent. An FPC operation can compile an .nxpk or consume .nxpl metadata using explicit SDK/package options. Requires never infers RequiredPackages, SDK identities or -FP flags. PackageSDKIdentity emits -Fj, PackageBuildIdentity emits -Fk, RequiredPackages emits -FP, and Files.PackagePaths emits -Fp. Use a matching compiler, RTL, startup units and SDK for runtime-package builds.

Installed resource projects

The shared Projects.nxscript catalog includes directory-only projects for installed SDK resources and RTL source support. A consumer requires the resources it uses; these projects have no build operations.

Project Published directories
NexusRTL Installed native RTL units
RTLSystem RTL system and object-Pascal source directories
RTLObjPas Object-Pascal support units and platform/CPU includes
RTLGenerics Generic collections and their includes
RTLExtra Additional platform RTL units and includes
NativeLibraries Native SDK library search directories
PackageSDK Runtime-package SDK units and its Windows library directory
AppleRTL RTL units from the selected Apple target SDK
RTLUnicodeRTL RTL units matching the Unicode build configuration

The RTL source projects publish their complete relevant source/include paths; consumers no longer reconstruct those directory layouts. Keep installed package SDK units before standalone RTL units, and installed RTL units before fallback sources in the requirement list. Ordinary project-local paths stay with the consumer. The Solar2D API project also publishes its existing Windows native plugin library directory.

Installation roots and compiler selection still come from the configuration modules. System headers stay in SystemIncludePaths because those use -isystem, while published Headers use -I. Package lookup stays in Files.PackagePaths (-Fp). Compiler executables, target triples, SDK identities, library names and linker options remain explicit settings; directory publication does not carry them.

Builders

FPC entries directly contain the existing typed FPC settings: SourceFiles, OutputPath, CompilerPath, Config, Files, Language, Syntax, Target, Linking, and the remaining compiler option sections in the dialect. For example:

FPC Application {
    SourceFiles: ["main.lpr"];
    CompilerPath: "tools/ppcx64.exe";
    OutputPath: "path/to/external/output/application";
    Config Options { DisableDefaultConfigFiles: True; }
    Language Pascal { Mode: ObjFPC; }
    Target Platform { OperatingSystem: "win64"; }
    Syntax Operators { COperators: Disabled; }
}

An FPC entry compiles each listed source separately, in order, with the same settings and OutputPath. FPC follows that source's unit dependencies as usual. A failure stops the remaining sources in that entry and all subsequent entries.

C-style operators default to enabled. Enabled emits -Sc, Disabled emits -Sc-, and Unset emits neither. CompilerPath is local to the entry; an omitted FPC compiler uses PP, then fpc. OutputPath supplies both -FE and -FU, directing executables and compiled units to the same destination. FPC chooses their names. The former Files.ExecutableOutputPath and Files.UnitOutputPath settings are replaced by this common property.

LLVM entries invoke Clang. Language is Auto, C, or CPP; CPP defaults to clang++, while Auto and C default to clang. CompilerPath overrides that choice. SourceFiles expands to the files passed to that single invocation. BuildKind is Program, SharedLibrary, or Object. Other named settings are OutputPath, RawOptions, ConfigFiles, Target, Standard, IncludePaths, SystemIncludePaths, LibraryPaths, Libraries, Defines, DebugInfo, and PositionIndependentCode. SystemIncludePaths uses -isystem for SDK/compiler headers; IncludePaths uses -I for project headers. Clang runs in OutputPath. RawOptions passes explicit native argument strings before the input list and libraries. For example, an Object entry with two source files can produce two object files in one invocation. Clang determines whether the supplied combination is buildable.

ConfigFiles passes native Clang configuration files in declaration order using --config. Paths resolve against RootDirectory; Clang reads and validates their contents during execution. This lets the compiler's own configuration describe its artifacts while nxbuild supplies OutputPath. See Clang configuration files.

SourceFiles accepts literal filenames and */? filename masks for both builders, for example:

SourceFiles: ["native/*.c", "support/helper.c"];

Masks expand when their build entry executes, so they can select files created by an earlier entry. Each mask searches only its stated directory, without recursion or wildcards in directory names. Matches use filesystem enumeration order; nxbuild does not sort them. Array declaration order and repeated files are preserved. List files explicitly when their compile order matters. An unmatched mask fails that entry and stops the build. Literal filenames are passed to the compiler, which reports missing or invalid input as usual.

Process operations

Process runs an executable directly, with an argument array and no shell. Directory is its working directory and defaults to OutputPath. Relative Directory/OutputPath values resolve against the project root; argument strings retain ordinary process semantics relative to Directory.

Process Generate {
    Executable: "python3";
    Directory: ".";
    OutputPath: @Example.OutputRoot + "/generated";
    Arguments: ["generate.py", @Example.OutputRoot + "/generated"];
}

An explicitly named tool may be produced by an earlier operation. Planning accepts that future executable beneath the earlier producer's output directory. Execution still stops if the producer fails or the tool cannot be launched.

Validation, planning and execution

nxbuild /action=validate /project=Project.nxproject /targetos=linux /targetcpu=x86_64
nxbuild /action=plan /project=Project.nxproject /targetos=linux /targetcpu=x86_64
nxbuild /action=build /project=Project.nxproject /targetos=linux /targetcpu=x86_64 /buildconfiguration=Release

validate checks the project model and complete graph without requiring installed tools. Both validate and plan display the selected OS, CPU and configuration, project identities, dependency edges and inherited directories. plan also checks explicitly located tools and shows operations. Bare command names are passed unchanged to process launching for normal executable lookup at execution; nxbuild does not search PATH or append filename extensions. Validation provides model/graph evidence; only build compiles the project. Neither action runs producers, expands source masks or creates output directories.

The complete TargetOS / TargetCPU / BuildConfiguration selection is passed unchanged to every dependency and its Nexus Script imports. Compiler options are explicit operation inputs: an FPC OS or LLVM triple may differ from the product selection when building a toolchain containing runtimes for several platforms. nxbuild does not choose or install a compiler automatically. OS and CPU default to the native nxbuild platform. BuildConfiguration defaults to Debug, including in the nxpackage project workbench. Configuration names are case-sensitive, matching Nexus Script target criteria; custom names such as Profile are accepted. An explicitly empty configuration is an error. Cross compilation needs appropriately configured compilers, RTLs and SDKs.

Additional selections can be supplied with /targets=Name:Value,Other:Value. They are available through the same Live $Name mechanism and are forwarded to dependencies. Names must be unique, including the three standard selection names; values may contain spaces and colons. Commas separate selections. For example, "/targets=BootstrapRoot:/path/to/worktree,Stage:cycle1" passes bootstrap locations without adding a bootstrap-specific nxbuild API.

Selected values are available as $TargetOS, $TargetCPU and $BuildConfiguration. Common and selected directories can share one publication:

Project Library {
    Id: "Local.Library";
    OutputRoot: "build/" + $TargetOS + "/" + $TargetCPU + "/" + $BuildConfiguration;
    Publishes Directories {
        Sources: ["src", "src/" + $TargetOS];
        Headers: ["include"];
        Objects: [@Library.OutputRoot + "/objects"];
        Libraries: [@Library.OutputRoot + "/libraries"];
    }
    // Producer operations use those same OutputRoot-based directories.
}

The migrated nxbuild descriptions include $BuildConfiguration in generated output paths. Source-only publications and prebuilt SDK paths remain independent where appropriate. Output paths are script expressions; nxbuild adds no directories automatically. Reuse the producer's output value in its publications so the published path matches its actual output. Consumers continue to require projects.

Configuration names select script criteria such as BuildConfiguration[Debug]. They do not automatically enable optimization, debug information or compiler defines. The project owns those settings. Existing projects keep their compiler settings while gaining separate output directories for each configuration.

build executes the dependency-first plan sequentially. FPC invokes its compiler once per source; LLVM uses one invocation for its list. Execution expands masks, creates each operation's output directory and waits for completion. A failure identifies the project/operation, preserves the tool's exit code and stops later operations. Directory/launch failures identify their responsible operation.

CMake, MSBuild and MSVC

These are typed build entries using installed tools and structured arguments. CompilerPath selects the executable explicitly; defaults are cmake, MSBuild, and cl/lib respectively. They do not require Nexus Forge or PowerShell.

  • CMake: Operation: Configure takes SourceDirectory, OutputPath, optional Generator and Definitions (NAME=value strings). Operation: Build uses OutputPath, optional Targets, Configuration, and positive Jobs. The upstream CMake project owns its dependency graph.
  • MSBuild: EntryPoint names a solution/project, with OutputPath, optional Configuration, Platform, Properties (NAME=value) and Targets. It runs in the solution/project directory and retains upstream ownership.
  • MSVC: BuildKind: Object compiles one explicit SourceFiles entry to OutputFile, relative to OutputPath. IncludePaths, Defines and RawOptions supply compiler settings. BuildKind: StaticLibrary combines the explicitly selected object files using lib and OutputFile.

Every build entry supports Environment: ["NAME=value", ...] for child-process variables and SearchPaths: ["tool/directory", ...] to prepend directories to that child's PATH. Search paths resolve from RootDirectory. Environment values are literal values, including any embedded paths. These settings preserve other inherited variables and never change the parent or later commands.

The Windows branch of nexus-mobile/Nexus2DEngine.nxproject delegates to the existing MSBuild solution. Nexus2D.Dependencies.nxproject builds its pinned external dependencies; Nexus Forge owns Git acquisition and staging.