-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Add support for EnvironmentVariables in Rust targets #10030
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #10030 +/- ##
==========================================
- Coverage 70.24% 61.89% -8.36%
==========================================
Files 219 200 -19
Lines 48453 42558 -5895
Branches 11488 9292 -2196
==========================================
- Hits 34037 26340 -7697
- Misses 11988 14124 +2136
+ Partials 2428 2094 -334 ☔ View full report in Codecov by Sentry. |
This is also necessary for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idiomatic usage of Rust requires the use of environment variables at a compile time. This can be seen in the common idiom:
include!(concat!(env!("OUT_DIR"), "/generated.rs"))
This topic has come up before, and it might be "idiomatic" usage of Rust but it's not "idiomatic compiler design". Previous discussion on the topic I'm pretty sure was targeting getting a rustc fix for this.
It's basically terrible to do this for including generated files, and it's outright horrible to do this for any other reason -- what are people doing, using env variables to select target features? To define constants used for switching out runtime logic?
What's the use case for this other than describing the current_build_dir()
and why do we need a generic solution to do frankly bad stuff? What's the solution to not requiring a "wrapped due to env" design for all sources involved in this target, rather than just the one source that cats out a generated file into the current file by absolute path underneath a pile of macros?
Given that structured_sources
is such a better more elegant solution to this problem, why merge a worse solution at all?
w.r.t mention of crate subprojects, I'd consider that to be best solved by handling this inside crate conversion to meson rules, not something that requires an extension to the Meson DSL (which crate subprojects wouldn't use... right?)
This is the documentation: https://doc.rust-lang.org/std/macro.env.html. @eli-schwartz, I think you are taking the example posted too literally. While including a generated file is a solved problem in Meson, the I don't think Meson should forbid someone from using a feature of their language effectively. |
Including a generated file in rust is a solved problem using meson? ... Thanks for the rust docs link, but it doesn't tell me anything I didn't know and acknowledge in my original comment. I was never in doubt that rust lets you do this, I simply challenge the notion that it's a good "compiler design" (i.e. rust was wrong to allow it) and that people should use it when it is allowed. The original PR asserted that it is useful, but didn't say why. Now you assert that it is useful too, but also don't say why. I, meanwhile, am asking why this thing that seems to be a terrible idea is in fact not only good, but so good that we should extend the meson DSL in a way that no other compiler supports and which slows down compilation by wrapping rust compile rules in a python script for something that is, of necessity, hardcoded into meson.build and always known at buildsystem generation time. So that source code files can process environment variables. Environment variables. Which meson loves so much the lead developer of meson would prefer to ban them entirely. I think it's not unreasonable of me to try to understand why this new feature is needed and what the practical use cases are. I'm perfectly okay with meson "forbidding someone from using a feature of their language effectively" when that feature is exclusively of use to move build system logic into source code files because cargo isn't a real build system. |
I mean it really is just an alternative to I thought this comment was interesting:
Maybe the problem could be solved by using |
What are you proposing? that I write a Rust parser in Meson and process every Rust file with a heuristic to determine when we could replace it with
That requires altering the source files, which isn't allowed in a wrap. Among other things though, bindgen recommends this as the way to handle generated sources: https://rust-lang.github.io/rust-bindgen/tutorial-4.html This may not be the way I'd design a compiler, but it is how Rust works, and refusing to make Rust work because it's not ideal isn't practical, we might as well just remove Rust support if we're going to refuse to implement common use cases because we don't find them pretty enough. |
No, I just want people writing meson.build for their own rust code to do it properly. :p Do we actually need it for wraps? I thought the idea was to inspect a crate and convert cargo's output to build.ninja rules somehow. That doesn't require having people literally add an |
No, but it likely requires the converted crate to add the keyword arguments because the rust files in the crate use Otherwise the wrap will have to patch the rust files, which we don't allow. |
Was not thinking of the wrap use case when I made my comment. Thanks for reminding me! |
Again, I thought the idea for crates was not to just add meson.build patches and add a bajillion things to the wrapdb, but to actually introspect cargo's output and use it to generate build.ninja rules similar to how cmake.subproject works from a high-level perspective, no meson.build involved. |
Those rust files may already be using
|
mesonbuild/build.py
Outdated
@@ -1050,6 +1055,8 @@ def process_kwargs(self, kwargs, environment): | |||
self.process_kwargs_base(kwargs) | |||
self.copy_kwargs(kwargs) | |||
kwargs.get('modules', []) | |||
if kwargs.get('env'): | |||
self.env = EnvironmentVariables(kwargs['env']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use type_checking._env_convertor()
@@ -1608,26 +1608,31 @@ def func_disabler(self, node, args, kwargs): | |||
|
|||
@FeatureNewKwargs('executable', '0.42.0', ['implib']) | |||
@FeatureNewKwargs('executable', '0.56.0', ['win_subsystem']) | |||
@FeatureNewKwargs('executable', '0.62.0', ['env']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0.63
for e in options.env: | ||
name, value = e.split('=') | ||
# This is internal, we can pick whatever separator we want! | ||
env.append(name, value.split(':')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not so sure, that's going to split C:\foo
on Windows. Also you should not assume user wants to append to current env, they could want to set() or prepend(). I think for that you should pickle an ExecutableSerialisation() that contains the original EnvironmentVariables() object, instead of adding --env
in the command line.
At this point I'd like to wait on this until the build.py typing stuff lands, as it will be much easier to ensure everything is correct here once that happens. |
internal wrapper This will be used by rustc when we're setting environment variables, but don't have support for --set-env
999c584
to
e7ce752
Compare
This has been updated to use the nightly --set-env option, though the fallback to use a wrapper is currently not implemented. That will need to be reimplemented |
@dcbaker Wondering if we should instead pretend Rust uses |
executable( | ||
'main' | ||
'main.rs', | ||
env : {'OUT_DIR' : meson.current_build_dir()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know, only Rust is crazy enough to use env at compile time, this should at least be renamed to rust_env
.
I don't quite understand what you are saying, but it doesn't sound great. add_project_arguments('--set-env=Hello=World', language: 'rust') |
Not sure we need to implement it. We could just make env usage requiring recent rustc version. Rust devs are used to always use latest version, that's not a problem. |
Yes, I think it's extremely reasonable to say that we support this but only with a recent enough rustc version that it can be done sanely. I've objected all along to adding a python wrapper which juggles os.environ -- the --set-env argument to rustc brings this more in line with -D from C/C++, which is fantastic news and makes this sane to implement. We should leave it at that. |
That's fair enough. In that case we don't need executable(
'main'
'main.rs',
rust_args : ['--env-set=OUT_DIR=@0@'.format(meson.current_build_dir()],
) EDIT: What I meant is we could also allow |
Unfortunately it's not yet stable, so we're basically telling people "you have to use an unstable feature in a nightly compiler, sorry. That's not great user experience. I was going to propose that the env wrapper be added with an explicit deprecation and remove in 1.6 or 1.7, with the argument that if it's stabilized soon, that there would be a least a few rustc versions with it stabilized and we're no longer telling people "hey this thing that you really need to do idiomatic rust (ie, crates) isn't available, sorry", but we're also being clear that this is a stop gap and we're not going to provide long term fallback support since it's slow and bad. It also doesn't change anything from a language point of view so the cost from our point of view is fairly small. I might be convinced to do away with it entirely, but that assumes that it's stabilized in the next rust release. We certainly could drop the |
e7ce752
to
68ba18a
Compare
There is currently no reason to track whether we have a beta compiler, and this is not user visible, so we're not differentiating stable and beta, just nightly vs !nightly
…able TODO: fallback to using a wrapper
At least for a while, we will need to support wrapping rustc in a script to set environment variables. This is far from ideal, since it's slow, clunky, and complicated.
68ba18a
to
145353a
Compare
This push is ugly, it needs some patches split, doc changes, etc. However, it does away with the |
Idiomatic usage of Rust requires the use of environment variables at a compile time. This can be seen in the common idiom:
Which is a very common thing to do. While I think the structured_sources proposal is more elegant and generally a better idea, both for the purpose of building cargo based projects with meson, and for the purpose of including incomplete snippets, we should support environment variables for Rust based targets.
This series adds that support by adding the
env
keyword to build_targets (usage in non-rust targets is considered an error), and generates two different rust rules, one for env wrapping and one for non wrapping.