Commit df5a6c3
committed
feat: stabilize
# Stabilization report
## Summary
The `include` key in Cargo configuration files allows loading additional
config files, enabling better organization, sharing, and management of
Cargo configurations across projects and environments.
This feature has been available under the `-Zconfig-include` flag since
2019 (Cargo 1.42) and has seen real-world usage.
The stabilization includes support for multiple syntax forms and the
`optional` field, which were added in October 2025 based on user
feedback.
Tracking issue: rust-lang#7723
### What is stabilized
The `include` configuration key allows loading additional config files.
**Supported syntax:**
- String: `include = "path.toml"`
- Array: `include = ["a.toml", "b.toml"]`
- Inline tables: `include = [{ path = "optional.toml", optional = true }]`
- Array of tables: `[[include]]` with `path` and `optional` fields
**Key behaviors:**
- Paths are relative to the including config file and must end with `.toml`
- Merge follows precedence order: included files (left-to-right) →
parent config
- `optional = true` silently skips missing files (default: `false`)
- Cyclic includes are detected and reported as errors
See the config documentation for complete details and examples.
### Future extensions
Several potential extensions are not implemented at this time:
* Glob patterns: like `include = "config.d/*.toml"`
* Conditional include: conditions like gitconfig's `includeIf`
* Variable substitution and template: placeholders like `{CONFIG_DIR}`
or `{CARGO_HOME}`
* Implicit-include: like `.cargo/config.user.toml` or
`.cargo/config.d` for config fragments
See "Doors closed" for more.
## Design
### Key evolution
All significant changes occurred during the unstable period (2019-2024)
and were approved by the Cargo team.
**1. File naming restrictions** (rust-lang#12298, 2023-06-21)
The team decided the restriction was reasonable. The restriction applies
to config file discovery but not to `--config` CLI arguments which has
already been stabilized.
**2. Loading precedence for arrays**
Config values in array elements are loaded left to right, with later
values taking precedence. The parent config file's values always take
precedence over included configs. This provides intuitive layering
behavior.
**3. Syntax complexity** (rust-lang#16174, 2025-10-30)
The feature started with simple string/array syntax. The team debated
and decided to add table syntax before stabilization to allow future
extensions.
**4. Optional includes by default vs. explicit** (rust-lang#16180, 2025-10-31)
Some users wanted missing files to be silently ignored by default for
local customization workflows. Others wanted errors to catch typos. The
team chose to error by default but added an explicit `optional = true`
field, requiring users to be intentional about optional behavior.
### Nightly extensions
No nightly-only extensions remain. The feature is fully stabilized as
implemented.
### Doors closed
**This stabilization commits to**:
1. Supporting the `include` key in Cargo configuration
2. Relative path resolution from the including config file
3. Left-to-right merge order for arrays
4. Parent config taking precedence over includes
5. The `.toml` file extension requirement
6. The `path` and `optional` fields in table syntax
**This does NOT prevent**:
- Adding glob/wildcard support
- Adding conditional includes
- Adding variable substitution and template
The `[[include]]` table syntax could optionally have a field to enable
the future extensions above. For example,
```toml
[[include]]
path = "path/config/*.toml" glob = true
[[include]]
path = "path/*/config.toml" if = "<some-condition>"
[[include]]
path = "path/*/config.toml" templatized = true
```
**This MAY prevent**:
* Adding new implicit-include for user local config or config
fragments directory
As we are going to allow all file paths. Adding any implicit includes
after stabilization might break the merge precendence if people already
include those paths.
## Feedback
### Call for testing
No formal "call for testing" was issued, but the feature has been
available under `-Zconfig-include` since Cargo 1.42 (2019) and has seen
real-world adoption.
### Use cases
Users reported use cases:
- **Sharing flags and environment conditionally**:
[Tock OS](https://github.com/tock/tock),
[esp-hal](https://github.com/esp-rs/esp-hal), rtos, and some FFI
libraries use it for preset management across multiple board
configurations for different hardware platforms, architectures,
and downstream crates.
- **Beyond hierarchical discovery**: Some use cases require
explicit includes because configs need to be loaded from
locations outside the hierarchical path, or need to be
conditionally included based on per-package or per-machine
requirements that can't rely on the directory structure alone.
This usually happens in a meta build system that generates
configs, especially when setting `CARGO_HOME` to a different
location off the hierarchical path.
- **Per-project profile overrides**: Projects with checked-in
configs (e.g., `[profile.test] debug = false` for CI) can allow
developers to override settings locally without modifying the
checked-in file. Developers can include
`.cargo/local-config.toml` without using git workarounds like
`update-index --assume-unchanged`.
### Coverage
Test coverage is comprehensive in `tests/testsuite/config_include.rs`:
- Merge behavior: left-to-right order, hierarchy interaction
- Path handling: relative paths, different directory structures
- Cycle detection: Direct and indirect cycles
- Error cases: missing files, invalid paths, wrong extensions,
missing required fields
- Syntax variations: string, array, inline table, array of tables
- Optional includes: missing optional files, mixed optional/required
- CLI integration: includes from `--config` arguments
- Forward compatibility: unknown table fields
### Known limitations
Issue rust-lang#15769 tracks inconsistent relative path behavior between
`include` paths (relative to config file) and other config paths like
`build.target-dir` (relative to cargo root). This is considered a known
limitation and confusion that can be addressed separately and doesn't
block stabilization.
No other known limitations blocking stabilization.
## History
- 2019-02-25: Original proposal (rust-lang#6699)
- 2019-12-19: initial implementation (rust-lang#7649)
- 2023-06-21: file extension restriction added (rust-lang#12298)
- 2025-10-30: table syntax support added (rust-lang#16174)
- 2025-10-31: optional field support added (rust-lang#16180)
## Acknowledgments
Contributors to this feature:
- `@ehuss` for initial implementation and design
- `@weihanglo` for extra syntax support and enhancement
- `@rust-lang/cargo` team for the support, review and feedback
- All users providing feedback in rust-lang#7723 (not going to tag each of them)-Zconfig-include
1 parent 14c6f00 commit df5a6c3
File tree
7 files changed
+139
-344
lines changed- src
- cargo
- core
- util/context
- doc/src/reference
- tests/testsuite
- cargo_config
- cargo/z_help
7 files changed
+139
-344
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
856 | 856 | | |
857 | 857 | | |
858 | 858 | | |
859 | | - | |
860 | 859 | | |
861 | 860 | | |
862 | 861 | | |
| |||
978 | 977 | | |
979 | 978 | | |
980 | 979 | | |
| 980 | + | |
| 981 | + | |
981 | 982 | | |
982 | 983 | | |
983 | 984 | | |
| |||
1362 | 1363 | | |
1363 | 1364 | | |
1364 | 1365 | | |
| 1366 | + | |
1365 | 1367 | | |
1366 | 1368 | | |
1367 | 1369 | | |
| |||
1376 | 1378 | | |
1377 | 1379 | | |
1378 | 1380 | | |
1379 | | - | |
1380 | 1381 | | |
1381 | 1382 | | |
1382 | 1383 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
186 | 186 | | |
187 | 187 | | |
188 | 188 | | |
189 | | - | |
| 189 | + | |
190 | 190 | | |
191 | | - | |
192 | | - | |
193 | 191 | | |
194 | 192 | | |
195 | 193 | | |
| |||
1138 | 1136 | | |
1139 | 1137 | | |
1140 | 1138 | | |
1141 | | - | |
1142 | | - | |
1143 | | - | |
1144 | 1139 | | |
1145 | | - | |
1146 | | - | |
1147 | | - | |
1148 | | - | |
1149 | | - | |
1150 | | - | |
1151 | | - | |
1152 | | - | |
1153 | | - | |
1154 | 1140 | | |
1155 | 1141 | | |
1156 | 1142 | | |
| |||
1277 | 1263 | | |
1278 | 1264 | | |
1279 | 1265 | | |
1280 | | - | |
1281 | | - | |
1282 | | - | |
| 1266 | + | |
1283 | 1267 | | |
1284 | 1268 | | |
1285 | 1269 | | |
| |||
1350 | 1334 | | |
1351 | 1335 | | |
1352 | 1336 | | |
1353 | | - | |
| 1337 | + | |
1354 | 1338 | | |
1355 | 1339 | | |
1356 | | - | |
1357 | | - | |
1358 | 1340 | | |
1359 | 1341 | | |
1360 | 1342 | | |
| |||
1406 | 1388 | | |
1407 | 1389 | | |
1408 | 1390 | | |
1409 | | - | |
1410 | | - | |
1411 | | - | |
1412 | | - | |
| 1391 | + | |
1413 | 1392 | | |
1414 | 1393 | | |
1415 | 1394 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
828 | 828 | | |
829 | 829 | | |
830 | 830 | | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
831 | 882 | | |
832 | 883 | | |
833 | 884 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
123 | 122 | | |
124 | 123 | | |
125 | 124 | | |
| |||
636 | 635 | | |
637 | 636 | | |
638 | 637 | | |
639 | | - | |
640 | | - | |
641 | | - | |
642 | | - | |
643 | | - | |
644 | | - | |
645 | | - | |
646 | | - | |
647 | | - | |
648 | | - | |
649 | | - | |
650 | | - | |
651 | | - | |
652 | | - | |
653 | | - | |
654 | | - | |
655 | | - | |
656 | | - | |
657 | | - | |
658 | | - | |
659 | | - | |
660 | 638 | | |
661 | 639 | | |
662 | 640 | | |
663 | | - | |
664 | | - | |
665 | | - | |
666 | | - | |
667 | | - | |
668 | | - | |
669 | | - | |
670 | | - | |
671 | | - | |
672 | | - | |
673 | | - | |
674 | | - | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
679 | | - | |
680 | | - | |
681 | | - | |
682 | | - | |
683 | | - | |
684 | | - | |
685 | | - | |
686 | | - | |
687 | | - | |
688 | | - | |
689 | | - | |
690 | | - | |
691 | | - | |
692 | | - | |
693 | | - | |
694 | | - | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
700 | | - | |
701 | | - | |
702 | | - | |
703 | | - | |
704 | | - | |
705 | | - | |
706 | | - | |
707 | | - | |
708 | | - | |
709 | | - | |
710 | 641 | | |
711 | 642 | | |
712 | 643 | | |
| |||
2327 | 2258 | | |
2328 | 2259 | | |
2329 | 2260 | | |
| 2261 | + | |
| 2262 | + | |
| 2263 | + | |
| 2264 | + | |
| 2265 | + | |
| 2266 | + | |
0 commit comments