Rules ForeignCc

Rules for building C/C++ projects using foreign build systems (non Bazel) inside Bazel projects.

Overview

Rules ForeignCc is designed to help users build projects that are not built by Bazel and also not fully under their control (ie: large and mature open source software). These rules provide a mechanism to build these external projects within Bazel's sandbox environment using a variety of C/C++ build systems to be later consumed by other rules as though they were normal cc rules.

Setup

Using bzlmod

Add the following content to your MODULE.bazel:

bazel_dep(name = "rules_foreign_cc", version = "{version}")

That's all you need for the default toolchains - rules_foreign_cc registers them for you. See bzlmod hub-and-spoke for the full extension API (tools.<tool>(...)), tools.explicit(), and built-in noop toolchains; Examples for copy-pasteable recipes; and Migrating from WORKSPACE to convert an existing project.

Using WORKSPACE

To use the ForeignCc build rules, add the following content to your WORKSPACE file:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "rules_foreign_cc",
    # TODO: Get the latest sha256 value from a bazel debug message or the latest
    #       release on the releases page: https://github.com/bazel-contrib/rules_foreign_cc/releases
    #
    # integrity = "...",
    strip_prefix = "rules_foreign_cc-{release_archive}",
    url = "https://github.com/bazel-contrib/rules_foreign_cc/archive/{release_archive}.tar.gz",
)

load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")

rules_foreign_cc_dependencies()

Please note that there are many different configuration options for rules_foreign_cc_dependencies which offer more control over the toolchains used during the build phase. Please see that macro's documentation for more details.

bzlmod hub-and-spoke

Under bzlmod, rules_foreign_cc exposes its toolchains through a single hub repository, @rules_foreign_cc_toolchains. The hub holds two kinds of target:

  • toolchain(...) entries, collected into a single :all target. rules_foreign_cc registers @rules_foreign_cc_toolchains//:all from its own MODULE.bazel, so every entry in it is a registered toolchain for the whole build. You do not register it yourself.
  • version-neutral aliases (e.g. cmake_src_all) into the spoke repos, for BUILD files that need to reach an archive directly.

The underlying per-version "spoke" repos hold the actual tools; the hub just points into them. Spoke names follow a fixed scheme per mode, so you can predict a spoke's name rather than look it up:

  • Binary spokes are named @<tool>-<version>-<os>-<arch>, e.g. @cmake-3.31.12-linux-x86_64 and @ninja-1.13.2-linux-x86_64 (target :<tool>_tool). <os> and <arch> are the Bazel platform names (linux/macos/windows, x86_64/aarch64/x86_32), so the suffix matches the toolchain's exec_compatible_with constraints. The one exception is cmake's macOS build: it ships a single universal2 binary that resolves for both x86_64 and aarch64 (so the toolchain carries no cpu constraint), and its arch token is universal - @cmake-3.31.12-macos-universal.
  • Source spokes are named @<tool>_src_<version>, e.g. @cmake_src_3.31.12, @make_src_4.4.1 (target :<tool>_tool).

For most users these names are an implementation detail: rules_foreign_cc registers the hub and you never touch the spokes directly.

For copy-pasteable recipes see Examples; to move an existing WORKSPACE project over, see Migrating from WORKSPACE.

How the hub is assembled

It helps to follow the chain from a tag to a registered toolchain, in order.

Step 1 - each tools.<tool>(...) tag has up to two effects. Every tag, from any module (root or transitive) and regardless of register_toolchain, declares a spoke repo for its tool/mode/version. Declaring is not downloading: Bazel materializes a spoke lazily, only when something references one of its targets (see Non-root modules and register_toolchain = False). On top of that, a tag that both comes from the root module and keeps the default register_toolchain = True adds a toolchain(...) entry to the hub. Non-root tags and register_toolchain = False tags only declare a spoke; they never add a hub entry.

Step 2 - rules_foreign_cc adds its own default entries. For tools the root didn't tag with a registering tag, rfcc contributes default toolchain(...) entries (the pinned cmake/ninja/etc.). Root entries sort ahead of rfcc's defaults in :all, so a registering root tag wins on conflict for that tool. tools.explicit() (root-only) drops rfcc's default entries entirely, leaving only the root's own; spoke declaration from Step 1 is unaffected.

Step 3 - rules_foreign_cc registers the hub. rfcc calls register_toolchains("@rules_foreign_cc_toolchains//:all") from its own MODULE.bazel, so every toolchain(...) entry collected in Steps 1-2 becomes a registered toolchain for the whole build. You never call register_toolchains for the hub yourself. This is also why register_toolchain = False suppresses registration without suppressing the spoke: it withholds the Step 1 hub entry, so there is nothing for Step 3 to register, but the spoke is still declared.

Minimal setup

If you want sensible defaults and don't care about specific versions, just depend on rules_foreign_cc:

bazel_dep(name = "rules_foreign_cc", version = "{version}")

That's it. rules_foreign_cc contributes its default tool set - cmake and ninja as prebuilt binaries, make, meson, and pkgconfig built from source, plus autoconf, automake, m4, and msbuild as system tools - and registers the hub for you from its own MODULE.bazel. (For the exact default mode and pinned version of each tool, see the per-tool support table below.) cmake and ninja additionally register an unconstrained system toolchain as a host-PATH fallback: the prebuilt binary wins on the platforms rfcc ships prebuilts for, and any other host falls back to a cmake/ninja on PATH rather than failing resolution. (nmake is not a default: it shares make's toolchain type, so it's selected only by an explicit toolchain = label, never registered for resolution.) bzlmod honors a dependency's register_toolchains(...) for the whole build, so you don't call it yourself.

The tools extension

Customisation goes through the tools module extension. You add only the tags for the tools you care about; every other tool keeps its default, and you still don't register anything yourself. (Tagging a tool replaces all of rfcc's default tags for that one tool - relevant for cmake and ninja, which default to a binary plus a system fallback; see the note in Minimal setup.)

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")

tools.cmake(version = "3.31.12", mode = "binary")
tools.ninja(mode = "system")
tools.make(mode = "system")  # opt out of source-build, use system make

use_repo(tools, "rules_foreign_cc_toolchains") and register_toolchains("@rules_foreign_cc_toolchains//:all") are only needed if you reference the hub repo by name in your own BUILD files, or if you opt out of rfcc's registration (see register_toolchain = False).

Omitting a tools.<tool>(...) tag entirely is how you accept rfcc's default mode and pinned default version for that tool. A bare tools.<tool>() tag with no attributes is rejected - it neither selects a tool variant nor constrains one, so it's a no-op (register_toolchain = False doesn't change that: with no mode/version/constraints there's nothing to declare or suppress). A tag must carry at least one of mode, version, exec_compatible_with, or target_compatible_with. Beyond that minimum the attributes still interact: a binary/source mode requires a version, while system/noop forbid one (see Tag attributes).

Each tool has its own tag class: tools.autoconf, tools.automake, tools.cmake, tools.m4, tools.make, tools.meson, tools.msbuild, tools.ninja, tools.nmake, tools.pkgconfig.

Tag attributes

All tools.<tool>(...) tags share the same shape:

AttributeTypeNotes
modestringOne of the modes supported by the tool. See the table below. If unset, the planner picks the highest-priority mode the tool supports (binary > source > system).
versionstringRequired when the resolved mode is binary or source; forbidden for system/noop and for versionless tools. Accepts an exact patch (3.31.12) or a major.minor.x wildcard (3.31.x) that resolves to that minor series' latest patch - see Version wildcards.
register_toolchainboolDefault True. If False, declare the spoke but skip registration - see below.
exec_compatible_withlabel listForwarded to the registered toolchain(...) target's exec_compatible_with.
target_compatible_withlabel listForwarded to the registered toolchain(...) target's target_compatible_with.

Per-tool support

ToolSupported modesDefault modeVersioned
autoconfsystem, noopsystemno
automakesystem, noopsystemno
cmakebinary, source, system, noopbinaryyes
m4system, noopsystemno
makesource, system, noopsourceyes
mesonsource, system, noopsourceyes
msbuildsystem, noopsystemno
ninjabinary, source, system, noopbinaryyes
nmakesystemsystemno
pkgconfigsource, system, noopsourceyes

The pinned default version for each versioned tool lives in foreign_cc/private/tool_specs.bzl (the default_version of each entry), the authoritative source for this whole table. The version numbers are omitted here on purpose: they move on every generator bump, and duplicating them in prose only invites drift.

Version wildcards

A version may be an exact patch (3.31.12) or a major.minor.x wildcard (3.31.x). A wildcard resolves to the latest patch rules_foreign_cc ships for that minor series:

tools.cmake(mode = "binary", version = "3.31.x")  # -> 3.31.12

Resolution happens before any repo is created, so the wildcard and the exact patch are interchangeable: version = "3.31.x" materializes the same @cmake-3.31.12-<platform> / @cmake_src_3.31.12 spoke as version = "3.31.12" would. This matches the WORKSPACE helpers (cmake_binary_spokes("3.31.x")), so the two dependency models behave identically.

An unknown wildcard (a minor series rfcc doesn't ship) is rejected with a message listing the accepted exact versions and wildcards.

tools.explicit()

By default, rules_foreign_cc contributes a baseline set of registrations into the hub so that downstream consumers Just Work. If you want full control:

Caution: tools.explicit() suppresses rfcc's default registrations entirely. Any tool you don't tag has no registered toolchain, so toolchain resolution fails for it (no matching toolchains found for ...). When you opt in, you must declare every tool your build actually uses.

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.explicit()

tools.cmake(version = "3.31.12", mode = "binary")
tools.ninja(version = "1.13.2", mode = "binary")
# ...declare every tool you want, or accept that resolution will fail for
# the ones you skipped.

tools.explicit() is a root-only opt-out. After it fires, the rfcc-default contributions are dropped entirely and the only registrations in the hub are those your root MODULE.bazel asks for.

tools.explicit() gates registration and singleton hub aliases only - it does not suppress spoke declaration. Spokes that any module (root or transitive) requests via tools.<tool>(...) are still declared (and materialized on reference), so a transitive dependency that says tools.cmake(version="3.21.7", register_toolchain=False) to reach a specific archive in its own scope keeps working under tools.explicit(). You just won't see those versions in the hub's :all list unless your root asks for them.

Non-root modules

Non-root tools.<tool>(...) tags declare their spoke (so the per-version repo is reachable inside that module's scope, materialized when referenced) but never contribute hub registrations or singleton aliases. The result: a transitive module pinned to a specific tool version keeps working without leaking that pin into the root's toolchain registration list.

If a transitive module wants cmake 3.21.7 and root wants cmake 3.31.12, both @cmake_src_3.21.7 and the root's binary spoke (@cmake-3.31.12-<platform>) are declared; the root's version is the registered toolchain of record.

register_toolchain = False

If you want the spoke declared (so the underlying repo and its targets are reachable, and materialized when you reference them) but you don't want it added to the hub's :all registration list - for example, because you're doing your own conditional registration - pass register_toolchain = False:

tools.cmake(version = "3.31.12", mode = "binary", register_toolchain = False)
use_repo(tools, "cmake-3.31.12-linux-x86_64")

Binary and source spokes differ in what they expose, so manual registration differs too:

Binary per-platform spokes ship only a native_tool_toolchain implementation target (:cmake_tool), not a toolchain(...) rule, so a bare register_toolchains(...) against it isn't enough. Wrap it in your own toolchain(...) with the appropriate toolchain_type and constraints, then register that:

# BUILD.bazel
toolchain(
    name = "cmake_tool_manual",
    exec_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    toolchain = "@cmake-3.31.12-linux-x86_64//:cmake_tool",
    toolchain_type = "@rules_foreign_cc//toolchains:cmake_toolchain",
)
# MODULE.bazel
register_toolchains("//:cmake_tool_manual")

Source spokes ship a registerable toolchain(...) rule directly, at @<tool>_src_<version>//:<tool>_toolchain, so you register it by label without wrapping anything:

# MODULE.bazel
register_toolchains("@cmake_src_3.31.12//:cmake_toolchain")

(The source spoke also exposes the underlying :<tool>_tool implementation target if you want to wrap it yourself, but you rarely need to.)

Built-in noop toolchains

rules_foreign_cc ships noop_<tool>_toolchain targets for every noop-capable tool (nmake has no noop mode -- it shares the make toolchain type, so use tools.make(mode = "noop") to no-op the make family):

  • @rules_foreign_cc//toolchains:noop_autoconf_toolchain
  • @rules_foreign_cc//toolchains:noop_automake_toolchain
  • @rules_foreign_cc//toolchains:noop_cmake_toolchain
  • @rules_foreign_cc//toolchains:noop_m4_toolchain
  • @rules_foreign_cc//toolchains:noop_make_toolchain
  • @rules_foreign_cc//toolchains:noop_meson_toolchain
  • @rules_foreign_cc//toolchains:noop_msbuild_toolchain
  • @rules_foreign_cc//toolchains:noop_ninja_toolchain
  • @rules_foreign_cc//toolchains:noop_pkgconfig_toolchain

Each one points its tool at false and exports the canonical env vars (CMAKE, NINJA, M4, etc.) pointing at the same. They make analysis succeed - toolchain resolution finds something - and execution fail loudly. This is intended for tests and other targets that need to build but never actually invoke the underlying tool. tools.<tool>(mode = "noop") is the extension-driven way to register one of these.

Limitations

The current surface does not handle these cases:

  • Major-only wildcards. A version is an exact patch or a major.minor.x wildcard (see Version wildcards); a bare major series like 3.x is not accepted.
  • Versions rfcc doesn't ship. A version must resolve to a version rules_foreign_cc has download URLs for; there is no way to point a tag at an arbitrary unsupported version.
  • Only the root shapes the default registration set. Non-root modules can declare spokes for their own scope but cannot append to the hub's :all registration list; that list is driven by the root module and rfcc's defaults.

bzlmod examples

Copy-pasteable MODULE.bazel recipes for the tools extension. For the full API reference see bzlmod hub-and-spoke; to convert an existing WORKSPACE project see Migrating from WORKSPACE.

You usually don't call register_toolchains yourself. rules_foreign_cc's own MODULE.bazel already registers @rules_foreign_cc_toolchains//:all, and bzlmod honors a dependency's registration for the whole build. Your tools.<tool>(...) tags shape what the hub contains; you don't need to re-register it or use_repo it. The only time you call register_toolchains / use_repo yourself is the Bring your own toolchain case below, or when you reference a hub alias / spoke repo by name in your own BUILD files.

Defaults only

Accept every tool's default mode and pinned version - just depend on rules_foreign_cc:

bazel_dep(name = "rules_foreign_cc", version = "{version}")

Pin a single version

Override just cmake; every other tool keeps its default:

bazel_dep(name = "rules_foreign_cc", version = "{version}")

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.cmake(version = "3.31.12", mode = "binary")

Note: overriding a tool replaces all of rfcc's default tags for that tool, not just the one you restate. cmake and ninja ship two defaults each - the prebuilt binary plus an unconstrained system host-PATH fallback (see Minimal setup) - so a lone tools.cmake(mode = "binary") drops the cmake system fallback, and resolution will fail on platforms rfcc has no prebuilt for. To keep the fallback, restate both tags:

tools.cmake(version = "3.31.12", mode = "binary")
tools.cmake(mode = "system")

Track the latest patch of a minor series

Use a major.minor.x wildcard to take whatever patch rules_foreign_cc ships for that minor series (here 3.31.x resolves to 3.31.12):

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.cmake(version = "3.31.x", mode = "binary")

Build a tool from source

Force cmake to build from source instead of downloading a prebuilt binary:

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.cmake(version = "3.31.12", mode = "source")

Use a host-installed tool

Skip downloading/building and use the tool already on the exec host. This is not hermetic - the build depends on what's installed - but it's useful for tools you don't want rules_foreign_cc to manage:

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.make(mode = "system")
tools.ninja(mode = "system")

Full control with tools.explicit()

Suppress rfcc's default registrations entirely and register only what you declare. Any tool you don't tag has no registered toolchain, so resolution fails for it:

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.explicit()

tools.cmake(version = "3.31.12", mode = "binary")
tools.ninja(version = "1.13.2", mode = "binary")
tools.make(version = "4.4.1", mode = "source")

Bring your own toolchain

Declare the spoke but register it yourself (e.g. with custom constraints or conditional logic). register_toolchain = False suppresses the hub entry:

# MODULE.bazel
tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.cmake(version = "3.31.12", mode = "binary", register_toolchain = False)
use_repo(tools, "cmake-3.31.12-linux-x86_64")

register_toolchains("//:cmake_tool_manual")
# BUILD.bazel
toolchain(
    name = "cmake_tool_manual",
    exec_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    toolchain = "@cmake-3.31.12-linux-x86_64//:cmake_tool",
    toolchain_type = "@rules_foreign_cc//toolchains:cmake_toolchain",
)

No-op a tool you don't need to run

Some build systems require a toolchain to resolve even if the tool is never run, or treat a tool as optional and simply skip the work when it's absent. mode = "noop" registers a placeholder that satisfies resolution (host-independent, unlike mode = "system") and points the tool at a path that fails when executed.

Whether that matters depends on the build: if nothing ever invokes the tool - e.g. a cmake build that declares an m4 dependency it doesn't use, or pkgconfig set to noop to skip optional package searches - the build succeeds and just skips that step. If the build does invoke the tool, it fails loudly at execution time rather than silently using a host binary.

tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools")
tools.explicit()

tools.cmake(version = "3.31.12", mode = "binary")
tools.ninja(version = "1.13.2", mode = "binary")
tools.m4(mode = "noop")
tools.pkgconfig(mode = "noop")

Migrating to the bzlmod hub

This page covers two migrations:

  1. From WORKSPACE to bzlmod (rules_foreign_cc_dependencies() → the tools extension).
  2. From the previous bzlmod surface (singleton spoke repos → version-suffixed spokes + hub aliases).

For the full API see bzlmod hub-and-spoke; for recipes see Examples.

From WORKSPACE

Before (WORKSPACE)

load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")

rules_foreign_cc_dependencies()

After (MODULE.bazel)

bazel_dep(name = "rules_foreign_cc", version = "{version}")

The bazel_dep alone reproduces the default tool set the WORKSPACE macro registered - rules_foreign_cc registers the hub from its own MODULE.bazel, and bzlmod honors that for the whole build. You only need the tools extension if you want to customize versions or modes, and even then you don't call register_toolchains yourself.

Mapping the old kwargs

rules_foreign_cc_dependencies(...) took several flags. Here's where each one goes under bzlmod:

WORKSPACE kwargbzlmod equivalent
register_default_tools = True (cmake/ninja)automatic; rfcc registers the hub for you
register_built_tools = True (build from source)tools.<tool>(mode = "source", version = "...") (an explicit version is required), or the source defaults in the hub
register_preinstalled_tools = True (host tools)tools.<tool>(mode = "system")
cmake_version = "3.31.12"tools.cmake(version = "3.31.12")
ninja_version = "1.13.2"tools.ninja(version = "1.13.2")
make_version = "4.4.1"tools.make(version = "4.4.1")
meson_version = "1.10.1"tools.meson(version = "1.10.1")
pkgconfig_version = "0.29.2"tools.pkgconfig(version = "0.29.2")
register_toolchains = Falseomit register_toolchains(...); register manually
native_tools_toolchains = [...]tools.<tool>(..., register_toolchain = False) + your own toolchain(...)

Selecting nmake by label (Windows)

If you build an MSVC target by pointing a rule's toolchain attribute at @rules_foreign_cc//toolchains:preinstalled_nmake_toolchain (e.g. cmake(name = "hello_nmake", toolchain = "@rules_foreign_cc//toolchains:preinstalled_nmake_toolchain")), that label still resolves under bzlmod - it's a static target in rules_foreign_cc, not something the hub generates. No change is needed; you do not need a tools.nmake(...) tag for this.

nmake has no noop mode: it shares the make toolchain type, so a noop nmake entry would carry no constraints and shadow the real make toolchain on every platform. tools.nmake(mode = "noop") is rejected at evaluation time. To no-op the make family, use tools.make(mode = "noop").

Running both during migration

You can keep your WORKSPACE working while you test the bzlmod path. Bazel selects the dependency model with --enable_bzlmod / --noenable_bzlmod (or the common --enable_bzlmod line in .bazelrc). Verify the bzlmod build before deleting WORKSPACE.

Note: this release makes rules_foreign_cc_dependencies() create a repo named @rules_foreign_cc_toolchains in WORKSPACE mode too (the hub that publishes the source-spoke aliases macros like meson_with_requirements rely on). If your own WORKSPACE already defines a repo by that name, rename yours to avoid the collision.

From the previous bzlmod surface

The version-suffixed source-archive repos replace the singleton names from the previous release. There is no zero-edit migration path; pick whichever of the patterns below matches what you reference in your BUILD files.

A root module's version tags now take effect

The previous tools extension read its cmake / ninja version tags only from non-root modules; a version set on the root module's own tag was not applied, so the build kept rfcc's default version. The registered toolchains are now driven by the root module's tags instead. (Transitive modules' tags still fetch spokes for their own scope but, as before, don't shape the hub's registration list - only the root and rfcc's own defaults do.) If your root MODULE.bazel already carried a tools.cmake(version = "...") or tools.ninja(version = "...") tag that previously had no effect, that version now applies - confirm it's the version you want. (This only matters if the pinned version differs from the default; if you weren't tagging cmake/ninja on the root, nothing changes.)

Drop the manual hub use_repo / register_toolchains

The previous bzlmod surface made you use_repo the extension's per-tool toolchain repos and register them yourself:

# Before -- previous bzlmod surface
use_repo(
    tools,
    "rules_foreign_cc_framework_toolchains",
    "cmake_3.31.12_toolchains",
    "ninja_1.13.2_toolchains",
    # ...source repos...
)
register_toolchains(
    "@rules_foreign_cc_framework_toolchains//:all",
    "@cmake_3.31.12_toolchains//:all",
    "@ninja_1.13.2_toolchains//:all",
)

@rules_foreign_cc_framework_toolchains is no longer the registration surface. The framework toolchains are still registered - the hub now carries them (the 00_framework entries in @rules_foreign_cc_toolchains), and rules_foreign_cc registers the hub from its own MODULE.bazel, so they resolve with no register_toolchains line at all. The aggregator repo is still minted, but nothing registers it and you no longer use_repo it. Delete the use_repo entries and the register_toolchains(...) calls above; leaving the @rules_foreign_cc_framework_toolchains//:all line in place would redundantly re-register the same framework toolchains. You only add a register_toolchains("@rules_foreign_cc_toolchains//:all") line back if you opted out of rfcc's own registration.

The per-version binary aggregators (@cmake_3.31.12_toolchains, @ninja_1.13.2_toolchains) aren't gone: a binary spoke still declares its aggregator repo. What changed is that nothing registers their toolchains for you and they're no longer in your use_repo list, so the hub's registrations win by default. If you want manual binary registration you can still use_repo one and register it yourself (see register_toolchain = False). Most consumers just delete the lines above and let the hub register the defaults.

bazel mod tidy will not clean these up for you: the tools extension reports reproducible = True and declares no use_repo-able repos of its own (the same as go_sdk and rules_python's pip), so mod tidy leaves the stale entries in place. Remove them by hand.

Renamed source repos (singleton → version-suffixed at default versions):

BeforeAfter
@cmake_src@cmake_src_3.31.12
@meson_src@meson_src_1.10.1
@gnumake_src@make_src_4.4.1
@ninja_build_src@ninja_src_1.13.2
@pkgconfig_src@pkgconfig_src_0.29.2

The per-platform binary spoke repos were also renamed to one scheme, @<tool>-<version>-<os>-<arch>, where <os> and <arch> are the Bazel platform names. This affects only code that referenced a binary spoke by its literal repo name (a use_repo entry or a hand-written toolchain(...) pointing at one); the hub and the aggregator repo names above are unchanged, so most consumers see nothing. The ninja spokes changed both separator and token (@ninja_1.13.2_linux -> @ninja-1.13.2-linux-x86_64), and cmake's upstream-derived platform tokens were normalized to Bazel spellings (@cmake-3.31.12-Linux-x86_64 -> @cmake-3.31.12-linux-x86_64, win64-x64 -> windows-x86_64). cmake's universal2 macOS build uses the arch token universal (@cmake-3.31.12-macos-universal). See bzlmod hub-and-spoke for the full scheme. These per-platform names are an implementation detail and not a stable API; pin the aggregator or the hub rather than a spoke if you need a name that won't move.

The aggregator repos themselves keep their names, but their per-platform toolchain(...) target names embed the spoke name, so those moved too (@ninja_1.13.2_toolchains//:ninja_1.13.2_linux_toolchain -> @ninja_1.13.2_toolchains//:ninja-1.13.2-linux-x86_64_toolchain). Registering @<tool>_<version>_toolchains//:all is unaffected; only a register_toolchains(...) pinned at one platform target by name needs the update.

The public build-from-source toolchain labels were also removed; they are now per-version spokes registered through the hub:

Removed labelReplacement
@rules_foreign_cc//toolchains:built_cmake_toolchaintools.cmake(mode = "source", version = "3.31.12") → hub registration
@rules_foreign_cc//toolchains:built_ninja_toolchaintools.ninja(mode = "source", version = "1.13.2") → hub registration
@rules_foreign_cc//toolchains:built_make_toolchaintools.make(mode = "source", version = "4.4.1") → hub registration
@rules_foreign_cc//toolchains:built_meson_toolchaintools.meson(mode = "source", version = "1.10.1") → hub registration
@rules_foreign_cc//toolchains:built_pkgconfig_toolchaintools.pkgconfig(mode = "source", version = "0.29.2") → hub registration

If you registered these labels explicitly (e.g. register_toolchains("@rules_foreign_cc//toolchains:built_make_toolchain")), you have two replacements. Either drop the register_toolchains(...) line and let the hub register a source-built default through @rules_foreign_cc_toolchains//:all (declare the tools.<tool>(mode = "source", version = "...") tag if you need a non-default version), or keep registering by label and point at the source spoke's own toolchain(...) target: register_toolchains("@make_src_4.4.1//:make_toolchain"), register_toolchains("@meson_src_1.10.1//:meson_toolchain"), and so on (@<tool>_src_<version>//:<tool>_toolchain). The source spoke ships that registerable toolchain(...) rule directly, unlike the binary per-platform spokes, which expose only a native_tool_toolchain you have to wrap yourself (see register_toolchain = False).

The autogenerated @rules_foreign_cc//toolchains:cmake_versions.bzl data file (CMAKE_SRCS) was also removed. It was a "DO NOT MODIFY" generated table, not a supported API; its data now lives at toolchains/private/cmake_versions.bzl as CMAKE_SRC_SRCS. If you loaded the old path directly, drop the dependency.

Pattern A - version-neutral, follow rfcc's defaults

If you don't care which version you get and want to track rfcc's defaults, reach the source archive through the hub's version-neutral aliases:

filegroup(
    name = "cmake_sources",
    srcs = ["@rules_foreign_cc_toolchains//:cmake_src_all"],
)

Hub aliases published per source-mode tool: cmake_src_all, cmake_built, make_src_all, make_built, meson_src_all, meson_built, meson_src_meson_py, meson_src_runtime, ninja_src_all, ninja_built, pkgconfig_src_all, pkgconfig_built.

Pattern B - pin the version yourself

If you want the version stable across rfcc upgrades, declare the spoke in your MODULE.bazel and reference its version-suffixed name:

# MODULE.bazel
tools.cmake(mode = "source", version = "3.21.7", register_toolchain = False)
use_repo(tools, "cmake_src_3.21.7")

# BUILD.bazel
filegroup(
    name = "cmake_sources",
    srcs = ["@cmake_src_3.21.7//:all_srcs"],
)

Don't blindly rename. Search-and-replacing @cmake_src@cmake_src_3.31.12 without declaring an explicit tools.cmake(mode = "source", version = "3.31.12") tag works today but breaks silently the day rfcc bumps its default cmake version - the suffixed repo will simply not exist. Either use Pattern A (hub alias) or Pattern B (declare the tag).

Common pitfalls

Error: no such package '@cmake_src//...': The repository '@cmake_src' could not be resolved Solution: The singleton source repos were renamed. Use the hub alias @rules_foreign_cc_toolchains//:cmake_src_all (Pattern A) or the version-suffixed @cmake_src_<version> after declaring the tag (Pattern B).

Error: no such target '@rules_foreign_cc_toolchains//:cmake_src_all' under tools.explicit() Solution: tools.explicit() drops the default source alias. Add an explicit tools.cmake(mode = "source", version = "...") so the hub knows which version to alias.

Error: no such target '@rules_foreign_cc_toolchains//:meson_src_meson_py' when calling the meson_with_requirements macro. Solution: That public macro reaches the hub's meson source aliases (through rfcc-owned @rules_foreign_cc//foreign_cc:meson_src_* aliases, so you do not need to use_repo the hub yourself). It does need a meson source spoke to exist. The defaults provide one automatically, but under tools.explicit() you must declare tools.meson(mode = "source", version = "...") yourself, otherwise the alias is never emitted.

Error: While resolving toolchains for target ...: no matching toolchains found for types @rules_foreign_cc//toolchains:cmake_toolchain Solution: Usually this means you used tools.explicit() and never tagged that tool - under tools.explicit() you must declare every tool you want registered. (You don't normally need a register_toolchains(...) line: rules_foreign_cc registers the hub for you. You'd only add one if you explicitly opted out of rfcc's registration.)

Error: a tools.<tool>() tag is rejected at evaluation time. Solution: A bare tag with no attributes is invalid - it neither selects a tool variant nor constrains one, so it's a no-op (register_toolchain = False doesn't change that). Pass at least one of mode, version, exec_compatible_with, or target_compatible_with.

Error: no such target '@rules_foreign_cc//toolchains:built_cmake_toolchain' (or built_ninja_toolchain / built_make_toolchain / built_meson_toolchain / built_pkgconfig_toolchain) Solution: The public built_*_toolchain labels were removed. The build-from-source toolchains are now per-version spokes registered through the hub. Declare a tools.<tool>(mode = "source", version = "...") tag (bzlmod) -- an explicit version is required in source/binary mode -- so the hub registers the source toolchain, or register the spoke's :<tool>_toolchain target by label yourself: register_toolchains("@make_src_4.4.1//:make_toolchain") (@<tool>_src_<version>//:<tool>_toolchain -- the source spoke ships a registerable toolchain(...); see register_toolchain = False).

Error: build picks up the wrong tool version after an rfcc upgrade. Solution: You were relying on a default version. Pin it with an explicit tools.<tool>(version = "...") tag.

Checklist

  1. Add bazel_dep(name = "rules_foreign_cc", version = "...") to MODULE.bazel. (This alone registers the default toolchains - you do not add a register_toolchains(...) line for the hub.)
  2. For any version or mode you pinned via rules_foreign_cc_dependencies(...), add the matching tools.<tool>(...) tag (see the kwarg table above).
  3. Replace any @cmake_src / @meson_src / etc. references with a hub alias (Pattern A) or a version-suffixed spoke (Pattern B).
  4. Build with --enable_bzlmod and confirm parity: bazel build //....
  5. Inspect what got registered if anything looks off: bazel query --output=build @rules_foreign_cc_toolchains//:all.
  6. Remove the WORKSPACE rules_foreign_cc_dependencies() call once green.

Rules

For additional rules/macros/providers, see the full API in one page.

CMake

Building CMake projects

  • Build libraries/binaries with CMake from sources using cmake rule
  • Use cmake targets in cc_library, cc_binary targets as dependency
  • Bazel cc_toolchain parameters are used inside cmake build
  • See full list of cmake arguments below 'example'
  • Works on Ubuntu, Mac OS and Windows (see special notes below in Windows section) operating systems

Example: (Please see full examples in ./examples)

The example for Windows is below, in the section 'Usage on Windows'.

  • In WORKSPACE.bazel, we use a http_archive to download tarballs with the libraries we use.
  • In BUILD.bazel, we instantiate a cmake rule which behaves similarly to a cc_library, which can then be used in a C++ rule (cc_binary in this case).

In WORKSPACE.bazel, put

workspace(name = "rules_foreign_cc_usage_example")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# Rule repository, note that it's recommended to use a pinned commit to a released version of the rules
http_archive(
   name = "rules_foreign_cc",
   sha256 = "c2cdcf55ffaf49366725639e45dedd449b8c3fe22b54e31625eb80ce3a240f1e",
   strip_prefix = "rules_foreign_cc-0.1.0",
   url = "https://github.com/bazel-contrib/rules_foreign_cc/archive/0.1.0.zip",
)

load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")

# This sets up some common toolchains for building targets. For more details, please see
# https://github.com/bazel-contrib/rules_foreign_cc/tree/main/docs#rules_foreign_cc_dependencies
rules_foreign_cc_dependencies()

_ALL_CONTENT = """\
filegroup(
    name = "all_srcs",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)
"""

# pcre source code repository
http_archive(
    name = "pcre",
    build_file_content = _ALL_CONTENT,
    strip_prefix = "pcre-8.43",
    urls = [
        "https://mirror.bazel.build/ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz",
        "https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz",
    ],
    sha256 = "0b8e7465dc5e98c757cc3650a20a7843ee4c3edf50aaf60bb33fd879690d2c73",
)

And in the BUILD.bazel file, put:

load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")

cmake(
    name = "pcre",
    cache_entries = {
        "CMAKE_C_FLAGS": "-fPIC",
    },
    lib_source = "@pcre//:all_srcs",
    out_static_libs = ["libpcre.a"],
)

then build as usual:

bazel build //:pcre

Usage on Windows

When using on Windows, you should start Bazel in MSYS2 shell, as the shell script inside cmake assumes this. Also, you should explicitly specify make commands and option to generate CMake crosstool file.

The default generator for CMake will be detected automatically, or you can specify it explicitly.

The tested generators: Visual Studio 15, Ninja and NMake. The extension .lib is assumed for the static libraries by default.

Example usage (see full example in ./examples/cmake_hello_world_lib): Example assumes that MS Visual Studio and Ninja are installed on the host machine, and Ninja bin directory is added to PATH.

cmake(
    # expect to find ./lib/hello.lib as the result of the build
    name = "hello",
    # This option can be omitted
    generate_args = [
        "-G \"Visual Studio 16 2019\"",
        "-A Win64",
    ],
    lib_source = ":srcs",
)

cmake(
    name = "hello_ninja",
    # expect to find ./lib/hello.lib as the result of the build
    lib_name = "hello",
    # explicitly specify the generator
    generate_args = ["-GNinja"],
    lib_source = ":srcs",
)

cmake(
    name = "hello_nmake",
    # explicitly specify the generator
    generate_args = ["-G \"NMake Makefiles\""],
    lib_source = ":srcs",
    # expect to find ./lib/hello.lib as the result of the build
    out_static_libs = ["hello.lib"],
)

cmake

load("@rules_foreign_cc//foreign_cc:cmake.bzl", "cmake")

cmake(name, deps, data, additional_inputs, additional_tools, alwayslink, build_args, build_data,
      cache_entries, configuration, copts, defines, dynamic_deps, env,
      experimental_validate_outputs_in_action, generate_args, generate_crosstool_file, includes,
      install, install_args, lib_name, lib_source, linkopts, out_bin_dir, out_binaries, out_data_dirs,
      out_data_files, out_dll_dir, out_headers_only, out_include_dir, out_interface_libs, out_lib_dir,
      out_shared_libs, out_static_libs, postfix_script, resource_size, set_file_prefix_map,
      static_suffix, targets, tool_prefix, tools_deps, working_directory)

Rule for building external library with CMake.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
build_argsArguments for the CMake build commandList of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
cache_entriesCMake cache entries to initialize (they will be passed with -Dkey=value) Values, defined by the toolchain, will be joined with the values, passed here. (Toolchain values come first)Dictionary: String -> Stringoptional{}
configurationOverride the cmake --build and cmake --install --config configuration. If left empty, the value of this arg will be determined by the COMPILATION_MODE env var: dbg will set --config Debug and all other modes will set --config Release.Stringoptional""
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
generate_argsArguments for CMake's generate command. Arguments should be passed as key/value pairs. eg: ["-G Ninja", "--debug-output", "-DFOO=bar"]. Note that unless a generator (-G) argument is provided, the default generators are Unix Makefiles for Linux and MacOS and Ninja for Windows.List of stringsoptional[]
generate_crosstool_fileWhen True, CMake crosstool file will be generated from the toolchain values, provided cache-entries and env_vars (some values will still be passed as -Dkey=value and environment variables). If CMAKE_TOOLCHAIN_FILE cache entry is passed, specified crosstool file will be used When using this option to cross-compile, it is required to specify CMAKE_SYSTEM_NAME in the cache_entriesBooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
installIf True, the cmake --install comand will be performed after a buildBooleanoptionalTrue
install_argsArguments for the CMake install commandList of stringsoptional[]
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
targetsA list of targets with in the foreign build system to produce. An empty string ("") will result in a call to the underlying build system with no explicit target setList of stringsoptional[]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]
working_directoryWorking directory, with the main CMakeLists.txt (otherwise, the top directory of the lib_source label files is used.)Stringoptional""

cmake_variant

load("@rules_foreign_cc//foreign_cc:cmake.bzl", "cmake_variant")

cmake_variant(name, toolchain, **kwargs)

Wrapper macro around the cmake() rule to force usage of the given make variant toolchain.

PARAMETERS

NameDescriptionDefault Value
nameThe target namenone
toolchainThe desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchainnone
kwargsRemaining keyword argumentsnone

A rule for building projects using the Configure+Make build tool

configure_make

load("@rules_foreign_cc//foreign_cc:configure.bzl", "configure_make")

configure_make(name, deps, data, additional_inputs, additional_tools, alwayslink, args, autoconf,
               autoconf_options, autogen, autogen_command, autogen_options, autoreconf,
               autoreconf_options, build_data, configure_command, configure_in_place,
               configure_options, configure_prefix, configure_xcompile, copts, defines, dynamic_deps,
               dynamic_module_ldflags_vars, env, executable_ldflags_vars,
               experimental_validate_outputs_in_action, includes, install_prefix, lib_name,
               lib_source, linkopts, out_bin_dir, out_binaries, out_data_dirs, out_data_files,
               out_dll_dir, out_headers_only, out_include_dir, out_interface_libs, out_lib_dir,
               out_shared_libs, out_static_libs, postfix_script, prefix_flag, resource_size,
               set_file_prefix_map, shared_ldflags_vars, static_suffix, targets, tool_prefix,
               tools_deps, unstubbed_regen_tools)

Rule for building external libraries with configure-make pattern. Some 'configure' script is invoked with --prefix=install (by default), and other parameters for compilation and linking, taken from Bazel C/C++ toolchain and passed dependencies. After configuration, GNU Make is called.

To prevent automake's mtime-driven regeneration recipes (e.g. aclocal.m4: configure.ac) from invoking version-suffixed tools like aclocal-1.16 at make time -- which Bazel's epoch-zero source mtimes routinely fire by leaving configure no newer than configure.ac, on RBE workers that don't have those tools installed -- the rule injects =true stubs for the regen tool variables (ACLOCAL, AUTOCONF, AUTOHEADER, AUTOM4TE, AUTOMAKE, HELP2MAN, MAKEINFO) onto the ./configure command line so configure substitutes them into the generated Makefile. The stubs are scoped to configure only; any autoreconf/autogen step the rule runs earlier still calls the real tools. To override a specific stub set the variable in env (typically to a real tool path); to fall back to configure's autodetected default for a variable, list it in unstubbed_regen_tools.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
argsA list of arguments to pass to the call to makeList of stringsoptional[]
autoconfSet to True if 'autoconf' should be invoked before 'configure', currently requires configure_in_place to be True.BooleanoptionalFalse
autoconf_optionsAny options to be put in the 'autoconf.sh' command line.List of stringsoptional[]
autogenSet to True if 'autogen.sh' should be invoked before 'configure', currently requires configure_in_place to be True.BooleanoptionalFalse
autogen_commandThe name of the autogen script file, default: autogen.sh. Many projects use autogen.sh however the Autotools FAQ recommends bootstrap so we provide this option to support that.Stringoptional"autogen.sh"
autogen_optionsAny options to be put in the 'autogen.sh' command line.List of stringsoptional[]
autoreconfSet to True if 'autoreconf' should be invoked before 'configure.', currently requires configure_in_place to be True.BooleanoptionalFalse
autoreconf_optionsAny options to be put in the 'autoreconf.sh' command line.List of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
configure_commandThe name of the configuration script file, default: configure. The file must be in the root of the source directory.Stringoptional"configure"
configure_in_placeSet to True if 'configure' should be invoked in place, i.e. from its enclosing directory.BooleanoptionalFalse
configure_optionsAny options to be put on the 'configure' command line.List of stringsoptional[]
configure_prefixA prefix for the call to the configure_command.Stringoptional""
configure_xcompileIf this is set and an xcompile scenario is detected, pass the necessary autotools flags.BooleanoptionalFalse
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
dynamic_module_ldflags_varsMake variables receiving linker flags for loadable dynamic modules. This is primarily useful on Darwin, where module builds cannot use conflicting -dynamiclib/-shared and -bundle linker flags together.List of stringsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
executable_ldflags_varsA list of variable names use as LDFLAGS for executables. These variables will be passed to the make command as make vars and overwrite what is defined in the Makefile.List of stringsoptional[]
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
install_prefixInstall prefix, i.e. relative path to where to install the result of the build. Passed to the 'configure' script with the flag specified by prefix_flag.Stringoptional""
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
prefix_flagThe flag to specify the install directory prefix with.Stringoptional"--prefix="
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
shared_ldflags_varsA list of variable names use as LDFLAGS for shared libraries. These variables will be passed to the make command as make vars and overwrite what is defined in the Makefile.List of stringsoptional[]
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
targetsA list of targets within the foreign build system to produce. An empty string ("") will result in a call to the underlying build system with no explicit target setList of stringsoptional["", "install"]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]
unstubbed_regen_toolsNames of automake regeneration-tool variables (a subset of ACLOCAL, AUTOCONF, AUTOHEADER, AUTOM4TE, AUTOMAKE, HELP2MAN, MAKEINFO) for which the rule should NOT inject the default =true stub on the configure command line. Use this when the package legitimately needs a real regeneration tool to run from a Makefile rule. Note that on RBE this typically requires the version-suffixed tool (e.g. aclocal-1.16) to be available on the worker.List of stringsoptional[]

configure_make_variant

load("@rules_foreign_cc//foreign_cc:configure.bzl", "configure_make_variant")

configure_make_variant(name, toolchain, **kwargs)

Wrapper macro around the configure_make() rule to force usage of the given make variant toolchain.

PARAMETERS

NameDescriptionDefault Value
nameThe target namenone
toolchainThe desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchainnone
kwargsRemaining keyword argumentsnone

A rule for building projects using the GNU Make build tool

make

load("@rules_foreign_cc//foreign_cc:make.bzl", "make")

make(name, deps, data, additional_inputs, additional_tools, alwayslink, args, build_data, copts,
     defines, dynamic_deps, dynamic_module_ldflags_vars, env, executable_ldflags_vars,
     experimental_validate_outputs_in_action, includes, install_prefix, lib_name, lib_source,
     linkopts, out_bin_dir, out_binaries, out_data_dirs, out_data_files, out_dll_dir,
     out_headers_only, out_include_dir, out_interface_libs, out_lib_dir, out_shared_libs,
     out_static_libs, postfix_script, resource_size, set_file_prefix_map, shared_ldflags_vars,
     static_suffix, targets, tool_prefix, tools_deps)

Rule for building external libraries with GNU Make. GNU Make commands (make and make install by default) are invoked with PREFIX="install" (by default), and other environment variables for compilation and linking, taken from Bazel C/C++ toolchain and passed dependencies. Not all Makefiles will work equally well here, and some may require patching.Your Makefile must either support passing the install prefix using the PREFIX flag, or it needs to have a different way to pass install prefix to it. An equivalent of make install MUST be specified as one of the targets.This is because all the paths with param names prefixed by out_* are expressed as relative to INSTALLDIR, not the source directory.That is, if you execute only make, but not make install, this rule will not be able to pick up any build outputs. Finally, your make install rule must dereference symlinks to ensure that the installed files don't end up being symlinks to files in the sandbox. For example, installation lines like cp $SOURCE $DEST must become cp -L $SOURCE $DEST, as the -L will ensure that symlinks are dereferenced.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
argsA list of arguments to pass to the call to makeList of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
dynamic_module_ldflags_varsMake variables receiving linker flags for loadable dynamic modules. This is primarily useful on Darwin, where module builds cannot use conflicting -dynamiclib/-shared and -bundle linker flags together.List of stringsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
executable_ldflags_varsA string list of variable names use as LDFLAGS for executables. These variables will be passed to the make command as make vars and overwrite what is defined in the Makefile.List of stringsoptional[]
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
install_prefixInstall prefix, i.e. relative path to where to install the result of the build. Passed as an arg to "make" as PREFIX=<install_prefix>.Stringoptional"$$INSTALLDIR$$"
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
shared_ldflags_varsA string list of variable names use as LDFLAGS for shared libraries. These variables will be passed to the make command as make vars and overwrite what is defined in the Makefile.List of stringsoptional[]
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
targetsA list of targets within the foreign build system to produce. An empty string ("") will result in a call to the underlying build system with no explicit target set. However, in order to extract build outputs, you must execute at least an equivalent of make install, and have your make file copy the build outputs into the directory specified by install_prefix.List of stringsoptional["", "install"]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]

make_variant

load("@rules_foreign_cc//foreign_cc:make.bzl", "make_variant")

make_variant(name, toolchain, **kwargs)

Wrapper macro around the make() rule to force usage of the given make variant toolchain.

PARAMETERS

NameDescriptionDefault Value
nameThe target namenone
toolchainThe desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchainnone
kwargsRemaining keyword argumentsnone

A rule for building projects using the Meson build system

meson

load("@rules_foreign_cc//foreign_cc:meson.bzl", "meson")

meson(name, deps, data, additional_inputs, additional_tools, alwayslink, build_args, build_data,
      copts, defines, dynamic_deps, env, experimental_validate_outputs_in_action, includes, install,
      install_args, lib_name, lib_source, linkopts, options, out_bin_dir, out_binaries, out_data_dirs,
      out_data_files, out_dll_dir, out_headers_only, out_include_dir, out_interface_libs, out_lib_dir,
      out_shared_libs, out_static_libs, postfix_script, resource_size, set_file_prefix_map,
      setup_args, shared_ldflags_option, static_suffix, target_args, targets, tool_prefix, tools_deps)

Rule for building external libraries with Meson.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
build_argsdeprecated: please use target_args with 'build' target key.List of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
installdeprecated: please use targets if you want to skip install.BooleanoptionalTrue
install_argsdeprecated: please use target_args with 'install' target key.List of stringsoptional[]
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
optionsMeson setup options (converted to -Dkey=value)Dictionary: String -> Stringoptional{}
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
setup_argsdeprecated: please use target_args with 'setup' target key.List of stringsoptional[]
shared_ldflags_optionName of additional setup option that will contain shared ldflags.Stringoptional""
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
target_argsDict of arguments for each of the Meson targets. The target name is the key and the list of args is the value.Dictionary: String -> List of stringsoptional{}
targetsA list of targets to run. Defaults to ['compile', 'install']List of stringsoptional["compile", "install"]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]

export_for_test.list_to_str_repr

load("@rules_foreign_cc//foreign_cc:meson.bzl", "export_for_test")

export_for_test.list_to_str_repr(lst)

PARAMETERS

NameDescriptionDefault Value
lst

-

none

meson_with_requirements

load("@rules_foreign_cc//foreign_cc:meson.bzl", "meson_with_requirements")

meson_with_requirements(name, requirements, **kwargs)

Wrapper macro around Meson rule to add Python libraries required by the Meson build.

PARAMETERS

NameDescriptionDefault Value
nameThe target namenone
requirementsList of Python "requirements", see https://github.com/bazelbuild/rules_python/tree/00545742ad2450863aeb82353d4275a1e5ed3f24#using-third_party-packages-as-dependenciesnone
kwargsRemaining keyword argumentsnone

MSBuild

This rule is tailored for MSBuild.exe from the Visual Studio installation. It does not support the dotnet msbuild execution path. MSBuild determines it own compile and linker flags based on the project/solution file configuration. This cannot be fully controlled from bazel like other rules (e.g. cmake). We do our best by generating a msbuild.props file that is used by specifying -p:ForceImportAfterCppTargets=msbuild.props to append bazel flags and override existing flags where possible.

Since MSBuild is closed source project from Microsoft, there is no prebuilt toolchain available and we cannot build it from source. The default is a pre-installed toolchain which assumes MSBuild.exe is installed as a part of Visual Studio and locateable by bazel. If you want to implement your own MSBuild toolchain you will need to define a toolchain that implements the toolchain type @rules_foreign_cc//toolchains:msbuild_toolchain. E.g.

toolchain(
    name = "msbuild_toolchain",
    exec_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    toolchain = ":_msbuild_toolchain",
    toolchain_type = "@rules_foreign_cc//toolchains:msbuild_toolchain",
)

native_tool_toolchain(
    name = "_msbuild_toolchain",
    path = "<Path to MSBuild.exe inside target>",
    target = "<Label to toolchain target>",
    env = {
        "MSBUILD": "$(execpath <Label for MSBuild.exe>)",
    },
)

native_tool_toolchain should refer to the target where your MSBuild binary/files reside.

When using your own toolchain, it may also be necessary to set the following properties for MSBuild:

# Use env from bazel toolchain, don't override it.
"-p:UseEnv=true",
"-p:SetEnvOverride=false",

# Toolchain config
"-p:PlatformToolset=", # e.g "v143" for Visual Studio 2022
"-p:VCToolsRedistVersion=",
"-p:VCInstallDir=<path to Visual C++ install dir>",
"-p:VCInstallDir_170=<path to Visual C++ install dir for Visual Studios 2022>",

# SDK configuration
"-p:WindowsSdkDir_10=<path to windows sdk>",
"-p:WindowsKitsRoot=<path to windows sdk>",

# Skip the problematic SDK check target
"-p:_CheckWindowsSDKInstalled=",

# Bypass Windows SDK validation checks
"-p:WindowsSDKInstalled=true",
"-p:WindowsSDK_Desktop_Support=true",

The MSBuild Configuration property is controlled by the configuration attribute. When left unset it follows the Bazel compilation mode, defaulting to Debug under -c dbg and Release otherwise (matching the cmake rule).

The MSBuild Platform property is controlled by the platform attribute. It is left unset by default so MSBuild picks the platform declared in the solution or project file. A .sln only builds the Configuration|Platform pairs it declares, so forcing a platform that the solution does not declare fails with MSB4126; set platform only when the project supports it.

MSBuild projects must copy their outputs into $(OutDir) using the layout declared on the rule. For example, with the default include directory and out_static_libs = ["mylib.lib"], the project should produce $(OutDir)mylib.lib and copy public headers under $(OutDir)include.

msbuild

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "msbuild")

msbuild(name, deps, data, additional_inputs, additional_tools, alwayslink, args, build_data,
        configuration, copts, defines, dynamic_deps, env, experimental_validate_outputs_in_action,
        includes, lib_name, lib_source, linkopts, out_bin_dir, out_binaries, out_data_dirs,
        out_data_files, out_dll_dir, out_headers_only, out_include_dir, out_interface_libs,
        out_lib_dir, out_shared_libs, out_static_libs, platform, postfix_script, properties,
        resource_size, set_file_prefix_map, sln_file_path, static_suffix, targets, tool_prefix,
        tools_deps, verbosity)

Rule for building external library with MSBuild.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
argsArgs for MSBuild.exe. e.g. '-p:PlatformToolset=v143'List of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
configurationMSBuild Configuration to build. When unset, defaults to Debug in -c dbg compilation mode and Release otherwise, mirroring the cmake rule. Usually either Debug or Release.Stringoptional""
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
platformMSBuild Platform to build (e.g. x64, Win32, ARM64). When unset, the -p:Platform flag is omitted and MSBuild selects the platform from the solution or project file. This is deliberately not derived from the target CPU: a .sln only builds Configuration|Platform pairs it declares, so forcing a mismatched platform fails with MSB4126. Set this explicitly when the project supports it.Stringoptional""
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
propertiesA map of properties (-p:) for MSBuild. Do not set Configuration or Platform; use the dedicated attributes instead.Dictionary: String -> Stringoptional{}
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
sln_file_pathSolution or project file path, relative to the detected lib_source root.Stringrequired
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
targetsList of MSBuild targets in the projectList of stringsoptional[]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]
verbosityVerbosityLevel of msbuild logs. One of 'quiet', 'minimal', 'normal', 'detailed', 'diagnostic'.Stringoptional"normal"

export_for_test.msbuild_dep_paths

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "export_for_test")

export_for_test.msbuild_dep_paths(deps, inputs)

PARAMETERS

NameDescriptionDefault Value
deps

-

none
inputs

-

none

export_for_test.msbuild_properties

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "export_for_test")

export_for_test.msbuild_properties(user_properties, configuration, platform)

PARAMETERS

NameDescriptionDefault Value
user_properties

-

none
configuration

-

none
platform

-

none

export_for_test.sln_file_path

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "export_for_test")

export_for_test.sln_file_path(sln_file_path, lib_source_files, root)

PARAMETERS

NameDescriptionDefault Value
sln_file_path

-

none
lib_source_files

-

none
root

-

none

A rule for building projects using the Ninja build tool

ninja

load("@rules_foreign_cc//foreign_cc:ninja.bzl", "ninja")

ninja(name, deps, data, additional_inputs, additional_tools, alwayslink, args, build_data, copts,
      defines, directory, dynamic_deps, env, experimental_validate_outputs_in_action, includes,
      lib_name, lib_source, linkopts, out_bin_dir, out_binaries, out_data_dirs, out_data_files,
      out_dll_dir, out_headers_only, out_include_dir, out_interface_libs, out_lib_dir,
      out_shared_libs, out_static_libs, postfix_script, resource_size, set_file_prefix_map,
      static_suffix, targets, tool_prefix, tools_deps)

Rule for building external libraries with Ninja.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
argsA list of arguments to pass to the call to ninjaList of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
directoryA directory to pass as the -C argument. The rule will always use the root directory of the lib_sources attribute if this attribute is not setStringoptional""
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
targetsA list of targets with in the foreign build system to produce. An empty string ("") will result in a call to the underlying build system with no explicit target setList of stringsoptional[]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]