rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.7k stars 2.41k forks source link

Cargo makes `target-dir` path relative to user's home directory #7843

Open klozovin opened 4 years ago

klozovin commented 4 years ago

I have a setting of target-dir = ".cargo" in ~/.cargo/config, to rename the default build directory. It has worked fine in the past, but now it seems that cargo takes the target-dir path to mean realtive to my home directory, instead of relative to the project's directory.

Right now my cargo (rustc 1.40.0 (73528e339 2019-12-16 on Linux) with that option set, tries to build every project in a single directory: ~/.cargo. That of course creates problems. Also, running cargo clean in any projects deletes the main ~/.cargo directory!

Using env variable $CARGO_TARGET_DIR to achieve what I want works just fine.

Using .cargo/config inside my project also works! But, as soon as I execute cargo clean cargo deletes .cargo directory in the project, so the setting is lost.

Maybe this issue is related #7551?

ehuss commented 4 years ago

Hm, this was a bit of an unexpected change from #7456.

@alexcrichton do you have any thoughts on how this should behave? It looks like target_dir has been special since #2703 where it was interpreted as relative to cwd.

I'm a little concerned about treating paths inconsistently (some config-relative, others cwd-relative). It's also questionable whether cwd relative makes sense, versus workspace-relative, versus config-relative.

I wonder if it might be worthwhile to have a way for the user to control how relative paths are treated (like #6210)?

For reference, the list of config vars with paths (which are treated as config-relative):

And program paths which have a special case to search PATH instead:

alexcrichton commented 4 years ago

Oh dear this is indeed a bit of a confusing situation now!

As of nowadays I think the current behavior is the best default, but I think it's a good idea to have more configurability here as well. It makes sense that you might want to configure globally a different name, and we could do something like target-dir = "{cwd}/my-name" in terms of configuration.

klozovin commented 4 years ago

I'd definitely be +1 on having a way to set a global project-relative directory for builds! Having it in ~/.cargo/config seems best. I'm currently setting it via $CARGO_TARGET_DIR but it's finicky - Visual Studio Code picks it up sometimes, depending on the shell it's launched from, etc.

Also, there's an additional issue of cargo clean deleting its configuration if specified from .cargo/config in the project directory. That's definitely a confusing one.

crncnnr commented 3 years ago

I'd like to quickly chime in that I got bitten by this today, especially cargo clean wiping out ~/.cargo, which took me a minute to figure out what I'd done.

I'd assumed setting build.target-dir = ".cargo" in ~/.cargo/config.toml would resolve to whatever workspace root cargo was currently operating in, mirroring Bazel's behaviour.

sellout commented 1 month ago

I too was expecting it to be relative to the workspace root, since the default is relative to the workspace root.

As @alexcrichton suggested in https://github.com/rust-lang/cargo/issues/7843#issuecomment-580128710, I think something like {cwd}/my-name would be good, but I want something like {workspace}/my-name.

Right now it seems impossible to explicitly set the value to its default, which seems like a design smell. I.e., there should be some way to write

[build]
target-dir = "{workspace}/target"

I’d be inclined to say that paths in a config file should generally be considered relative to that file. So, in ~/.cargo/config.toml, running cargo from ~/Projects/my-project/bar, with the workspace root at ~/Projects/my-project, would map like the following

Maybe there are others, maybe {cwd} isn’t necessary, I dunno. But relative-to-workspace seems very necessary.