-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Remap target dir #11156
Comments
More use cases:
I appreciate that this proposal is looking to precedence for a design. Since |
Being a repeatable option can be useful. I don't know which is the best delimiter in this case. Using The config field makes sense. In that case I would use the same logic already implemented for the
|
I'm not sure what should be the correct interaction with
|
And how the env var and the config field interact? One could override the other, or they could be merged. |
I'd personally like to see Cargo adopt an approach similar to what Bazel does, i.e. keep its cache under XDG_CACHE_DIR/cargo-whatever/... and make
WDYT? |
How do we maintain a unique location within
|
I see two approaches:
I personally prefer the first option as it allows for the most flexibility at moderate complexity.
True, in that specific case it also depends on how the executable checking is done and if a symlink would count. I don't know enough about a workflow would look like with such a system in place to make any recommendations here.
Most tools should not notice the difference. They would need to explicitly call I've done tests by creating the symlink by hand and everything I tested (cargo build, run, rust-analyzer) at it worked OOTB. |
In my case, the symlink does not count
For myself, I am used to running |
This would still (mostly) do what you intend (if we go with option 1 for the directory mapping), it would just leave a dangling cache directory. |
No, I generally do it to recover space from all of my projects when I upgrade cargo. If someone knows about the move, this makes it even easier. The problem is how do we help adjust workflows. |
@lorenz proposal would help in my case. But what about users which do not have freedesktop XDG? Or CI pipelines? The behavior would be inconsistent between different operating systems. And it would be the default behavior, possibly breaking some build systems. With my proposal, you just need to set
and everything is put inside the xdg cache dir, with the full path of Cargo.toml appended to it (though i like the idea of having an hash of it). And you need to explicitly opt-in for this feature, so it won't break any existing system. |
I ran into the same issue with btrfs and wrote a wrapper as a quick hack: https://github.com/sunshowers/targo |
@sunshowers looks like Mind explaining your design and trade offs? I'm assuming its too early to get a feel for benefits and pitfalls. |
Still super early, but, yeah it's very similar to what @lorenz was proposing. The only real (minor) difference is that it uses For directories it uses a base58-encoded blake3 hash of the workspace directory. This is just for initial setup -- there's also a metadata JSON file stored in the directory with a Execution modelThe execution model is that you're supposed to alias cargo to Targo does a bit of interception of cargo's arguments. For now it just processes SymlinksTargo uses the same symlink strategy as proposed by @lorenz. Some interesting effects:
A bind mount would be more transparent but doesn't work on Windows or Mac, and requires root permissions. I'm not sure how Windows junctions manage this. |
Oh, and I'd love for someone else to be co-maintainer of the project and run with it! What I have is a very basic MVP that works for me, but there's a lot of work that can be done here. I don't expect to have more than a few hours a month to work on it. (Of course, being upstreamed in cargo also works!) |
Did a quick look and at least cargo sweep respects the |
Yeah, agreed, I should just be able to look at cargo metadata for the information. My concern is more about the design of what circumstances we should switch the target dir to being managed by targo. For example, a target dir within the workspace vs outside it, being able to manually override it, etc. |
There are several ways that can go
Additionally, there is the question of whether we should change the default or not. We could even have a transition where we check if We just need someone to enumerate and weigh the options and create a proposal from among them. |
Great! I'm giving it a try. It seems promising! |
Sorry if that's not the best place for it, I just found the issue and tried to write something in the form of a proposal for it: Cargo: remapping the target directoryMotivation
Proposed solutionIntroduce The syntax is inspired by SyntaxThe syntax would be: For [build] # Or another section, since it also affects `cargo run`
target-dir-remap = [
"/home/poliorcetics=/caches/cargo_target_dirs/mine",
"/home/poliorcetics/work=/caches/cargo_target_dirs/work"
] For the CLI: cargo build \
--target-dir-remap "/home/poliorcetics=/caches/cargo_target_dirs/mine" \
--target-dir-remap "/home/poliorcetics/work=/caches/cargo_target_dirs/work" For environment variables:
Note the BehaviourThe most specific (longest matching prefix) path is the one applied, so with the following config: target-dir-remap = [
"/home/poliorcetics=/caches/cargo_target_dirs/mine",
"/home/poliorcetics/work=/caches/cargo_target_dirs/work"
]
Just like Naming scheme inside the remapped directoryObjectives:
Proposed solution:
where the "main manifest" is the one for the whole workspace and the "dir name" is the name of the In the case where the "parent directory" is the root, "dir name" should be left empty and the following dash ( Example: $ cd /home/poliorcetics/work/work-crate-1
$ cargo build --target-dir-remap "/home/poliorcetics/work=/caches/cargo_target_dirs/work"
# ...
$ echo -n "/home/poliorcetics/work/work-crate-1/Cargo.toml" | b3sum # https://crates.io/crates/blake3 for the b3sum utility
e738a37f44b76767aa51b9d5c12ad9077b9c4ad44cc13833ade787867e6f5c3e -
$ ls -1 /caches/cargo_target_dirs/work/
# ...
work-crate-1-e738a37f44b76767aa51b9d5c12ad9077b9c4ad44cc13833ade787867e6f5c3e
# ...
$ cargo run --target-dir-remap "/home/poliorcetics/work=/caches/cargo_target_dirs/work"
# ...
Running `/caches/cargo_target_dirs/work/work-crate-1-e738a37f44b76767aa51b9d5c12ad9077b9c4ad44cc13833ade787867e6f5c3e/debug/work-crate-1` Of course, most user (probably) won't pass Interactions with existing cargo features
Interactions with external toolsLots of build tools would probably be very happy with the option to entirely remap target directories to somewhere else, Alternatives consideredDoing nothingIt is already possible today to use
For those reason, this option has not been retained. Using
|
How does rustc command line argument --remap-path-prefix deal with this?
cargo is documented as reading but not writing CARGO_TARGET_DIR. I wonder if we should guarantee that CARGO_TARGET_DIR is set if not set by the user. Granted, I mostly want this to workaround CARGO_TARGET_TMPDIR not being available for test libs. Unsure what other use cases there might be that don't need the OUTDIR or TMPDIR.
This is mixing proposals and, while I can understand it being here, also feels weird. What is being mixed
Why its helpful: it allows using this proposal to act as a way to get a central cache dir Why it feels weird: the user explicitly gave a remap directive and we aren't following it. |
Ah you're right, what I personally want is a form of cache that does not gathers all the crates and workspaces together like
I would very much like that too, and I can't think of a case where that wouldn't be useful: either it set by the user and nothing is done or it is set by cargo itself, meaning runners can rely on it for example. |
It selects the last match, which really should be documented, I'll make a PR |
True, but other OSs have equivalent mechanisms, sometimes very well integrated with the OS. For example macOS has |
Since that variable/config option would not be set by default, how could we make it point to the OS's default ? With the idea I'm going for, users have to set it themselves, machine by machine, I don't see a need to depend on OS defaults here |
Fair, this primarily benefits users when it is already the default. I guess there is no way to actually change the default in cargo to make it use OS defaults without manual configuration. |
Thanks @poliorcetics for your contribution! I especially like the Motivations and Alternatives part. I only feels uncomfortable about the hash part. Like @epage pointed out, there's no need to hash anything, with this option we are just asking to remap, so it feels weird to not be just remapped. I would also keep the rustc command line argument --remap-path-prefix convention, instead of being too smart and use the most specific path. Precedence to the rightmost item is a convention used by many About the OSs |
If we want to keep this focused and bike-shed free, we could error on any As I mentioned, the hashing and central directory would be part of an alternative proposal for just moving the caches in an opinionated way, like targo. The proposal should have a comparison for this and why one vs the other. One potential extension of this one is that an empty source path could mean "cache the path" and the empty destination path could mean "central directory", allowing this proposal to be extended into the other proposal over time. |
Finally found the time and motivation to write a proper RFC, here it is: rust-lang/rfcs#3371 |
See also #5544 |
I've implemented a quick hack for this case: export RUST_BUILD_BASE="$HOME/.cache/rust-builds"
WORKSPACE_ROOT=$(cargo metadata --no-deps --offline 2>/dev/null | jq -r ".workspace_root")
PACKAGE_BASENAME=$(basename $WORKSPACE_ROOT)
TARGET_DIRECTORY=$(cargo metadata --no-deps --offline 2>/dev/null | jq -r ".target_directory")
# Check if target has default location
if [ $TARGET_DIRECTORY == "$WORKSPACE_ROOT/target" ]; then
# Run cargo with target set to $RUST_BUILD_BASE/$PACKAGE_BASENAME
CARGO_TARGET_DIR="$RUST_BUILD_BASE/$PACKAGE_BASENAME" cargo $@
else
# Do nothing, target dir is configured to smth non-default
cargo $@
fi |
Problem
I'm using ZFS filesystem, which has an instant snapshot feature very useful for disaster recovery. I use this feature to automatically make snapshots of my projects. The snapshot is applied to the whole ZFS dataset and there is no way to exclude certain directories.
The problem with Rust projects is that they may have many files in the
target
directory (which is usually inside the project directory). File under target directory change often (e.g. when re-building) and can be effortlessly recreated. So they don't fit well with ZFS automatic snapshotting system.Similar problem exists if someone wants to always use a different disk or partition for target directories (which are frequently changed, effortlessly recoverable, unlike the source code).
I could override
CARGO_TARGET_DIR
environment variable, but I would need to remember to do it for every every project.I could create an alias of
cargo
which automatically overridesCARGO_TARGET_DIR
, but it would also override whatever is set as target directory in the config.toml, which can cause unpredictable issues.Proposed Solution
I propose to add the environmental variable
CARGO_TARGET_DIR_REMAP
which let the user remap where target dir should be created.Example: crate is in
/home/user/projects/foo
and default target directory is in/home/user/projects/foo/target
. SettingCARGO_TARGET_DIR_REMAP=/home/user/projects=/tmp/cargo-build
should change the real target directory so it becomes/tmp/cargo-build/foo/target
The syntax is inspired by rustc command line argument
--remap-path-prefix
Notes
I've already experimented with a possible implementation. This is a simple working patch.
The text was updated successfully, but these errors were encountered: