-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Add .toml file extension restriction for -Zconfig-include
#12298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is to avoid possible name collisions. For example, a user creates a file called `.cargo/cache`, and then in the future cargo wants to create a directory called `.cargo/cache/`, that would collide with what the user specified. Restricting to `.toml` extensions would avoid that since we won’t make a directory named with a `.toml` extension.
Collaborator
|
r? @epage (rustbot has picked a reviewer for you, use r? to override) |
Contributor
|
@bors r+ |
Contributor
Contributor
bors
added a commit
that referenced
this pull request
Jun 21, 2023
Add `.toml` file extension restriction for `-Zconfig-include`
Contributor
|
💔 Test failed - checks-actions |
Member
Author
|
#11334 (comment) (due to coarse mtime on macOS)? @bors retry |
Contributor
Contributor
|
☀️ Test successful - checks-actions |
This was referenced Jun 22, 2023
compiler-errors
added a commit
to compiler-errors/rust
that referenced
this pull request
Jun 24, 2023
Update cargo 8 commits in 4cebd130ebca3bc219180a54f3e26cc1b14a91de..03bc66b55c290324bd46eb22e369c8fae1908f91 2023-06-21 18:59:29 +0000 to 2023-06-23 23:27:46 +0000 - fix(script): Be quiet on programmatic output (rust-lang/cargo#12305) - docs(unstable): Update script documentation (rust-lang/cargo#12308) - cargo script example needs nightly -Zscript feature (rust-lang/cargo#12287) - fix(script): Process config relative to script, not CWD (rust-lang/cargo#12303) - -Znext-lockfile-bump: Don't suggest using -Z on stable (rust-lang/cargo#12302) - build(deps): bump openssl from 0.10.54 to 0.10.55 (rust-lang/cargo#12300) - Add `.toml` file extension restriction for `-Zconfig-include` (rust-lang/cargo#12298) - docs(unstable): Point stable-unstable docs to nightly docs (rust-lang/cargo#12299) r? `@ghost`
weihanglo
added a commit
to weihanglo/cargo
that referenced
this pull request
Nov 21, 2025
# 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)
weihanglo
added a commit
to weihanglo/cargo
that referenced
this pull request
Nov 21, 2025
# 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)
weihanglo
added a commit
to weihanglo/cargo
that referenced
this pull request
Nov 21, 2025
# 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)
weihanglo
added a commit
to weihanglo/cargo
that referenced
this pull request
Nov 21, 2025
# 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` - Glob syntax and templated paths (with `{}` braces} are disallowed in paths. - 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"` — rust-lang#9306 * Conditional include: conditions like gitconfig's `includeIf` — rust-lang#7723 (comment) * Variable substitution and template: placeholders like `{CONFIG_DIR}` or `{CARGO_HOME}` — rust-lang#15769 * Implicit-include: like `.cargo/config.user.toml` or `.cargo/config.d` for config fragments — [#t-cargo > Built-in &rust-lang#96;.cargo/config.local.toml&rust-lang#96;for non-committed config](https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/Built-in.20.60.2Ecargo.2Fconfig.2Elocal.2Etoml.60for.20non-committed.20config/with/558705263) * Environment variable include support: like `CARGO_INCLUDE=path/to/config.toml` — rust-lang#6728 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) (rust-lang#16285, 2025-11-21) The syntax has a couple restrictions: * File path should end with `.toml` extension * File path should not contain glob syntax or template braces The team considered 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 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 precedence if people already include those paths. However, implicit-include for config fragments (e.g., `include = [".cargo/config.toml/"]`) can be supported in the future without breaking changes, if `config.toml/` is a directory. ## 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. A board's config (used by entering its directory) is defined by pulling from role-based config slices. - **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. - **User and project configuration**: 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 an optional `.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) - 2025-11-21: glob and template syntax restriction added (rust-lang#16285) ## 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
weihanglo
added a commit
to weihanglo/cargo
that referenced
this pull request
Nov 21, 2025
# 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` - Glob syntax and templated paths (with `{}` braces} are disallowed in paths. - 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"` — rust-lang#9306 * Conditional include: conditions like gitconfig's `includeIf` — rust-lang#7723 (comment) * Variable substitution and template: placeholders like `{CONFIG_DIR}` or `{CARGO_HOME}` — rust-lang#15769 * Implicit-include: like `.cargo/config.user.toml` or `.cargo/config.d` for config fragments — [#t-cargo > Built-in &rust-lang#96;.cargo/config.local.toml&rust-lang#96;for non-committed config](https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/Built-in.20.60.2Ecargo.2Fconfig.2Elocal.2Etoml.60for.20non-committed.20config/with/558705263) * Environment variable include support: like `CARGO_INCLUDE=path/to/config.toml` — rust-lang#6728 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) (rust-lang#16285, 2025-11-21) The syntax has a couple restrictions: * Path must end with `.toml` extension * Path must not contain glob syntax or template braces The team considered 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 `path` and `optional` fields in table syntax **This does NOT prevent**: - Adding glob/wildcard support - Adding conditional includes - Adding variable substitution and template **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 precedence if people already include those paths. The only possible way to support it is accepting `.cargo/config.toml/` as a directory and treat it as a config fragments directory. `.cargo/config.toml` (and the legacy `.cargo/config`) is the only path Cargo reserves. ## 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. A board's config (used by entering its directory) is defined by pulling from role-based config slices. - **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. - **User and project configuration**: 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 an optional `.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) - 2025-11-21: glob and template syntax restriction added (rust-lang#16285) ## 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
A-configuration
Area: cargo config files and env vars
A-documenting-cargo-itself
Area: Cargo's documentation
S-waiting-on-bors
Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Z-config-include
Nightly: `include` config key
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What does this PR try to resolve?
During yesterday's Cargo meeting, we decide to have a restriction to
.tomlextensions on the file name for-Zconfig-include. Thus it will be less likely to collide with what the user specified in.cargo/directory.This also included a
unstabledoc update and a tests to verify what has been written in the doc.How should we test and review this PR?
By commit. Most tests are touched because they need to comply with the
.tomlrestriction.Additional information
Part of #7723