From 41480abad8f117fba2f87d0e442cc489e4dff697 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 8 Aug 2016 18:34:43 -1000 Subject: [PATCH 1/8] RFC: Support versioned dependencies on build tools, such as cargo --- text/0000-tool-dependencies.md | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 text/0000-tool-dependencies.md diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md new file mode 100644 index 00000000000..0bacdc97b98 --- /dev/null +++ b/text/0000-tool-dependencies.md @@ -0,0 +1,113 @@ +- Feature Name: tool-dependencies +- Start Date: 2016-08-08 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +Allow crates to declare versioned dependencies on tools they use, such as cargo +and rustc. Declare these as dependencies on special crate names such as +`tool:cargo`, which can appear anywhere a dependency can currently appear. + +# Motivation +[motivation]: #motivation + +Build tools, such as cargo, develop new features over time. For instance, +Cargo 0.10 introduced new environment variables `$CARGO_PKG_NAME`, +`$CARGO_PKG_HOMEPAGE`, and `$CARGO_PKG_DESCRIPTION`. A crate that expects +valid values for these environment variables will fail to build on an older +version of Cargo. However, such a crate cannot currently declare a dependency +on the version of Cargo it expects. + +To avoid conflicts with any existing crate, this RFC introduces a namespace for +"tool" crate names, `tool:`, and defines one such build tool, `tool:cargo`. + +# Detailed design +[design]: #detailed-design + +In Cargo.toml files, anywhere the name of another crate can appear, +allow a name prefixed by `tool:`, such as `"tool:cargo"`. For example: + +```toml +[dependencies] +"tool:cargo" = "^1.5" + +[dev-dependencies] +"tool:cargo" = "^1.8" + +[target.'cfg(unix)'.dependencies] +"tool:cargo" = "^1.42" +``` + +Cargo should recognize specific tool names internally, and behave as though the +corresponding `tool:` crate existed with an associated version. In particular, +Cargo should recognize `tool:cargo`, and behave as though that crate existed +with a version number corresponding to the version of Cargo itself. + +A `tool:` name does not refer to a crate; Cargo must recognize tool names +intrinsically. If Cargo sees a tool dependency that it does not recognize, it +should treat that dependency as unsatisfiable, as it would a crate dependency +for a non-existent crate. (This may not lead to a failed build, such as if a +crate declares the dependency as optional, or if a crate declares it in a +`[dev-dependencies]` section and the current build does not require satisfying +dev-dependencies.) + +Typically, Cargo will provide only one version of a build tool, and fail if it +encounters a tool dependency on that build tool that does not allow that +version. However, a future definition of a new build tool could specify +different behavior, such as building a new version of a build tool before +building a crate; such a definition would need to consider the case of multiple +crates specifying incompatible version dependencies on build tools. This RFC +specifies only one build tool, `tool:cargo`, and Cargo should only provide one +version of that build tool, corresponding to its own version number + +Future definitions of build tools may support defining feature names for build +tools, analogous to features for crates. + +Note that versions of Cargo without support for this RFC will still parse such +a Cargo.toml file, and process it correctly, only failing if the dependencies +actually require such a crate. In particular, if a crate declares an optional +build tool dependency in its Cargo.toml, builds that do not require satisfying +that dependency will still complete successfully with older versions of Cargo. + +# Drawbacks +[drawbacks]: #drawbacks + +Tools that parse Cargo.toml files without using cargo itself could potentially +expect to resolve build tools such as `tool:cargo` as crates, and fail. (Tools +that use the cargo API should continue to work.) + +# Alternatives +[alternatives]: #alternatives + +Rather than introducing a new crate namespace, Cargo and crates.io could +instead reserve special crate names, such as `cargo-bin` or `tool-cargo`. +However, this would potentially conflict with an existing crate name, including +a local crate. In addition, this would complicate backward compatibility; +Cargo could not recognize any unknown build tool dependency. + +Rather than using a prefix of `tool:`, Cargo could use a syntax that works as a +TOML "bare key", such as `-tool-cargo` or just `-cargo`. This would avoid the +need to quote key names. Using a syntax that crates.io prohibits in crate +names would prevent conflicts between crates and build tools. However, cargo +does not actually prohibit such names in crates; only crates.io does. So these +names could still potentially conflict with a local crate. + +Cargo could introduce a separate key type or section for dependencies on a +build tool, such as `[tool-dependencies]`. However, this would require +analogous extensions to every type of dependency Cargo supports, such as +dev-dependencies, dependencies for a specific crate feature flag, dependencies +for a specific platform, and so on. In addition, existing versions of Cargo +would ignore the new section, rather than treating it as an unknown dependency +that it doesn't know how to satisfy. Adding the `tool:` namespace allows a +build tool dependency to appear anywhere a crate dependency can currently +appear, and improves backward compatibility with existing versions of Cargo. + +# Unresolved questions +[unresolved]: #unresolved-questions + +This RFC intentionally avoids introducing `tool:rustc`, and associated +versioning and feature names for rustc. Any such versioning scheme or feature +names would likely need to take nightly versions into account, to allow crates +that require nightly rustc feature-gates to express corresponding dependencies. From 00c0e12da1b072323520773afcf289d334a9aeca Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 9 Aug 2016 11:57:13 -1000 Subject: [PATCH 2/8] Document the possibility of choosing an older version of a crate --- text/0000-tool-dependencies.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index 0bacdc97b98..39b1bbe939e 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -53,14 +53,17 @@ crate declares the dependency as optional, or if a crate declares it in a `[dev-dependencies]` section and the current build does not require satisfying dev-dependencies.) -Typically, Cargo will provide only one version of a build tool, and fail if it -encounters a tool dependency on that build tool that does not allow that -version. However, a future definition of a new build tool could specify -different behavior, such as building a new version of a build tool before -building a crate; such a definition would need to consider the case of multiple -crates specifying incompatible version dependencies on build tools. This RFC -specifies only one build tool, `tool:cargo`, and Cargo should only provide one -version of that build tool, corresponding to its own version number +Typically, Cargo will provide only one version of a build tool. However, a +future definition of a new build tool could specify different behavior, such as +building a new version of a build tool before building a crate; such a +definition would need to consider the case of multiple crates specifying +incompatible version dependencies on build tools. This RFC specifies only one +build tool, `tool:cargo`, and Cargo should only provide one version of that +build tool, corresponding to its own version number + +Cargo could also choose to look for an older version of a crate whose build +tool dependencies it can meet, rather than failing a build if the latest +version of that crate requires a newer version of a build tool. Future definitions of build tools may support defining feature names for build tools, analogous to features for crates. From 796a3f86e345a553d0e849f24c96c7a868874a6c Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 9 Aug 2016 11:58:13 -1000 Subject: [PATCH 3/8] Document the benefit of declarative dependencies for package management systems --- text/0000-tool-dependencies.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index 39b1bbe939e..cc5f34b1bd7 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -74,6 +74,11 @@ actually require such a crate. In particular, if a crate declares an optional build tool dependency in its Cargo.toml, builds that do not require satisfying that dependency will still complete successfully with older versions of Cargo. +In addition to Cargo's own handling of build tool dependencies, other tools +working with crates, such as package management systems, can translate these +declarative dependencies into build time dependencies on the corresponding +packages of build tools. + # Drawbacks [drawbacks]: #drawbacks From 6485a4214e9a9496028c0bf4c0d5e7a2c67f0ed3 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 9 Aug 2016 11:58:42 -1000 Subject: [PATCH 4/8] Add another alternative: build-time detection in build.rs Document the advantages of declarative dependencies over build-time detection. --- text/0000-tool-dependencies.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index cc5f34b1bd7..b5334938887 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -89,6 +89,14 @@ that use the cargo API should continue to work.) # Alternatives [alternatives]: #alternatives +Today, packages could detect the version of Cargo or other build tools in +`build.rs`, and fail the build if they don't have a new enough version. This +RFC provides a purely declarative dependency instead. Cargo can parse such a +declarative dependency in advance to determine if the build will succeed. +Other tools, such as package management systems, can translate such a +declarative dependency into a build dependency on their package of the +corresponding build tool. + Rather than introducing a new crate namespace, Cargo and crates.io could instead reserve special crate names, such as `cargo-bin` or `tool-cargo`. However, this would potentially conflict with an existing crate name, including From 9e2aed6bf4e82348bdc50aaef987d5d943cbfc4a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 1 Jan 2017 16:45:21 -0800 Subject: [PATCH 5/8] Clarify tool dependency versioning and Cargo behavior --- text/0000-tool-dependencies.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index b5334938887..af8922a16c2 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -53,17 +53,14 @@ crate declares the dependency as optional, or if a crate declares it in a `[dev-dependencies]` section and the current build does not require satisfying dev-dependencies.) -Typically, Cargo will provide only one version of a build tool. However, a -future definition of a new build tool could specify different behavior, such as -building a new version of a build tool before building a crate; such a -definition would need to consider the case of multiple crates specifying -incompatible version dependencies on build tools. This RFC specifies only one -build tool, `tool:cargo`, and Cargo should only provide one version of that -build tool, corresponding to its own version number - -Cargo could also choose to look for an older version of a crate whose build -tool dependencies it can meet, rather than failing a build if the latest -version of that crate requires a newer version of a build tool. +Typically, Cargo will provide only one version of a build tool at a time. A +future definition of a new build tool could specify different behavior. Other +tools may provide mechanisms to take advantage of having multiple versions +available. + +Cargo could also choose to look for an older version of a crate with compatible +tool dependencies, rather than failing a build if the latest version of that +crate requires a newer version of a build tool. Future definitions of build tools may support defining feature names for build tools, analogous to features for crates. From fc76ce925414765022263596829e729fd0e9a179 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 1 Jan 2017 16:46:10 -0800 Subject: [PATCH 6/8] Elaborate on non-Cargo tools that parse Cargo.toml files --- text/0000-tool-dependencies.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index af8922a16c2..4c727f89797 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -80,8 +80,9 @@ packages of build tools. [drawbacks]: #drawbacks Tools that parse Cargo.toml files without using cargo itself could potentially -expect to resolve build tools such as `tool:cargo` as crates, and fail. (Tools -that use the cargo API should continue to work.) +expect to resolve build tools such as `tool:cargo` as crates, and fail. Such +tools would require updates. (Tools that use the cargo API should continue to +work.) # Alternatives [alternatives]: #alternatives From 0d168cd98dbb4646e922eae2ec2f39d6d61f64ad Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 1 Jan 2017 16:46:24 -0800 Subject: [PATCH 7/8] Add tool:rustc to support versioning of rustc and the standard library --- text/0000-tool-dependencies.md | 48 +++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index 4c727f89797..2a7fd52a372 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -8,7 +8,8 @@ Allow crates to declare versioned dependencies on tools they use, such as cargo and rustc. Declare these as dependencies on special crate names such as -`tool:cargo`, which can appear anywhere a dependency can currently appear. +`tool:cargo` and `tool:rustc`, which can appear anywhere a dependency can +currently appear. # Motivation [motivation]: #motivation @@ -20,8 +21,22 @@ valid values for these environment variables will fail to build on an older version of Cargo. However, such a crate cannot currently declare a dependency on the version of Cargo it expects. +In addition, some crates want to remain compatible with older versions of Rust, +avoiding newer language and library features to preserve that compatibility. +Declaring minimum versions will make it easier to detect intended +compatibility, and preserve that compatibility, such as by detecting when a +crate's dependencies have a newer version requirement than the crate itself, or +by using the metadata to run test builds with the corresponding versions. + +This would also avoid conflating the semantic version of a crate with the +version of rust that it depends on. Some crates incorporate changes in minimum +Rust versions into their semver as either minor-version or major-version bumps; +tool dependencies would allow expressing such changes via explicitly declared +dependency versions instead. + To avoid conflicts with any existing crate, this RFC introduces a namespace for -"tool" crate names, `tool:`, and defines one such build tool, `tool:cargo`. +"tool" crate names, `tool:`, and defines two such build tools, `tool:cargo` and +`tool:rustc`. # Detailed design [design]: #detailed-design @@ -37,13 +52,24 @@ allow a name prefixed by `tool:`, such as `"tool:cargo"`. For example: "tool:cargo" = "^1.8" [target.'cfg(unix)'.dependencies] -"tool:cargo" = "^1.42" +"tool:rustc" = "^1.13" + +[features] +nightly = ["tool:rustc/unstable"] ``` Cargo should recognize specific tool names internally, and behave as though the corresponding `tool:` crate existed with an associated version. In particular, -Cargo should recognize `tool:cargo`, and behave as though that crate existed -with a version number corresponding to the version of Cargo itself. +Cargo should behave as though `tool:cargo` exists with a version number equal +to that of Cargo itself, and behave as though `tool:rustc` exists with a +version number equal to rustc. + +For `tool:rustc`, Cargo should additionally provide a feature `unstable`, if +building with a compiler that allows unstable features; this allows crates that +depend on nightly Rust to declare such a requirement, and allows environments +that require stable Rust (such as Linux distributions) to recognize and avoid +such dependencies. Future work may introduce additional feature names for +`tool:` crates, such as specific Rust feature-gate names. A `tool:` name does not refer to a crate; Cargo must recognize tool names intrinsically. If Cargo sees a tool dependency that it does not recognize, it @@ -62,8 +88,8 @@ Cargo could also choose to look for an older version of a crate with compatible tool dependencies, rather than failing a build if the latest version of that crate requires a newer version of a build tool. -Future definitions of build tools may support defining feature names for build -tools, analogous to features for crates. +Future definitions of build tools may support defining other feature names for +build tools. Note that versions of Cargo without support for this RFC will still parse such a Cargo.toml file, and process it correctly, only failing if the dependencies @@ -117,11 +143,3 @@ would ignore the new section, rather than treating it as an unknown dependency that it doesn't know how to satisfy. Adding the `tool:` namespace allows a build tool dependency to appear anywhere a crate dependency can currently appear, and improves backward compatibility with existing versions of Cargo. - -# Unresolved questions -[unresolved]: #unresolved-questions - -This RFC intentionally avoids introducing `tool:rustc`, and associated -versioning and feature names for rustc. Any such versioning scheme or feature -names would likely need to take nightly versions into account, to allow crates -that require nightly rustc feature-gates to express corresponding dependencies. From 912558005c55eede1a8f8c22274587c1e2406cef Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 1 Jan 2017 18:41:20 -0800 Subject: [PATCH 8/8] Note that Cargo should have an option to ignore and warn Based on feedback from Sean McArthur. --- text/0000-tool-dependencies.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/text/0000-tool-dependencies.md b/text/0000-tool-dependencies.md index 2a7fd52a372..ee7ddf973d0 100644 --- a/text/0000-tool-dependencies.md +++ b/text/0000-tool-dependencies.md @@ -88,6 +88,11 @@ Cargo could also choose to look for an older version of a crate with compatible tool dependencies, rather than failing a build if the latest version of that crate requires a newer version of a build tool. +By default, Cargo should enforce tool dependencies and versions. However, +Cargo should provide an option to warn but continue. This simplifies testing +with older versions, such as prior to loosening the dependency, or as part of +detecting whether a crate actually uses any features from the target version. + Future definitions of build tools may support defining other feature names for build tools.