From 707870d6c7bb94ffcbcace0c7dc7561e3ff60e62 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Wed, 26 Jun 2024 16:29:36 -0700 Subject: [PATCH] Remove support for manifest, rename to path-base --- text/3529-cargo-path-bases.md | 169 +++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 76 deletions(-) diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md index 3e94dff2d..afafa78ac 100644 --- a/text/3529-cargo-path-bases.md +++ b/text/3529-cargo-path-bases.md @@ -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_` +* Environment: `CARGO_PATH_BASES_` -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.