From my experience using Qt, the MOC wasn't a pain point for me. All the generations that I saw were very straightforward and I never had to mess with it.
That's just my experience though, so I'd love to hear where people have found shortcomings.
Also, I am happy to see this project and may try it out nonetheless. Always happy to see work around Qt.
The convenience of the MOC is its raison d'être. The minor pain point for me is practically being forced to use the Qt Creator IDE. I'm happy to see a possible best of both worlds solution like this.
Why do you feel forced to use Qt Creator? I used Visual Studio for years, and these days I just use Vim. While Qt Creator is a great IDE, it has never felt necessary to me.
I used to do this too but I started using the form designer and uic + uiloader and it was a nice boost to productivity for creating lame but necessary dialogs.
Most C++ build systems have support for moc generation - CMake even has CMAKE_AUTOMOC which can automatically do it for you with no further intervention with some caveats.
Qt Creator doesn't even get involved in the build once it has started qmake - a qmake .pro[ject] file is nothing like a Visual Studio project file. You are supposed to make edits other than adding or removing source files by hand. So you really don't need Qt Creator for moc.
Note that qmake is generally easiest for tiny programs such as bug reproducers. For anything nontrivial, it's better to use CMake. Most advanced functionality in qmake is undocumented and weird. Qt itself is moving to CMake with Qt 6.
I was trying to figure out how to do MOC from gnu make when I came across this, the only other option I saw was to run qmake and then run that generated makefile from my makefile. Of those two options verdigris seemed to be the better choice to me.
> A technology demonstration or demonstrator model, informally known as a tech demo, is a prototype, rough example or an otherwise incomplete version of a conceivable product or future system, put together as proof of concept with the primary purpose of showcasing the possible applications, feasibility, performance and method of an idea for a new technology.
Verdigris has been developed and maintained now for over 4 years. Not only does it work - it has unit tests, CI and issues are addressed by the maintainers.
While verdigris does demonstrate that something is technically possible, so does Apache httpd - does not make Apache httpd a tech demo.
It started out as a tech demo. Then people started using it and reported bugs and features request. So support for MSVC was added, and version 1.0 was released. It is relatively low maintenance given that Qt maintain binary compatibility anyway (Qt 6 will be another story).
> not sure what binary compatibility has to do with it ...
Because the meta object generated by the verdigris macro will continue to work with newer version of Qt.
But in Qt6, the binary format will change so some adaptations will be required.
And the only reason I discussed that is because earlier in this thread someone claimed "The project is part tech demo for fun, part shut up the people who complain about moc."
> Because the meta object generated by the verdigris macro will continue to work with newer version of Qt. But in Qt6, the binary format will change so some adaptations will be required.
If it Qt6 retains backwards source code compatibility then verdigris should still keep working I guess. If not then yes verdigris will need to change but in neither of these cases do I see binary compatibility as being relevant - if you compiled something for Qt5 and the binary compatibility breaks to Qt6 then this will affect you regardless of having used verdigris or not no?
I'm interested in hearing your thoughts on the MOC if you have time and don't mind sharing. I've been researching QT's software design approach, architecture, etc. ("core" code base in general), and stand to benefit from learning the pros and cons of software built this way.
My biggest gripe with MOC is that it makes it no longer C++ and if I just want to quickly throw together some sample code and build it with a makefile I can't. This still requires the use of a separate header file with is annoying but a lot less annoying than writing in a language which is not c++ and which does not work with a simple toolchain.
You don't need a separate header, you can just do #include "foo.moc" at the end.
I'd be interested in knowing in which way it is no longer c++, considering Q_OBjECT, signals, slots, ... are just plain cpp macros (see qobjectdefs.h).
> You don't need a separate header, you can just do #include "foo.moc" at the end.
I was talking about verdigris for which you have to do #include "wobjectimpl.h"
> I'd be interested in knowing in which way it is no longer c++, considering Q_OBjECT, signals, slots, ... are just plain cpp macros (see qobjectdefs.h).
If it was pure C++ then I would not need to run a MOC to generate working executables.
While they are also plain CPP macros they have semantics which is only understood by the MOC and is not captured by CPP or C++. This additional semantics is the reason why they are used in the first place because if it was not for the additional semantics again you would not need MOC.
All my types (and `#define`s) have some semantic meaning only I and non of my tools understand.
It is nice if a tool understands those and for an `emit` suggests only my signals for auto-completion, but if it lists them along all other members it is fine.
So I can see the argument from a puristic view, but in practice, once my built is setup to run it (cmake automoc or something), it simply works.
My issue with Qt is that the API design comes from days very long ago, where they did fantastic work on keeping compatibility, while not adopting to "modern C++" which always requires me to rethink the way I write code. Also integrating with non-Qt code isn't always easy due to reliance on QString (which has value Unicode features), QList (which meanwhile has many std-like APIs) etc. which easily travel through all layers. Thus when staying inside At it's really nice and quite consistent, but integrating is hard.
> All my types (and `#define`s) have some semantic meaning only I and non of my tools understand.
If it is not semantics essential to the correct operation of your program then this is a different matter. I really am not sure what the contention here or misunderstanding is.
When I write C++ I write it for a C pre-processor and C++ compiler to read in order to obtain a output program which does something specific and in line with the C++ standard.
This is not some high minded purism - this is just pragmatic reality.
If I write something in my source which I expect to result in specific output but the specific output cannot be obtained if I use a standard compliant C Preprosessor and C++ Compiler then either my expectation is wrong or I'm writing something which is not C++.
So if you don't rely on the behaviour that results from MOC being part of the toolchain then sure - you are writing C++ - if you do - it is not C++.
If the semantics (in a sense where it actually affects output) is part of a language, which it is, then changing the semantics of the language makes it a different language.
> So I can see the argument from a puristic view, but in practice, once my built is setup to run it (cmake automoc or something), it simply works.
> When I write C++ I write it for a C pre-processor and C++ compiler to read in order to obtain a output program which does something specific and in line with the C++ standard.
It generates output but the output is wrong in the sense that when I wrote Q_OBJECT I expected the output to be the result of (MOC -> CPP -> CXX) and not just (CPP -> CXX).
So put differently I expected Q_OBJECT (and what it expands to) to have semantic meaning which is not provided by a standard compliant C Preprosessor and C++ Compiler.
And if it was valid output - i.e. the output is the entirety of what I expected from the input - then I would not need to ever use MOC.
Moc just adds some more generated code next to you valid C++ code, generally in a new translation unit.
That generated code is just boiler plate which you could write by hand if you wanted. In a sense this is what verdigris does: it provides macros that makes makes it easier to "write it by hand" (the W_OBJECT_IMPL macro somehow expends to the code generated by moc)
> Moc just adds some more generated code next to you valid C++ code
Code without which the complete output of your toolchain from your source is incomplete and therefore invalid - again if this was not the case you would not need to run MOC at all.
> the output is wrong in the sense that when I wrote Q_OBJECT I expected the output to be the result of (MOC -> CPP -> CXX) and not just (CPP -> CXX).
That is not really how moc works though ? moc does not change anything to your original sources nor their translation units; it is not an additional preprocessing step, but a parallel one.
This .o is exactly the same that one that would be produced in a complete Qt program. Moc just generates additional source files with the implementation of some functions whose declaration is given by the Q_... macros. You could also write them by hand or generate them with fancy cmake scripts... it's just not a fun experience.
> moc just generates additional source files with the implementation of some functions whose declaration is given by the Q_... macros.
But those additional source files are essential to the operation of my program - if they werent - and it was just entirely optional - why would someone ever opt to run it?
> it is not an additional preprocessing step, but a parallel one.
If I write something and I use QT MOC specials like Q_OBJECT and I do no MOC processing occurs I will never obtain the output I consider as correct as a whole - sure if I don't care about the output as a whole and just look at parts of it then I could say those parts there and correct. But I did not write Q_OBJECT because I like the way it looks in my source file, I wrote it so that MOC could generate some specific code without which my program will not function correctly.
> This .o is exactly the same that one that would be produced in a complete Qt program.
Say I had a program (XPP) that for all valid c++ input generates the output that a c++ compiler would generate for:
// blank
Would it be a C++ compiler? And if not why not? I could also tell people that the .o file it generates is the same as would be produced by a c++ compiler except there is some additional parts which they can write by hand in the .o file.
When I write c++ I don't just care that some output is generated - if the output is just missing some parts it is still wrong - even if I could go add those parts by hand.
Similarly if I write Qt, I actually care very much that when I put Q_OBJECT that some things end up in the output - because if I did not I would not use MOC.
> I'd be interested in knowing in which way it is no longer c++, considering Q_OBjECT, signals, slots, ... are just plain cpp macros (see qobjectdefs.h).
It's been a while since I've used Qt but if I recall correctly MOC also parsed and read the user interface files to generate the headers which get included in the C++ source.
There's also a stand-alone designer you can use on individual ui files. In general, there's no need to have the whole project in Qt Creator just to edit a ui file.
You can also edit the ui files in a normal text editor. They're just XML files that specify the widget hierarchy to construct. If you have a few example files to work from, they're pretty straight-forward to understand and modify. Validating your changes using designer is definitely faster than recompiling your program, but it's an option.
I do not have much experience with Qt, but moc is one of those things that seems a bog deal in theory (it os not c++, what's the debugging experience, what happens if it breaks) but it is absolutely not an issue in practice (you forget it exists very quickly).
My thinking was why require an intermediate processing step of the moc, if the core c++ is capable enough. Other toolkits like gtk does not seem to require intermediate compilation step too. Also the QObject stuff added by qt is quite mysterious atleast on the first look.
Also using the moc is a bit similar to using complex preprocessor-macr-ridden c code, which to me is an antipattern.
> My thinking was why require an intermediate processing step of the moc, if the core c++ is capable enough.
Sadly it is not. C++ does not provide reflection - not without macros duplicating all your function names. GTK+ does not provide reflection. For instance with Qt you can just define a C++ object and directly access its properties & methods from Javascript, which is extremely useful if you want to add a scripting layer to an existing software.
You can also iterate over all the properties of an object to create UIs automatically.
> Also using the moc is a bit similar to using complex preprocessor-macr-ridden c code, which to me is an antipattern.
We sort of agree. gobject is a "kill it with fire" kind of mess, moc is not exactly the pinnacle of elegance either (but does more than glib gives you and somehow manages to be less weird than glib's macro jungle). The basic fact is that moc works around C++ not being able to provide this kind of functionality; so either you take some inconvenience (gtk, verdigris) or use an external tool (moc). moc doesn't usually give any trouble beyond being somewhat slow, so that seems like an acceptable deal for almost any situations you might consider using Qt in.
Gtk uses GLib which basically re-invent object oriented programming with "complex preprocessor-macr-ridden c code" boilerplate.
I find moc approach much superior to that as it just help the programmer concentrate on what to program without having to manually write all the error-prone boilerplate.
Qt makes UI programming in C++ easier, nothing wrong that.
It'd be nice to have a tool that performs a one-time migration tool from Qt-compatible sources that expect the use of moc to code that uses Verdigris, which can then be checked into source control and maintained in place of the original.
I have started such a tool in python (see the github issues) but never got around finishing it... got me 90% of the way for a few hundred kloc codebase though.
I think that MOC is the problem only for people that don't do much Qt development at all.
MOC integrates into Qt build system so well that it's mostly invisible.
A bigger problem is the deployment step, at least on Linux. How to deploy Qt apps with Qt libraries bundled with the app, so that it uses system's look and feel is something I still don't know how to do.
When I was doing Qt development, getting CMake to build Qt projects properly was absurdly difficult. CMake had added some half-baked first class functions for building Qt (it's insane that a build system has first class knowledge of certain libraries, but insanity is par for the CMake course), but you still had to invoke them yourself and the various docs, blog posts, stackoverflow answers, etc gave different advice about invoking them but rarely did the advice work (and if it did work, it never generalized to non-toy projects). My understanding is that CMake has improved its insane first-class Qt functions such that it's easier.
(There's also qmake, but at the time I was using Qt, it only worked if you didn't depend on anything that wasn't also a qmake project, which is just more C++ build system insanity).
That's just my experience though, so I'd love to hear where people have found shortcomings.
Also, I am happy to see this project and may try it out nonetheless. Always happy to see work around Qt.