Remove support for manifest, rename to path-base

This commit is contained in:
Daniel Paoliello 2024-06-26 16:29:36 -07:00
parent 247ff65973
commit 707870d6c7
1 changed files with 93 additions and 76 deletions

View File

@ -30,7 +30,7 @@ relative paths (which makes refactoring and moving sub-projects very difficult)
and don't work at all if the mono-repo requires publishing and consuming from an
intermediate directory (as this may very per host, or per target being built).
This RFC proposes a mechanism to specify `base` directories in `Config.toml` or
This RFC proposes a mechanism to specify path bases in `Config.toml` or
`Cargo.toml` files which can be used to prepend `path` dependencies. This allows
mono-repos to specify dependencies relative to their root directory, which
allows the consuming project to be moved freely (no relative paths to update)
@ -69,16 +69,16 @@ drive for performance reasons).
path (e.g., `../../../other_layer/foo` and `../foo`) and may be error prone if
there is some other sub-project in directory with the same name.
Instead, if we could specify these `base` directories in a `Config.toml` (which
may be generated by an external build system which in turn invokes Cargo):
Instead, if we could specify these common paths as path bases in a `Config.toml`
(which may be generated by an external build system which in turn invokes Cargo):
```toml
[base-paths]
[path-bases]
sources = "/home/user/dev/src"
intermediates = "/home/user/dev/intermediates/x86_64/Debug"
```
Then the `Cargo.toml` can use those `base` directories and avoid relative paths:
Then the `Cargo.toml` can use those path bases and avoid relative paths:
```toml
[dependencies]
@ -94,15 +94,15 @@ Which resolves the issues we previously had:
generated).
* The `intermediates` directory can be placed anywhere.
* Moving `foo` or `baz` only requires searching for the canonical form relative
to the `base` directory.
to the path base.
## Other uses
The ability to use `base` directories for `path` dependencies is convenient for
The ability to use path bases for `path` dependencies is convenient for
developers who are using a large number of `path` dependencies within the same
root directory. Instead of repeating the same path fragment many times in their
`Cargo.toml`, they can instead specify it once in a `Config.toml` as a `base`
directory, then use that `base` directory in each of their `path` dependencies.
`Cargo.toml`, they can instead specify it once in a `Config.toml` as a path
base, then use that path base in each of their `path` dependencies.
Cargo can also provide built-in base paths, for example `workspace` to point to
the root directory of the workspace. This allows workspace members to reference
@ -111,20 +111,20 @@ each other without first needing to `../` their way back to the workspace root.
# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation
If you often use path dependencies that live in a particular location,
If you often use multiple path dependencies that have a common parent directory,
or if you want to avoid putting long paths in your `Cargo.toml`, you can
define path _base directories_ in your Cargo [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html)
or [configuration](https://doc.rust-lang.org/cargo/reference/config.html).
Your path dependencies can then be specified relative to those
define path _base directories_ in your
[configuration](https://doc.rust-lang.org/cargo/reference/config.html).
Your path dependencies can then be specified relative to those base
directories.
For example, say you have a number of projects checked out in
For example, say you have a number of projects checked out in
`/home/user/dev/rust/libraries/`. Rather than use that path in your
`Cargo.toml` files, you can define it as a "base" path in
`~/.cargo/config.toml`:
```toml
[base-paths]
[path-bases]
dev = "/home/user/dev/rust/libraries/"
```
@ -145,14 +145,13 @@ the path must exist on any other host where you want to use the same
## Specifying Dependencies
### Base Paths
### Path Bases
A `path` dependency may optionally specify a base path by setting the `base` key
to the name of a base path from the `[base-paths]` table in either the
[manifest](https://doc.rust-lang.org/cargo/reference/manifest.html) or
[configuration](https://doc.rust-lang.org/cargo/reference/config.html#base-paths)
or one of the [built-in base paths](#built-in-base-paths). The value of that
base path is prepended to the `path` value to produce the actual location where
A `path` dependency may optionally specify a base by setting the `base` key to
the name of a path base from the `[path-bases]` table in either the
[configuration](https://doc.rust-lang.org/cargo/reference/config.html#path-bases)
or one of the [built-in path bases](#built-in-path-bases). The value of that
path base is prepended to the `path` value to produce the actual location where
Cargo will look for the dependency.
For example, if the Cargo.toml contains:
@ -162,67 +161,51 @@ For example, if the Cargo.toml contains:
foo = { path = "foo", base = "dev" }
```
Given a `[base-paths]` table in the configuration that contains:
Given a `[path-bases]` table in the configuration that contains:
```toml
[base-paths]
[path-bases]
dev = "/home/user/dev/rust/libraries/"
```
This will produce a `path` dependency `foo` located at
`/home/user/dev/rust/libraries/foo`.
Base paths can be either absolute or relative. Relative base paths are relative
to the parent directory of the configuration or manifest file that declared that
base path.
Path bases can be either absolute or relative. Relative path bases are relative
to the parent directory of the configuration file that declared that path base.
The name of a base path must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
The name of a path base must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
characters or `-` or `_`, must start with an [alphabetic](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic)
character, and must not be empty.
#### Built-in base paths
If the name of path base used in a dependency is neither in the configuration
nor one of the built-in path base, then Cargo will raise an error.
Cargo provides implicit base paths that can be used without the need to specify
them in a `[base-paths]` table.
#### Built-in path base
Cargo provides implicit path bases that can be used without the need to specify
them in a `[path-bases]` table.
* `workspace` - If a project is [a workspace or workspace member](https://doc.rust-lang.org/cargo/reference/workspaces.html)
then this base path is defined as the parent directory of the root Cargo.toml of
then this path base is defined as the parent directory of the root Cargo.toml of
the workspace.
#### Base paths resolution order
Cargo will search for base paths in the following order:
1. In the [configuration](https://doc.rust-lang.org/cargo/reference/config.html).
1. In the [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html)
that is using the base path.
1. In the workspace's [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html).
1. In the list of built-in base paths.
If the base path is not found in during this search then Cargo will generate an
error.
Once a base path is found Cargo will stop searching, thus it is possible to
shadow a base path by declaring it earlier in the search order. This allows the
user's configuration to override the base path in a package, or for Cargo to add
new built-in base paths without compatibility issues (as existing uses will
shadow the built-in name).
## The Manifest Format
* Dependency tables:
* [`[base-paths]`](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths) - Base paths for path dependencies.
If a built-in path base name is also declared in the configuration, then Cargo
will prefer the value in the configuration. The allows Cargo to add new built-in
path bases without compatibility issues (as existing uses will shadow the
built-in name).
## Configuration
`[base-paths]`
`[path-bases]`
* Type: string
* Default: see below
* Environment: `CARGO_BASE_PATHS_<name>`
* Environment: `CARGO_PATH_BASES_<name>`
The `[base-paths]` table defines a set of path prefixes that can be used to
prepend the locations of `path` dependencies. See the [specifying dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths)
The `[path-bases]` table defines a set of path prefixes that can be used to
prepend the locations of `path` dependencies. See the
[specifying dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#path-bases)
documentation for more information.
# Drawbacks
@ -232,7 +215,7 @@ documentation for more information.
`Cargo.toml` that may not be accessible when others try to build the
same project. Specifically, it may now be that the other host has a
`path` dependency available at the same relative path to `Cargo.toml`
as the author of the `Cargo.toml` entry, but does not have the `base`
as the author of the `Cargo.toml` entry, but does not have the path base
defined (or has it defined as some other value).
At the same time, this might make path dependencies _more_ re-usable
@ -325,6 +308,28 @@ in strategic locations, cluttering their directories. The proposed
mechanism is simple to understand and to use, and still covers a wide
variety of use-cases.
## Support for declaring path bases in the manifest
Currently path bases only support being declared in the configuration, and not
the manifest. While it would be possible to add support for declaring path bases
in the manifest in the future (which would require specifying if the declaration
in the manifest or configuration is prefered, and how workspace versus members
declarations work), it is hard to justify the additional complexity of adding of
adding this capability to the initial implementation of the feature.
An argument could be made that specifying path bases in the manifest is a
convenience feature, allowing a common path where multiple local dependencies
exist to be specified as a path base so that the individual path dependencies
would be shorter. However, it would be just as easy to add a configuration file
to some parent directory of the dependent and this would be more useful as it is
likely that those dependencies will also be used in other local packages thus
saving the path bases table being duplicated in multiple manifests.
It could also be argued that specifying path bases in the manifest would be a
way to set "default values" for path dependencies (e.g., to a submodule) that a
developer could override in their local configuration file. While this may be
useful, this scenario is already taken care of by the `patch` feature in Cargo.
# Prior art
[prior-art]: #prior-art
@ -376,24 +381,34 @@ could help.
# Unresolved questions
[unresolved-questions]: #unresolved-questions
- What should the Cargo configuration table and dependency key be called? This
RFC calls the configuration table `base-paths` to be explicit that it is
dealing with paths (as `base` would be ambiguous) but calls the key `base` to
keep it concise.
- Is there other reasonable behavior we could fall back to if a `base`
is specified for a dependency, but no base by that name exists in the
current Cargo configuration? This RFC suggests that this should be an
error, but perhaps there is a reasonable thing to try _first_ prior to
yielding an error.
# Future possibilities
[future-possibilities]: #future-possibilities
It seems reasonable to extend `base` to `git` dependencies, with
something like:
## Path bases relative to other path bases
We could allow defining a path base relative to another path base:
```toml
[base-paths]
[path-bases]
base1 = "/dev/me"
base2 = { base = "base1", path = "some_subdir" } # /dev/me/some_subdir
```
## Path dependency with just a base
We could allow defining a path dependency with *just* `base`, making
`cratename = { base = "thebase" }` equivalent to
`cratename = { base = "thebase", path = "cratename" }`. This would simplify many
common cases, where crates appear within the base in a directory named for the
crate.
## Git dependencies
It seems reasonable to extend path bases to `git` dependencies, with something
like:
```toml
[path-bases]
gh = "https://github.com/jonhoo"
```
@ -402,7 +417,9 @@ gh = "https://github.com/jonhoo"
foo = { git = "foo.git", base = "gh" }
```
However, this may get complicated if someone specifies `git`, `path`,
_and_ `base`.
However, this may get complicated if someone specifies `git`, `path`, _and_
`base`.
It may also be useful to be able to use `base` for `patch` and `path`.
## Support patches
It may also be useful to be able to use path bases in `patch` and `path` tables.