Buildroot Config.in: select vs depends on and Toolchain Capability Constraints

Read the menu as a validity filter

A package disappearing from menuconfig is often a useful warning: the selected toolchain or platform cannot satisfy its requirements. Making the option visible by deleting a dependency can postpone that warning until compilation, linking or deployment. The right question is whether the configuration model accurately describes what the package needs, including the requirements of libraries it enables.

This guide targets Buildroot 2025.02. It separates Kconfig selection from the make dependency graph and uses a fictional package called telemetry-view. The snippets are review examples, not a tested package submission. Start with upstream build requirements, then compare the exact library recipes in your selected Buildroot tag. Requirements can change when either the application or a dependency is updated.

Two separate layers connect valid Kconfig selection to make dependency ordering and a test matrix.
Conceptual configuration review; no build results asserted

Use depends on for conditions the package cannot create

Architecture support, an MMU, threads, a supported C library and compiler capabilities are conditions of the environment. A package should not try to create those conditions through select. In Buildroot conventions, library dependencies commonly use select, while toolchain and platform requirements use depends on. The 2025.02 package configuration reference also specifies the matching explanatory comments.

For a package that truly needs C++ and threads, the relevant symbols are BR2_INSTALL_LIBSTDCPP and BR2_TOOLCHAIN_HAS_THREADS. Add further conditions only when the software requires them. A minimum kernel-header symbol describes the toolchain headers, not proof that the running kernel implements every feature the application will use. Keep that runtime compatibility question in the product validation plan.

Do not expect select to inherit every constraint

Suppose library B depends on condition A, and application C selects B. That does not automatically make C depend on A. This distinction is the source of many configurations that appear selectable but violate a library requirement. The author of C must propagate the relevant constraints, including transitive ones, rather than assume select performs general dependency solving.

As a review method, follow each selected library until its architecture and toolchain requirements are accounted for. Compare the direct consumer constraints with the union of requirements actually needed by its enabled features. Do not copy every condition mechanically: optional features may have narrower requirements. Explain why each propagated condition exists so future updates can remove obsolete restrictions instead of accumulating them forever.

Keep the comment predicate aligned

The following skeleton illustrates a package requiring C++ and threads. It intentionally omits a library selection, because the correct library depends on the application. Tabs and the upstream project help text should be supplied in the real recipe. The comment is visible when either toolchain capability is missing.

config BR2_PACKAGE_TELEMETRY_VIEW
	bool "telemetry-view"
	depends on BR2_INSTALL_LIBSTDCPP
	depends on BR2_TOOLCHAIN_HAS_THREADS

comment "telemetry-view needs a toolchain w/ C++, threads"
	depends on !BR2_INSTALL_LIBSTDCPP || !BR2_TOOLCHAIN_HAS_THREADS

If the package also has an architecture or parent-feature condition, repeat that non-toolchain condition on the comment, or place both under an appropriate shared if block. Otherwise users may see advice to change their toolchain on a platform where the package will never be supported. Conversely, a missing comment can make a valid product option look as though it has vanished without explanation.

Express ordering in the makefile too

A Kconfig select enables a package; it does not by itself establish the required build ordering. A real library dependency must also appear in the consumer’s DEPENDENCIES variable. Host tools used to generate source belong in the host dependency side of the build graph, rather than being confused with target libraries. The 2025.02 generic infrastructure shows where these relationships become build targets.

Test the distinction with a fresh output directory, not only an incremental rebuild. A previously installed header can conceal a missing make dependency. At the same time, a fully correct make dependency cannot rescue an invalid toolchain configuration. Review menu validity and build ordering independently, then verify they describe the same enabled feature set.

Build a small truth table before a large build

For the example, enumerate all four C++/threads combinations. Only the combination with both enabled should offer the package. The other three should show the toolchain comment if the platform and parent conditions allow the package. Then repeat a representative row with the unsupported architecture or disabled parent feature: neither the package nor misleading toolchain advice should appear.

Add rows for each selected library’s critical constraint and for optional subfeatures. This is more informative than testing only the shipping defconfig, which may happen to enable every capability. Inspect the normalized .config after configuration processing; a fragment requesting a symbol is not evidence that the resulting symbol stayed enabled. Save the expected and observed state, together with any Kconfig warning.

Interpret warnings without weakening the model

An unmet-dependency warning after select usually means a consumer omitted a required condition or a selection path is inappropriate. A recursive dependency warning requires inspecting the full cycle, not removing a random edge until the warning stops. A package that is visible but fails a feature probe may have an inaccurate recipe or an upstream requirement that changed.

Use the failure to identify whether the missing fact belongs to the toolchain, architecture, optional feature, chosen provider or make graph. Keep a minimal reproducing configuration with the fix. Avoid hard-coding a result from one compiler invocation as a universal capability claim; supported architecture, ABI and compiler combinations can differ even within a single version number.

Acceptance checklist and limits

Accept the configuration when the package is available exactly in its supported configurations, unavailable combinations give useful comments where appropriate, selected dependencies have their constraints propagated, and make dependencies provide correct ordering. At least one fresh build and relevant negative configurations should be part of the project’s proposed validation, although none were run for this article.

Keep the truth table with the package review so future dependency upgrades have an obvious place to update requirements. This establishes a maintainable selection model. It does not establish runtime behavior, security support or compatibility with every kernel image. Those claims need their own evidence after the configuration has produced the intended software.

Similar Posts