tomato·bazeldocs v0 · latest
Docs/Reference/Modules/rules_autoconf

rules_autoconf

Bazel-native autoconf-style configuration. cc_check_{header,function,symbol} + config_header — replaces autoconf+m4 with a graph of cache-aware Bazel actions.

Latest0.1.0
Versions1
CategoryBazel rules
Compat level1
MaintainersMatt Marshall
Registryhttps://registry.tbzl.dev/modules/rules_autoconf/
Sourcegithub.com/tomato-bazel/rules_autoconf
MODULE.bazelstarlark
bazel_dep(name = "rules_autoconf", version = "0.1.0")

View source & releases on GitHub ↗

Bazel-native autoconf-style configuration. Replaces the autoconf+m4 shell pipeline with Bazel rules that compose probe results into a graph.

  • cc_check_header — autoconf’s AC_CHECK_HEADER. Bazel-native equivalent.
  • cc_check_function — autoconf’s AC_CHECK_FUNC (compile + link test).
  • cc_check_symbol — autoconf’s AC_CHECK_DECL / AC_CHECK_TYPE.
  • config_header — autoconf’s AC_CONFIG_HEADERS. Renders a config.h template from a defines dict + probe results.

See docs/defs.md for the full reference.

What this is and isn’t (v0.1)

Is: the Bazel-native seed of an autoconf replacement. Probes execute as Bazel actions, so their results compose into the build graph and are cache-aware. No shell, no m4, no configure script generation.

Isn’t (yet): a full autoconf clone. v0.1 covers the most common AC_* primitives — enough to ground a hand-written config.h.in against the host. The long tail (AC_C_BIGENDIAN, AC_CHECK_SIZEOF, AC_FUNC_* function-specific tests, AC_PROG_* program detection) lands in subsequent releases.

Doesn’t run real autoconf: v0.1 has no autoconf or m4 binary dependency. The probes use the host C compiler (whatever $CC resolves to, defaulting to cc). For projects that ship a pre-generated configure script (like PostgreSQL), a future configure_run rule will let you invoke it under Bazel sandboxing without needing autoconf itself. For projects that need autoconf-generated configure scripts built on the fly, that’s v0.3+ work.

Install

Add the registry to your .bazelrc:

common --registry=https://registry.fastverk.com/
common --registry=https://bcr.bazel.build/

In your MODULE.bazel:

bazel_dep(name = "rules_autoconf", version = "0.1.0")

Quick start

A typical autoconf project has a config.h.in template with #undef stubs. Tell rules_autoconf which probes to run and what static values to substitute:

load(
    "@rules_autoconf//autoconf:defs.bzl",
    "cc_check_function",
    "cc_check_header",
    "config_header",
)

cc_check_header(name = "have_stdio_h",      header = "stdio.h")
cc_check_header(name = "have_sys_socket_h", header = "sys/socket.h")

cc_check_function(
    name     = "have_strlcpy",
    function = "strlcpy",
    header   = "string.h",
)

cc_check_function(
    name      = "have_openssl_init_ssl",
    function  = "OPENSSL_init_ssl",
    header    = "openssl/ssl.h",
    libraries = ["ssl", "crypto"],
)

config_header(
    name    = "config_h",
    out     = "config.h",
    template = "config.h.in",
    defines = {
        "PACKAGE_NAME":    "\"myproj\"",
        "PACKAGE_VERSION": "\"0.1.0\"",
    },
    probes = [
        ":have_stdio_h",
        ":have_sys_socket_h",
        ":have_strlcpy",
        ":have_openssl_init_ssl",
    ],
)

bazel build //path/to:config_h runs each probe as a Bazel action, captures its success/failure, and stamps the result into config.h:

/* config.h */
#define PACKAGE_NAME "myproj"
#define PACKAGE_VERSION "0.1.0"
#define HAVE_STDIO_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_STRLCPY 1
#undef HAVE_OPENSSL_INIT_SSL          /* OpenSSL not in -lssl -lcrypto on this host */

The probes are content-addressed by their inputs (header name, function signature, library list, host compiler), so they’re cached: rebuilding without changing probe attrs reuses results. Changing a probe attr invalidates only its own result and the downstream config_header.

How it differs from rules_foreign_cc

rules_foreign_cc wraps autoconf+make+cmake builds end-to-end as opaque cc_library outputs. rules_autoconf instead replaces the autoconf step with Bazel-native primitives — you keep fine-grained control over the resulting cc_library graph, but you lose the ability to drive an existing configure.ac directly. The two complement each other:

  • Use rules_foreign_cc if you want a Bazel-managed build of an autoconf project without doing the dependency surgery yourself.
  • Use rules_autoconf if you want a hand-written, fine-grained Bazel build of an autoconf project and just need the config.h generated correctly.

Roadmap

VersionAdds
v0.1 (this)cc_check_{header,function,symbol}, config_header
v0.2cc_check_sizeof, cc_check_bigendian, cc_check_decl (compile-only function probe), cc_check_libraries (cumulative -l detection)
v0.3configure_run rule for projects shipping pre-generated configure scripts
v0.4autoconf+m4 binaries packaged as Bazel toolchains (built from source under Bazel via hand-rolled cc_library for m4)
v0.5+Long-tail AC_* macros, AC_ARG_ENABLE / AC_ARG_WITH equivalents, optional Bazel C-toolchain integration replacing host $CC

Limitations of v0.1

  • Probes use the host compiler via $CC (default cc). The Bazel C toolchain integration that would make probes fully hermetic against the registered cc_toolchain lands in v0.5+.
  • No cross-compilation — probes always run on the exec platform.
  • No AC_TRY_RUN-style probes that need to execute the test binary. Compile+link is sufficient for most checks; run-time probes (like AC_C_BIGENDIAN’s fallback path) are deferred.
  • No @VAR@ substitution in non-header files yet — only the header template path. Adding generic file substitution is straightforward but not in v0.1.

Compatibility

  • Bazel: 7.4+, bzlmod required.
  • Host: a C compiler on $PATH (or $CC set).
  • Platforms: any host with a working C compiler. Tested on darwin_aarch64 and linux_x86_64.

Contributing

Reference docs (docs/defs.md) are stardoc-generated from the .bzl docstrings. After editing a rule docstring:

bazel run //docs:update

CI gates this via bazel test //docs/... plus the end-to-end smoke build in examples/hello/.

License

MIT.

Usage#

Real usage, taken from the module’s examples/.

examples/hello/BUILD.bazel

load(
    "@rules_autoconf//autoconf:defs.bzl",
    "cc_check_function",
    "cc_check_header",
    "config_header",
)

# Header probes — should succeed for std headers, fail for the fake one.
cc_check_header(
    name = "have_stdio_h",
    header = "stdio.h",
)

cc_check_header(
    name = "have_string_h",
    header = "string.h",
)

cc_check_header(
    name = "have_fake_h",
    header = "this_header_does_not_exist.h",
)

# Function probes — strlen is libc; nonexistent_function_42 isn't.
cc_check_function(
    name = "have_strlen",
    function = "strlen",
    header = "string.h",
)

cc_check_function(
    name = "have_nonexistent",
    define_name = "HAVE_NONEXISTENT_FUNCTION_42",
    function = "nonexistent_function_42",
)

# Compose probes + static defines into config.h.
config_header(
    name = "config_h",
    out = "config.h",
    defines = {
        "PACKAGE_NAME": "\"hello\"",
        "PACKAGE_VERSION": "\"0.1.0\"",
    },
    probes = [
        ":have_stdio_h",
        ":have_string_h",
        ":have_fake_h",
        ":have_strlen",
        ":have_nonexistent",
    ],
    template = "config.h.in",
)

Rules & providers#

Generated with Stardoc from the module's .bzl sources.

from docs/defs.md

User-facing rules for rules_autoconf.

The Bazel-native equivalents of common autoconf AC_* primitives. Each rule emits a single result file that other rules (notably config_header) consume — so probe results compose into a graph, not into shell-script global state.

The probes use Python tools that shell out to the host C compiler. The host compiler choice is the CC env var (defaults to cc). v0.1 does NOT use Bazel’s @bazel_tools//tools/cpp C toolchain — it relies on whatever cc resolves to on the host. v0.2+ will integrate the proper Bazel C toolchain for full hermeticity.

Available rules: cc_check_header — autoconf’s AC_CHECK_HEADER cc_check_function — autoconf’s AC_CHECK_FUNC (link test) cc_check_symbol — autoconf’s AC_CHECK_DECL / AC_CHECK_TYPE config_header — autoconf’s AC_CONFIG_HEADERS (renders config.h from a template + define dict + probe results)

cc_check_function

load("@rules_autoconf//autoconf:defs.bzl", "cc_check_function")

cc_check_function(name, define_name, function, header, libraries)

Probe whether a C function is linkable. Bazel-native equivalent of autoconf’s AC_CHECK_FUNC.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
define_nameOverride the macro name. Defaults to HAVE_<FUNCTION> (uppercased).Stringoptional""
functionFunction to probe (e.g. “strlcpy”, “getifaddrs”).Stringrequired
headerOptional header to #include (e.g. “string.h”). Some functions need a declaration to compile cleanly.Stringoptional""
librariesLibraries to link (each becomes -l).List of stringsoptional[]

cc_check_header

load("@rules_autoconf//autoconf:defs.bzl", "cc_check_header")

cc_check_header(name, define_name, header)

Probe whether a C header is includable. Bazel-native equivalent of autoconf’s AC_CHECK_HEADER.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
define_nameOverride the macro name. Defaults to HAVE_<HEADER> (uppercased, non-alphanumeric -> underscore).Stringoptional""
headerHeader to probe (e.g. “string.h”, “sys/socket.h”).Stringrequired

cc_check_symbol

load("@rules_autoconf//autoconf:defs.bzl", "cc_check_symbol")

cc_check_symbol(name, define_name, header, symbol)

Probe whether a symbol is declared. Bazel-native equivalent of autoconf’s AC_CHECK_DECL.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
define_nameOverride the macro name. Defaults to HAVE_DECL_<SYMBOL>.Stringoptional""
headerHeader to #include to bring the symbol into scope.Stringoptional""
symbolSymbol/identifier to probe. Works for type names, macros, enum members, function declarations.Stringrequired

config_header

load("@rules_autoconf//autoconf:defs.bzl", "config_header")

config_header(name, out, defines, probes, template)

Render an autoconf-style config header from a template + defines + probe results.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
outThe rendered config header.Labelrequired
definesStatic substitutions. Values become both #define bodies (for #undef VAR lines) and @VAR@ substitutions.Dictionary: String -> Stringoptional{}
probesProbe targets (cc_check_header / cc_check_function / etc.). Each contributes <DEFINE_NAME>=1 to defines iff the probe result is ‘1’ (autoconf’s HAVE_* convention).List of labelsoptional[]
templateThe template header (typically config.h.in). Lines matching #undef VAR are substituted with #define VAR <value> when VAR is in defines. @VAR@ substitutions are also applied.Labelrequired

ProbeResultInfo

load("@rules_autoconf//autoconf:defs.bzl", "ProbeResultInfo")

ProbeResultInfo(result_file, define_name)

A compile-test probe result.

FIELDS

NameDescription
result_fileFile: contains ‘1’ if the feature is present, ‘0’ otherwise.
define_namestring: the macro name this probe defines when present (e.g. “HAVE_STRLCPY”).

Conformance#

No gate findings. 8 contested atoms. See how gating works or the full report.

Contested atoms

Third-party modules where this module resolves a different version than others do. Not a violation of anything this module did — it is the actionable form of a registry-level convergence finding, and the sentence a maintainer can act on.

AtomResolved hereElsewhere
apple_support 1.24.2 2.2.0 ×1
bazel_skylib 1.8.2 1.9.0 ×2
nlohmann_json 3.6.1 3.12.0.bcr.1 ×1
protobuf 33.4 34.0.bcr.1 ×2
rules_jvm_external 6.7 6.8 ×4
rules_python 1.7.0 2.0.1 ×1
rules_swift 3.1.2 3.6.1 ×1
upb 0.0.0-20220923-a547704 0.0.0-20230516-61a97ef ×1

Dependencies#

rules_autoconf in the registry graph — what it depends on (left) and what depends on it (right).

Depends on

platforms0.0.10bazel_skylib1.7.1rules_cc0.0.17rules_python0.40.0stardoc0.7.2devrules_shell0.4.1dev

Versions#

1 published version, newest first. Each resolves to an immutable, integrity-checked archive.

VersionIntegrity (sha256)Source archive
0.1.0 latest duRlcN1c6qSLOGaz… tag archive ↗

Changelog#

All notable changes to rules_autoconf. The format is loosely Keep a Changelog — version headers mirror the published bazel-registry entries.

0.1.0 — initial release

  • Initial scaffold of Bazel-native autoconf replacement: probes run as Bazel actions, composing into the build graph and the action cache instead of an out-of-band configure shell pipeline.
  • Ships the core autoconf primitives: cc_check_header, cc_check_function, cc_check_symbol, and config_header (renders config.h from a defines dict + probe results).
  • No autoconf / m4 runtime dependency — probes use the host C compiler ($CC, default cc).

← All modules