OxL Reference

Parallel build

Parallel build#

The program and the reachable part of std form one LLVM module. After optimisation (single-threaded) the module is cut into codegen units: each unit is compiled to its own object file on its own thread, and all objects go to the linker. This applies to every command that builds a program: oxl build, oxl run, oxl test.

Units and threads are different things#

WhatFlagEnvironmentoxl.tomlChanges the output
Number of units--codegen-units N (1..256)OXL_CODEGEN_UNITS[profile.<name>] codegen-units = Nyes
Number of threads-j N / --jobs NOXL_JOBS—no
Linker--linker auto|lld|bfd|gold|default|<path>OXL_LD—yes (another file)

Precedence: flag, environment, oxl.toml, automatic choice.

  • Reproducibility. The binary depends on the number of units only, never on -j, the number of cores or thread scheduling: the module is split and serialised in a fixed order, only the code generation of the finished parts runs in parallel, and the objects reach the linker in unit order. -j1 and -j8 builds with the same units are byte-identical (D-1403, D-9001).
  • Automatic choice. Without an explicit number the units depend on the module content only: one unit per ~5000 optimised instructions, at most 8. A small program (examples/hello) is one unit, as before. The number of cores never matters, so every machine produces the same file.
  • Local symbols of the module become external with hidden visibility when it is split; none of them is exported from the executable.
  • A profile with lto = true and --emit-llvm are not split: LTO stays one module (the object is bitcode, lld optimises).
  • macOS: always one unit (the Mach-O debug map and the reproducible UUID need one object); the flags are accepted and ignored.
  • Cost: debug info and metadata are duplicated between the parts, so the binary is slightly larger (see the section on parallel builds in the benchmarks). For the fastest and smallest binary use --codegen-units 1.

Linker#

When ld.lld (or ld.lld-18) is in PATH, oxl links with -fuse-ld=lld: about 50 ms instead of about 160 ms with GNU ld. Without lld everything works as before (the driver's own linker is used silently). An automatically chosen lld that fails is replaced by the default linker and the link is retried. --linker bfd (or OXL_LD=bfd) forces GNU ld, --linker default passes no -fuse-ld, --linker /path/to/ld uses your linker. oxl doctor shows the choice. The linker is part of the build cache key.

Build cache#

The local build cache key (OXL_BUILD_CACHE=1, D-6313) contains the number of units and the linker, not the number of threads.

Tests#

oxl test accepts --codegen-units N and --linker; build threads come from OXL_JOBS (-j of oxl test is the number of tests running at once). Workspace members are built one after another, each build is parallel inside.

OxL 1.0.0-beta · Documentation version 1.0.0-beta© OxwaldLink · generated from the Standard, the std sources and the guides