Skip to content
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

mintro: Introspect --buildoptions without a build directory #4564

Merged
merged 5 commits into from
Jan 1, 2019

Conversation

mensinda
Copy link
Member

@mensinda mensinda commented Nov 29, 2018

This PR adds the possibility to run meson introspect --buildoptions /path/to/meson.build without a configured build directory.

Running --buildoptions without a build directory produces the same output as running it with a freshly configured build directory.

This works similar to the other #4191 but with more copy and pasted code. Unfortunately, I have not found a way to implement this in another way, without refactoring the language handling in the main interpreter.

@textshell You might be interested in this.

Update:

Added the --backend option to the introspector to make sure the introspected build options are exactly the same.

Also did some refactoring to reduce the amount of code duplication.

@jpakkane
Copy link
Member

jpakkane commented Dec 3, 2018

Since this is a big change, it will have to wait until 0.49.0 is out.

mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
@textshell
Copy link
Contributor

One thing this does not cover yet is subproject options. I think we should at least have plan for those though.
We can't really know in this case what subprojects are going to be used. So i think we can only offer all subproject options with the understanding, that the user of this code (i.e. the configuration Dialog in an IDE) processes the result in a way that is ok with that.

With the current output format (which matches the format for the configured case, which we should try to keep) we can't even have the subproject options separate so the users of this interface need to know what is a subproject option and what is not.

@mensinda
Copy link
Member Author

I don't think that we should support subproject options here. Implementing this feature would require a lot more effort and even more code duplication.

From what I know we would also have to (partially) implement dependency to make this work.

To your last point: It is already possible to group subproject options since they follow the naming convention subproject_name:variable_name.

@textshell
Copy link
Contributor

I don't think that we should support subproject options here. Implementing this feature would require a lot more effort and even more code duplication.

Well we need something that parses meson_options.txt from the subprojects and exposes that. From my point of view meson can not really offer more for unconfigured projects.

From what I know we would also have to (partially) implement dependency to make this work.

I agree that we should not even try to predict which subprojects will be used. That simply is not feasible.

To your last point: It is already possible to group subproject options since they follow the naming convention subproject_name:variable_name.

My point is that adding this later will break expectations of IDEs. Or we could have a separate command that just parses the subproject options files. But that seems a little odd to require two shell outs.

What i imagine a UI to look like is that it per default shows the options of the main project (incl. meson options) and has some picker somewhere to add one of the subprojects at a time. So if you can't configure the main project because a subproject has a (possibly only on your setup) mandatory option you can get a dialog / section for these options. The alternative would be to force the users to find out what option is needed and it's syntax completely manually and offer just an input box for additional options.

mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
subpr = os.path.join(subproject_dir_abs, dirname)
self.global_args_frozen = True
try:
subi = BuildoptionsInterperter(subpr, '', self.backend.name, cross_file=self.cross_file, subproject=dirname, subproject_dir=self.subproject_dir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just use optinterpreter.OptionInterpreter here. Doing that does include options of subprojects that have a obviously bad meson.build file, but i don't think it's worth having more complicated code here just to detect that case. And also i think error reporting and parameter checking is best left to the full interpreter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, this would not cover the case where a new language is added in a subproject. The options for this language would be missing in this case. So I think that keeping this extra logic is worth it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed. I didn't think of that. The language detection is useful.
And i think it's not a big problem that the IDE will not know if that language is used by the main project or a subproject.

So i agree we should keep this.

mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
mesonbuild/mintro.py Outdated Show resolved Hide resolved
if comp is None:
return False
self.add_base_options(comp)
return True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value is never used. Also we can move self.add_base_options into the branch for newly added compilers and delete the code for lang in self.coredata.compilers

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done with the last two commits.

mesonbuild/mintro.py Outdated Show resolved Hide resolved

options = BuildoptionsOptionHelper(cross_file)
self.cross_file = cross_file
self.environment = environment.Environment(source_root, None, options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should use a environment that is shared by all subprojects?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not do this, since Environment stores coredata and I want to avoid conflicts between (sub)projects.

Also, see my last comment.

return

self.coredata.user_options.update(subi.coredata.user_options)
self.coredata.compiler_options.update(subi.coredata.compiler_options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two lines are needed because each interpreter has it's own environment and thus coredata, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. And having a shared coredata and / or environment may break stuff when the subproject modifies entries from the root project.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could that be a problem when the real interpreter does share its environment and coredate as well. (via self.environment = build.environment and self.coredata = self.environment.get_coredata() in Interpreter.init

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't: Coredata is stored in Environment which is stored in Build:
https://github.com/mesonbuild/meson/blob/master/mesonbuild/interpreter.py#L1948-L1950

And for each subproject a copy of Build is created, which is later merged:
https://github.com/mesonbuild/meson/blob/master/mesonbuild/interpreter.py#L2381

I don't exactly know what happens during the merge process and how that affects the build options.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that copy does not actually deep copy environment. It only copies OrderedDict·s. All other attributes of Build are just reference copied.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, I didn't look at copy() itself. But isn't this a bug? I mean, what happens when the subproject fails and is not required?

It should be fin for the introspection, however (unless it breaks my test case).

Copy link
Contributor

@textshell textshell Dec 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think mostly by not containing much mutable data that would need rollback. But i can not say for sure that there are no dragons in there. I don't know that corner of meson well.

@textshell
Copy link
Contributor

As i don't think anyone else is currently reviewing this, can you squash this down to a state where all the initial refactorings have a dedicated commit and the new functionality is added in one (or more) commits on top of that?

@mensinda
Copy link
Member Author

I am not a git mage, but I will try. Also, are you done with the review, did I forget something? I would like to keep the rewriting of the git history to a minimum :)

@textshell
Copy link
Contributor

I am not a git mage, but I will try. Also, are you done with the review, did I forget something? I would like to keep the rewriting of the git history to a minimum :)

I hope that i'm done. But my plan is to look at this again tomorrow when i'm less tired. If you go with a single commit for the newly added functionality, adding in a few final fixes should not be hard though.

Of course someone with actual commit powers has to look at this too, but i think that would be better with a cleaned up commit structure.

without a configured build directory.

Running `--buildoptions` without a build directory produces the same output as running
it with a freshly configured build directory.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to update the snippet with an caveat about this outputting the options of all subprojects even when they will not be active after configuration. (And that IDEs should be careful about displaying subproject options without user request)

self.subproject_dir = subproject_dir
self.coredata = self.environment.get_coredata()
self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
self.backend = backends.get_backend_from_name(backend, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems from the backend only the name is used. We could just store the name. Not sure if that would be an improvement

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

self.sanity_check_ast()
self.parse_project()
self.run()
self.coredata.set_options(self.default_options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some restrictions what default options a subproject can set. I think they are restricted to setting defaults for their own user defined options. Interpreter.set_options automatically applies the subproject prefix to these options also.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also done. Although this had required a bit more refactoring.

@textshell
Copy link
Contributor

looks good now.
From my point of view it only needs cleaning up the commits now.

@mensinda
Copy link
Member Author

OK. Squashed everything down to two commits. Let's hope that this didn't break anything and the CI passes.

@textshell
Copy link
Contributor

Thanks for splitting this up into more focused commits.

@jpakkane i think this is ready now. Could you have a look if this is acceptable as new feature? I would very much like to use this in the qtcreator plugin and @mensinda likely as well in the kdevelop support for meson.

@@ -70,6 +70,15 @@ The possible values for `section` are:

To set the options, use the `meson configure` command.

It is also possible to get the default buildoptions without a build directory by providing the root `meson.build` instead of a build directory to `meson introspect --buildoptions`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should mention that this is only available since version 0.50. The line should also be rewrapped to 80 characters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done with the last commit

@jpakkane jpakkane merged commit 8c9fcb1 into mesonbuild:master Jan 1, 2019
@mensinda mensinda deleted the introBuildOpts branch January 1, 2019 17:28
@Ericson2314
Copy link
Member

Ericson2314 commented Jan 6, 2019

Hi just noticed this rebasing a PR of mine. I really like the feature, but am concerned about the amount of new code in mintro and the degree to which it duplicates existing code. Any idea how that might be improved?

@textshell
Copy link
Contributor

I don't see a way to make this a lot simpler. There might be some parts that can be shared with other AstParser users (i.e. maybe parts of the func_project) but this PR already did move the easy code parts out of interpreter into shared code.

If somebody has good ideas having this with less duplicated logic would of course be nice. But the "don't really execute" way of introspection does differ in some important parts from the normal execution flow.

@mensinda
Copy link
Member Author

mensinda commented Jan 6, 2019

I am also not really a fan of the amount of code duplication in this PR. However, (as @textshell already mentioned) refactoring the remaining parts to avoid code duplication is not easy. The only real way I see to resolve this is to create a new base interpreter that implements the shared parts of the "real" and the "introspection" interpreter. Of course, this would require massive amounts of refactoring.

@Ericson2314
Copy link
Member

Well at least it's all contained within BuildoptionsInterperter to revisit later. I finished rebasing my PRs (#4626, #4010) and I think caught all the relevant bits so my immediate need is satisfied.

Perhaps another way to do it would be to make a fake coredata and just use one interpereter. I dunno.

@mensinda
Copy link
Member Author

mensinda commented Jan 6, 2019

It might be possible to move detect_compilers completely into Environment. I will try to make a PR for this.

@Ericson2314
Copy link
Member

Oh awesome! That would completely solve it for my PRs, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants