[Qt-creator] JSON wizard: build systems and sub-projects

Tobias Hunger Tobias.Hunger at qt.io
Mon May 13 10:54:36 CEST 2019

Hi Christian,

reading my last mail again it was rather short and sounds harsher than intended.
Sorry for that. I did not intend to slight you or your work, it is just that I
get very lazy when composing mails on my phone.

On Mon, 2019-05-13 at 10:38 +1200, Christian Gagneraud wrote:
> On Mon, 13 May 2019 at 05:27, Tobias Hunger <tobias.hunger at gmail.com> wrote:
> > > 2. "Define Build System" page.
> > > Currently the boiler plate attempt to identify the "Project type" to
> > > generate, but doesn't rely/use the semantic of the
> > > "supportedProjectType" above.
> > > Instead they use the HasPlugin concept to map the build system tool
> > > (aka, "qmake", "qbs", "cmake"), which is actually equivalent to the
> > > project type (the wizard doesn't care about the tool, it cares about
> > > the project manager it targets: CMakeProjectManager.CMakeProject,
> > > Qbs.QbsProject, ...).
> > 
> > Sure. Disable qmake and qbs support in Creator and see what happens:-)
> !?!

I wanted to point out that the wizard has a hard-coded list of project types it
supports. Creator also has a list of build systems it supports, which is dynamic
and depends on the plugins that are loaded.

At the "Define Build System" page that dynamic part is the important one: The
wizard should not offer build systems that are not supported by the current
Creator instance, even though it would support these build systems in other
creator instances.

So IMHO the wizard does the right thing here by relying on the loaded plugins
and not on the supportedProjectTypes.

> What i'm trying to say here, is that for each project manager, the
> wizard plays with 3 information, let's take qmake:
> PluginId => QmakeProjectManager
> ProjectTypeId => QmakeProjectManager.QmakeProject (as defined by the plugin)
> BuildSystem => "qmake" (which could be "some random alias" since this
> is internal to the wizard, and is just used to multiplex the
> generator)

That is correct.

> Currently JSON wizards for subprojects are not working, only the
> built-in qmake one work (and AFAIU they need to go).
> So something has to be done to solve this issue.

I am aware of that and appreciate you looking into this problem.

This will need more than just the wizard part to work though. E.g. CMake has no
way to add new files into existing CMakeLists.txt files, so a wizard will not be
able to do much in that case.

> What i'm proposing here, is to forget about these 3 facets, and use
> only one way to talk about projects: The ProjectTypeId.

I got that.

But you will need to check whether a plugin is currently loaded and you will
need to have a user-visible name for that build system and you need the. Where
do you get that information from?

Do you offer a registry in one of the plugins to hold that information

Currently we are having the information in the wizard directly has the charm
that it becomes pretty easy to copy one of ours and modify it for a new build

> I do not care about the fact that 'QmakeProjectManager' plugin
> provides 'QmakeProject', and that it uses "qmake" as a build system.
> What i care, is that my JSON wizard can generate stuff for
> ProjectTypeIdX, ProjectTypeIdY and ProjectTypeIdZ, all the rest is
> implementation details.
> Injected into wizard:
>  - availableProjectTypes

That becomes tricky due to the limited logic that the wizards support: They only
do string replacement. Injecting anything more complex than a single variable is
not trivial.

Note that Eike has been working on making it easier to pass complex objects to
JS, so this might be easier now than it was just a month ago.

>  - parentProjectType (in case of sub-project)

That is straight forward to do:-)

> Selected by user:
>  - ProjectType (in case of top project, aka. %{BuildSystem})
> Defined by wizard:
>  - supportedProjectType
>  - enabled = !intersection(availableProjectTypes,
> supportedProjectType).isEmpty()
> This would make the writing of project wizards IMHO more consistent,
> but would require quite some changes, i agree with that.

Changing things is of course completely fine:-)

> And concerning the case "Sub project from main menu", Wouldn't it be
> better to ask for the parent project on the first page, not the last
> one?
> Actually, maybe the first page should only be about project parenting
> and build systems, since they are strongly coupled

I am not so sure: At the last page you get a summary of everything and thus have
much more complete information on what exactly will get added to the project. I
see some value in having that information when deciding where the whole thing
should go in the project.

But I also see value in doing this first:-)

> > <snip>
> > 
> > > 5. Ideas to achieve that
> > > I did some quick hack in the ProjectNode, there is a "buildKey()"
> > > there, that returns the build target key, so i added a
> > > "projectTypeKey()" that returns the project manager's project ID
> > > (CMakeProjectManager.CMakeProject, ...), and which is injected wizard
> > > environment.
> > 
> > That could help when starting the wizard via the context menu. That is
> > unfortunately not the only way to trigger this wizard.
> Yes, there are already variables that are only defined when started
> via the context menu. we could add more, couldn't we?


> > > With the above and proper macro nesting, it should be possible to
> > > define the following wizard options:
> > >  - IsSubProject, IsTopProject
> > >  - HasCMake, HasQmake, HasQbs
> > > 
> > >  - IsCMake, IsQmake, IsQbs
> > 
> > Please do not hardcore the list of possible build systems! There are more
> > plugins out there 5han those that are shipped with Creator.
> I'm talking about the "options" section of a wizard, this information
> is already hard coded into the wizard, the above list is just a
> convenience naming sheme, eg:
> options: [
>  {key: "HasCMake", "value": "%{JS:
> value('Plugins').indexof('CMakeProjectManager') >= 0}"},
>  {key: "IsSubProject", value: "%{Exists:ProjectExplorer.Profile.Ids}"}
>  {key: "IsTopProject", value: "%{JS: !value('IsSubProject')}"}
>  ...
> ]

Yes, it is trivial to do this kind of thing. But doing so inside creator hides
this from the wizard -- and thus reduces the "copy-and-paste-ability" of the

Yes, copy and paste is far from ideal, but it is the best we can do with the
wizards we have.

> the IsQmakeProject, etc... case is a bit trickier, as there are 2 sub-cases:
> - Triggered from main menu: User's choice if top project, parent's
> project type in case of sub-project
> - Triggered from context menu: injected by the project explorer (as
> described above)
> One last comments, sorry to sound negative, but currently all project
> templates are a massive pile of copy/paste, with complex and error
> prone macro/javascript expressions.

You are right there:-)

> That is clearly a sign that something is "far from ideal".
> I'm not moaning or anything, i'm really just trying to help this
> wizard thing going. I can't wait to be able to do with qbs/cmake what
> i can currently do only with qmake.

I fully agree that the current state is far from ideal -- and I caused much of
the mess:-)

Best Regards,

Tobias Hunger, Senior Software Engineer | The Qt Company
The Qt Company GmbH, Rudower Chaussee 13, D-12489 Berlin
Geschäftsführer: Mika Pälsi, Juha Varelius, Mika Harjuaho. Sitz der
Gesellschaft: Berlin, Registergericht: Amtsgericht Charlottenburg, HRB 144331 B

More information about the Qt-creator mailing list