Skip to content

Toolchain

Machine.toolchain, also carried in the snapshot, reports the C, C++, and CUDA compilers and build systems found on the host PATH, so a tool can learn the machine's real build capability without shelling out itself.

from mainboard import Machine

toolchain = Machine().toolchain
for tool in toolchain.tools:
    print(tool.name, tool.version, tool.path)

Only tools that are actually on PATH are kept, so the list reflects what the host can really run. Each tool keeps its registered order, grouped by category.

In the snapshot

The toolchain field of Machine().model_dump_json() lists every available tool:

{
  "tools": [
    {
      "name": "gcc",
      "category": "c-compiler",
      "path": "/usr/bin/gcc",
      "version": "13.2.0",
      "available": true
    },
    {
      "name": "clang",
      "category": "c-compiler",
      "path": "/usr/bin/clang",
      "version": "21.0.0",
      "available": true
    },
    {
      "name": "nvcc",
      "category": "cuda-compiler",
      "path": "/usr/local/cuda/bin/nvcc",
      "version": "13.0",
      "available": true
    },
    {
      "name": "cmake",
      "category": "build-system",
      "path": "/usr/bin/cmake",
      "version": "3.28.3",
      "available": true
    },
    {
      "name": "ninja",
      "category": "build-system",
      "path": "/usr/bin/ninja",
      "version": "1.11.1",
      "available": true
    }
  ]
}

version is null when the tool is present but its version output cannot be parsed.

DetectedTool

Each entry in tools is a DetectedTool, the structured result of one probe.

field type meaning
name str display name of the tool, e.g. gcc or cmake
category ToolCategory toolchain group the tool belongs to
path str \| None absolute path to the resolved binary, None when not on PATH
version str \| None parsed version string, None when absent or unparseable
available bool whether the binary was found on PATH

ToolCategory

ToolCategory is a StrEnum that buckets each tool.

member value
C_COMPILER c-compiler
CXX_COMPILER cxx-compiler
CUDA_COMPILER cuda-compiler
BUILD_SYSTEM build-system

Toolchain.by_category regroups the available tools into these buckets.

from mainboard import Machine, ToolCategory

toolchain = Machine().toolchain
cuda = toolchain.by_category.get(ToolCategory.CUDA_COMPILER, ())
print([tool.name for tool in cuda])

How it is probed

Discovery is data-driven. A ToolProbe is an immutable recipe for finding one tool, and the module-level TOOL_PROBES tuple is the registry that Toolchain.probe() runs.

field type meaning
name str display name reported on the DetectedTool
category ToolCategory toolchain group the tool belongs to
binaries tuple[str, ...] candidate executable names, tried in order until one is on PATH
version_args tuple[str, ...] arguments that make the binary print its version, default ("--version",)
pattern re.Pattern[str] regex whose first group captures the version from the command output

For each probe, the first binary found on PATH wins. Its version output is captured and the pattern's first group becomes version. The default registry covers gcc, clang, g++, clang++, nvcc, cmake, ninja, make, and meson.

Extending the registry

Adding a tool is one line. Append a ToolProbe to TOOL_PROBES and it is discovered on the next probe, with no change to the discovery logic.

from mainboard.models.toolchain import TOOL_PROBES, ToolProbe
from mainboard import ToolCategory

bazel = ToolProbe("bazel", ToolCategory.BUILD_SYSTEM, ("bazel",))
probes = (*TOOL_PROBES, bazel)

from mainboard import Toolchain

toolchain = Toolchain.probe(probes)

A tool with a non-standard version command sets version_args and pattern.

import re
from mainboard.models.toolchain import ToolProbe
from mainboard import ToolCategory

icx = ToolProbe(
    "icx",
    ToolCategory.C_COMPILER,
    ("icx",),
    version_args=("--version",),
    pattern=re.compile(r"(\d+\.\d+\.\d+)"),
)

A brand-new family of tools is one ToolCategory member plus its probes, so the model grows by adding code rather than editing the probe loop.