-
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
Read project environment vars from config #8839
Conversation
Some custom build scripts (especially for -sys packages) expect to query environment variables to locate build resources (such as pre-built binaries) but these cause lots of trouble when considering the numerous different ways in which cargo may be invoked. For example each editor that invokes cargo as part of providing development diagnostics needs to offer some way to configure environment variables or users need to find their own way of controlling the environment variables of these different tools which is burdensome and can lead to an inconsistent duplication of state across tools. This introduces support for reading an (optional) environment.json found at the root of the current workspace that may contain a map of environment variable key, value pairs. These variables will be exported to all build scripts run under the workspace. The removes any need to configure tools and editors independently. The configuration is separate from any Config.toml since it's likely that the state shouldn't be under version control in many situations (generally locating resources for the project within a specific user's development environment). Fixes: rust-lang/issues/4121 Fixes: rust-lang/rls/issues/915 Fixes: rust-lang/vscode-rust/issues/791 Fixes: rust-lang/rust-analyzer/pull/6099 Fixes: intellij-rust/intellij-rust/issues/1569
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Eh2406 (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
A few other things I'd probably change with an update of this:
Can imagine a structure like this working: {
// defaults...
"FOO": "bar"
"FOO2": "baz"
// target overrides...
"aarch64-linux-android": {
"FOO": "cross_bar"
}
}
|
We talked about this in the Cargo meeting today. Summary of the consensus from that meeting:
[env]
FFMPEG_DIR = "/some/path"
One more thought from that meeting: This is, effectively, adding a channel for a crate to communicate down to its dependencies. Previously, the only such channel we've had was feature flags. In an ideal world, we'd have a more general structured channel for that. In particular, we've talked about cargo "capabilities", which would be a key-value way to specify parameters for dependencies; that would work for things like "use this backend", for which things depending on a crate directly or indirectly could set the value, with capability higher in the dependency tree (ultimately the final binary crate) overriding those set lower in the dependency tree. Such a mechanism would allow ffmpeg-sys to have a structured and namespaced way to pass in a path, rather than using global unstructured unnamespaced environment variables. So, long-term, we'd like to see a cargo key-value capability mechanism, which would allow |
Right, it looks like these It's an asside really but looking at the docs for these config files it makes me wonder whether there could potentially be a Was a bit surprised to realise that cargo will apparently keep searching up to the root of the filesystem for config.toml overrides! I guess that's safe most of the time - seems odd to be searching well outside the bounds of a project though. Anyway totally unrelated. Although I was initially focused on build script overrides for my use case, I forgot to mention that I'd been wondering if actually it could make sense for it to be more global, so the env state would be re-exported much earlier and then be visible across other commands like Assuming re-evaluation on a per-crate basis for now and thinking about being carefull to not trample environment variables set by the user (I agree that if the user had exported the environment variable themselves cargo shouldn't touch them) I suppose there will need to be a central record of which env vars have only been set by cargo so it always remains possible differentiate user-set and cargo-set environment variables. Guess that sounds fine - just a little bit more fiddly. Just thinking about the ability to have different overrides for different targets, such as when cross-compiling for Android in my case. I guess the way that might be able to work here is that About the downsteam communication - this doesn't necessarily need to open up that possibility - it seems like it really comes down to the question of whether this environment state should be re-evaluated on a per-crate basis or just once for the top-level project. Perhaps environment state should be kept more global (which could be more in keeping with how environment variables are generally not a precision tool for configuring things). It could be somewhat simpler to implement and conceptually reasonable that this state would be evaluated very early on within cargo only with respect to the top level of your project/workspace and with that constraint I think it avoids introducing general downstream communication (which can be left to "capabilities" or something similar later)? Certainly if there was a feature like capabilities in the future then it would be good if projects like ffmpeg-sys could migrate to using that instead of environment variables. Oh, haha, sorry, I clearly hadn't digested your last paragraph :)
Right, so this pretty much answers the question I had about what you were imagining - this state would only be evaluated once. Thanks for the follow up! |
@rib Are you up for updating the PR to get the environment variables from the Cargo config? I recently found a use case for this myself (setting |
Hey, it's been in the back of my mind to follow up at some point on this, but just been really focused on seasonal startup work recently. I'm happy either way if you go ahead and put something together or otherwise I guess some time in the new year I may get a chance to look at following up on this. |
@rib Not a problem, and no rush. Just wanted to see if you were still interested. |
From an IDE point of view, I'd say that "global" env-vars should be configured by the shell (and IDE should be started from the shell) while project-specific config should either be handled by https://direnv.net (IDEs integrate with that somewhat) or by build-in IDE config. I personally feel that "convenient way to set env vars" is a feature creep for Cargo, as that's clearly the shell's turf. OTOH, using shell on windows is a pain, so we might as well support this. |
Add support for [env] section in .cargo/config.toml This adds support for an `[env]` section in the config.toml files. Environment variables set in this section will be applied to the environment of any processes executed by cargo. This is implemented to follow the recommendations in #8839 (comment) Variables have optional `force` and `relative` flags. `force` means the variable can override an existing environment variable. `relative` means the variable represents a path relative to the location of the directory that contains the `.cargo/` directory that contains the `config.toml` file. A relative variable will have an absolute path prepended to it before setting it in the environment. ``` [env] FOOBAR = "Apple" PATH_TO_SOME_TOOL = { value = "bin/tool", relative = true } USERNAME = { value = "test_user", force = true } ``` Fixes #4121
Closing as implemented by #9175. |
I've recently been struggling with being able to use Visual Studio Code with rust-analyzer while I'm trying to use a dependency (ffmpeg-sys) that needs to be configured via an
FFMPEG_DIR
environment variable for it to build.Looking around I found a bunch of different, related issues where people have basically been struggling with this same issue:
Since I saw that #4121 had been open for over three years I figured there's little point waiting for progress with that and I instead looked at modifying ffmpeg-sys so I could remove its dependence on an environment variable for configuration. My original plan was to implement something very similar to this pull request except that I found cargo didn't expose enough information to build scripts for them to locate the workspace root which meant I could only find a config that would be adjacent to the Cargo.toml for ffmpeg-sys. This wasn't very practical since it meant I'd have to fork ffmpeg-sys in order to configure it.
This is the PR for reference: zmwangx/rust-ffmpeg-sys#7
Notably the maintainer was clearly very much against the idea too, of the oppinion that it should either be solved within the tooling integrations or lower in the stack in cargo.
This PR brings the same idea directly into Cargo, with the advantage that it knows where the workspace root is and it can also solve the same problem for all crates that depend on environment variables for configuration where users need to be able ensure a consistent environment between command line builds and IDE or editor-driven builds.
In summary this introduces support for reading an (optional) environment.json found at the root of the current workspace that may contain a map of environment variable key, value pairs. These variables will be exported to all build scripts run under the workspace. The removes any need to configure tools and editors independently.
The configuration is separate from any Config.toml since it's likely that the state shouldn't be under version control in many situations (generally locating resources for the project within a specific user's development environment).
A few open questions
In principle does this seem like a reasonable way of addressing issues like #4121?