Monday, 11 May 2020

A technique for connection checking in Qt


Recently, I stumbled upon a technique for checking if the connect() call for Qt signals/slots was successfull. You may ask what the problem is - just check the result of the call, how difficult can that be?
  bool ok = connect(...);
  Q_ASSERT(ok);
This doesn't look as it's much! However, in a standard Qt project you won't see that because it doesn't scale really well. What you'll normally see is this:
  connect(a, SIGNAL(...), b, SLOT(...));
  connect(c, SIGNAL(...), d, SLOT(...));
  connect(e, SIGNAL(...), f, SLOT(...));
  // etc..
Repeated insertions of Q_ASSERT(ok) would kill readability in such case! In a couple of projects I've seen that people were trying somehow to have the cake and eat it - do not sacrifice readibility but nonetheless report a failed connect. This was done by means of custom Qt builds, where the connect() function was changed to include an assert or to throw an exception in case of failure.

Digression: I'm normally not a fan of exceptions but here they seem to be perfect a perfect match, don't they? Just signal some error condition without polluting the code with error handling! What's here not to love? But on a closer inspection it poses problem in Release builds, as in production environment we do not want to crash a program when some connection are not right. Ok, with enough testing and exception handling code it's not a problem, but asserts are a much simpler method to achieve the same goal.

Technique:

So let us proceed to the advertised technique:
    v << connect(...);
How is the shift omperator implemented? Let's have a look:
    ConnectionVerifier& ConnectionVerifier::operator<<(const QMetaObject::Connection& connection)
    {
        verify(connection);
        return *this;
    }

    void ConnectionVerifier::verify(const QMetaObject::Connection& connection)
    {
        const bool connected = (connection != nullptr);
        //Q_ASSERT(connected);
        if (!connected)
        {
            throw Exception("Could not establish signal-slot connection.");
        }
    }

Now we can easily scale:
  v << connect(a, SIGNAL(...), b, SLOT(...));
  v << connect(c, SIGNAL(...), d, SLOT(...));
  v << connect(e, SIGNAL(...), f, SLOT(...));
  // etc..
Well, this is the code as I found in to be used in the project - somehow the dychotomy of exceptions and asserts we discussed before wasn't resolved by the authors. Admittedly, both alternatives have their merits.

Summing up:

So will I use this technique? Well, it's most useful for the old connect() syntax where the signals and slots are passed as (Q)strings using the SLOT() and SIGNAL() macros - here it is very easy to accidentally misstype the name or parameters of the corresponding slot/signal, believe me,

But with advent of Qt 5 we have also the modern, type-safe syntax alternative:
  connect(a, &A::singnalA, b, &B::slotB);
which I'm using quite exlusively right now. Theoretically there are some corrner cases where it also could fail, but the standard problem we had in the old days, i.e. the typos, is solved now.

However, if you inherited some giant legacy Qt application wehich uses the old connect() syntax, you might be thankfult to have this trick up your sleeve!

Monday, 4 May 2020

Example Programs form the Qt 5 Performace Book


Hi all! You will meanwhile probably have learned that I wrote a book about C++ program performance in the context of the Qt framework (you can have a look at the TOC here).

But along the book I also created quite a few example programs, which, as a rule, aren't discussed in the book. Some of them are pretty nice, so I decided to write up what they are and what they do.

There are two kinds of example programs in that collection: ones that illustrate some performance optimization idea, but also ones which just show how to use some of discussed Qt features. So if you want just learn some Qt usage, you might find it interesting. Also if you are interested in details on the techniques mentioned in the book, you'd better look into the examples, because the book didn't have place for step-by-step exlanations.

Chapter 1: Intro

At the moment no code and no resources here. Sorry. Some examples for usage of basic performance techniques would fit here in nicely, so maybe in the future...

Chapter 2: Profiling

QmlWithModel

This is the program we will be using to show how to take advantage of profiling tools. It has a QML GUI showing all the countries where Qt is used. This list is fetched with an HTTP request from the internet:


As you can check in its code, we can enable:
  •  a memory leak and 
  •  excessive burning of CPU cycles 
in order to show how to find these problems using profilers.

Additionally, there's a recorded ETW trace file of the above application to be browsed with the UI for ETW tool mentioned in the book:


Here you can take your time and look into different metrics which can be collected with ETL!

Addendum: I always wanted to include an example usage of  some flame graph generators in your code, but never got round to it. Maybe I'll find some spare time for it.

Chapter 3: C++ and Compilers

ClassicTemplateTricks

Here we show some of the template techniques mentioned in this chapter, e.g, expression templates for optimized string concatenation, CRTP for avoiding run-time polymorphism and compile-time calculations using recursive templates.


Addendum: Because Qt 5.12 required C++11, the techniques shown in book are the ones supported by that standard. But for example the expression templates could be replaced with fold expressions in C++17!*

Compiler Explorer Tests

Some code you can copy and paste into Matt Godboldt's Compiler Explorer and look at the assembly it produces. Here we can observe such optimization as:

- compiler optimization examples: the basic examples discussed in the book - avoidance of direct summation, elision of allocations, etc.





- constexpr factorial: here you can see the proof that a factorial can be calcualted at comple time! This time without templates, but using constexpr instead!



- constexpr hash: and here is the equivalent proof for a compile-time hash function!



- restrict and pure: here we can see how the restriced and pure attributes can guide the compiler for better optimization and how it's absence worsens the generated code. Unfortunately these attributes are only avaliable as compiler extensions.




- UB examples: here we have a few UB cases mentioned in the book



So just grab the snippets from example files, paste them into Compile Explorer an see live how different compilers optimize your code behind the curtains!

MemoryMgmExamples  - these are examples of a custom memory managers and allocators. They will trace to cout to show when they are used:



MoveTest - in a similar manner, an example usage of the move semantics, also tracing to show that it's working:



Chapter 4: Data Structs and Algorithms

Interning of strings - an example implementation of string interning. As this would be to detailed to explain in the book, I just provided some code for the curious to read through:


Addendum: with Visual Studio compiler we can activate string pooling option to automatically remove duplicate strings!

Schwartzian transform - here we are using the ominous Schwarzian transforrm to paint triangles and christmas trees πŸŽ„!


StdSearch - here we show the usage of the new C++17 Boyer-Moore searcher



Chapter 5: Multithreading

ActiveObject - an implementation of the "Active Object" pattern. You surely remember that we can use this pattern to implement a (nearly) share-nothing multithreading scheme, do you?



ConcurrentAndFutures -  here we load images asynchronously using futures and can compare this to a simple synchronous loading strategy by pressing the "Load All at Once" button:



QFutureInterfaceExample - this is an example explaining usage of the undocumented QFutureInterface class which is widely used in Qt Creator



ThreadsAndTimers - basic example for starting timers in threads (because it can be somehow confusing)


Chapter 6: Case Studies

In this chapter we could do with some more examples, don't you think? Because we have only this single one:

SvgCache - here I show an implementation for the SVG cache we discussed in 6.4.



Chapter 7: I/O and Parsing

JsonExample - example of basic JSON parsing, nothing special, I know



MemMappedFile -  a hands-on demonstration of how to map a file onto memory:



SqlLiteExample - shows example usage of the SQLite database.

First we have to create the DB offline:


then we wil perform some simple SQL manipulations on it:



StreamReaderExample - again a basic example: parsing XML data this time



Chapter 8: Graphics

These examples mainly illustrate the discussion of various Qt graphic interfaces, but the minimal FPS counter can be used as a performance tool as well.

CustomQmlElementsTest - here we paint a simple triangle in QML using several ways to define our own, custom QML element. The FrameBufferTriangle uses custom OpenGL painting on current OpenGL context.



FpsCounterExample - want to know how to implement a live FPS counter for your application? Here we use a particle system to stress the QML runtime measure (and display it in an extra widget!) the FPS rate that can we are able to achieve:



OpenGLWidgetExample - we use Qt's OpenGL support for widgets to draw this classic triangle picture:


It used the most basic (and old...) OpenGL 1.0 API, but hey, this book isn't a graphic tutorial - I just needed this picture for the explanations of how the graphics pipeline is working. Please bear with me.

Qt3DSphereExample - look what is possible with Qt 3D! We animate a rotating sphere using the Phong lighting model:


It is also a very basic program, but the result is rather cool (at least for me).

Chapter 9: Networking

Here I wanted to write some basic demonstrators running client and server on the same machine to show basic usage of TCP sockets and HTTP transport mechanism.

EchoServerTcpExample - an echo server: the client will connect on a given port and the server will echo every data it receives from client!



HttpDownloadExample - here we will connect to a given web address, then fetch and save some resources from there. Additionally, the progress of file download is visualised with a progress bar.


If you have Python installed on your machine, you could start a local web server on some directory and then run this testapp locally. As I mentioned in the book, Qt doesn't have a HTTP server component and doesn't allow us to easily write one.**

Chapter 10: Mobile and Embedded

Here we do not have much resources (sorry, publisher's deadline didn't allow that πŸ˜’) but at least one example pertinent to embedded data presentation could be included.

OpenGLAcceleratedChart - an example of using OpenGL acceleration with Qt Charts. You can parametrize the number of points if you want to stress your hardware!


There is another example implementation I should have provided is the polyline simplification, but due to time shortages I missed out on this one. But at least I provided you with this link: https://www.kdab.com/a-speed-up-for-charting-on-embedded/, which describes the implementation of a polyline simplification technique that uses a flattened min-max tree.

Addendum: If I'll find some time, I could add some example project for my Raspberry-Pi, as I was initially planning. You know, the deadlines etc... :-\.

Chapter 11: Testing and Deploying

ExampleSubdirProjectWithTests - this is an example of how to add tests to an existing project using the Qt Creator:


The tests are wiritten using QTest library, and integrate nicely with Qt Creator's UI, as you can see on the above figure. Also a minimal Qt application is created to be tested here and in the Squish tests below.

SimplestQMLProject - this one is a very simple QML project we will need in the example Squish tests below.



Squish - here we have a definition of Squish tests for both Widgets and QML applications we've introduced above:


Summing Up

So, that's all. I hope you've found something interesting there!

---
* expression templates can be replaced with fold expressions (C++17) for string concatenation, as shown in this post: https://www.qt.io/blog/efficient-qstring-concatenation-with-c17-fold-expressions

** e.g. I couldn't port my old Qt4-based embeddable web server project to Qt5 because of removal of HTTP parsing classes.

Saturday, 4 April 2020

My answer to a young programmer


You maybe know that I offer C++ mentoring via Twitter (DMs are open!) and, as it happened, someone approached me and wanted to be mentored. So I asked him for his questions and then wrote some responses, which ended up to to be qute long... Then the idea to share what I wrote in this blog - maybe someonw will find it interesing.

Without much ado, to the questions.

1. Questions

I first asked about the goals. Thes answers are probably in line with many young programmers want:
1. I just need to be able to solve programming problems and strong myself in
this part, to be qualified for big tech companies interviews like Google,
Microsoft and Amazon. 
2. No the programming language doesn't matter for me, I know the basics of C, C++ and Python but I just want to be a problem solver and think like a programmer 
3.  I just want to understand the theory behind Algorithms and Data Structure
Then also came a list of resources that one finds on the internet using uncle Google. I won't show them here, as thea are quoted in the response.

2 The Response

Here's my response, in full, without any later editing:
Hi Xyz!

I had a look at your references:

>Courses:

>Algorithms and Data structures by Revi
>https://youtube.com/playlist?list=PLEbnTDJUr_IeHYw_sfBOJ6gk5pie0yP-0

Here we have much complexity theory but little of algos - only basic sorting methods.

>Algorithms by Abdul Bari
>https://youtube.com/playlist?list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O

Don't know what to think about it's TOC - maybe too academic (too much about recurrences) but also covers a broad range of themes you'll need. So-so.

>MIT 6.006 Introduction to Algorithms
>https://youtube.com/playlist?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb
Had a look the TOC and liked it! If you can grasp these themes, you'll have good working knowledge of Comp.Sci.

>Books:

>Data Structures and Program Design in C by Robert L. Kruse
>https://goodreads.com/book/show/27846.Data_Structures_and_Program_Design_in_C
Looks like it's pretty old. Probably outdated, looks like waste of time.

>Introduction to Algorithms By Thomas H. Cormen
>https://mitpress.mit.edu/books/introduction-algorithms-third-edition

This is a classic, maybe a little heavy on the academic side, but a good reference to check what the options are. For an algorithms book the "The Algorithm Design Manual" by Steven Skiena is a much lighter read I'd recommed!

>Think Like a Programmer by V. Anton Spraul
>https://goodreads.com/book/show/13590009-think-like-a-programmer

I don't know this one. Had a look at the TOC and it can be OK or even good. It has a couple of programming problems but the title seems to be kind of a clickbait. Notheless. maybe it's good.

>Practice:

>https://hackerrank.com

Don't know this one (sorry) and couldn't check it out, as it requires a login. Back in the day Google recommended topcoder.com for testing your problem-solving skills in competitions, but I don't know the current status of it.

>https://leetcode.com

Don't know this one (sorry), but it looks somehow inetersting at first glance. You have specific questions for Google, Facebook, etc. Could be worth it.

And responses:

>I just need to be able to solve programming problems and strong myself in this part, to be qualified for big tech companies interviews like Google, Microsoft and Amazon.

A classic book for that is "Cracking the Coding Interview" by Gyle Laakmann McDowell - but it's a real tome! "Programming Interviews Exposed" by J. Morgan et. all was a lighte read. "Algorithms for Intreviews" by A. Aziz & A. Prakesh has many tough problems, but the solutions aren't that well explained - a challenge!

>Q1: No the programming language doesn't matter for me, I know the basics of C, C++ and Python but I just want to be a problem solver and think like a programmer

To be a (real) problem solver you need some deep knowledge in at leas one OO-langauge! Programmers think in patterns, you have to learn them by solving programming problems! On a little higher level, you'll need at least cursory knowledge in design patterns - look at the 4 Amigos book!

>Q2: I just want to understand the theory behind Algorithms and Data Structure

You'll have to undertstand the O-notation at least and to be able to estimate the O-complexity of your algoriths. The Master theorem is not really needed though. You have at least to understand NP-complete complexity class (NP=P?). You'll have to be able to estimate run time of an algorithm - which algos would need thousands of years to complete?

Regards,
Marek
3. Summing Up

Hopefully some young programmer will find it helpful!

Trip Report Qt Word Summit, Berlin, 5-6 November 2019


You've probably noticed that I'm not a hell of a conference goer, didn't you? The last conference I attended was the first "Meeting C++" conference in 2014, at that time still taking place in Neuss, Rhineland* instead of the worldly and hipster Berlin.

I tried to go to the two consecutive Meeting C++ conferences in Berlin, but I was both times unable to do it, so eventually I gave up and called it a day on this idea.

But because recently I got somehow more seriously involved with the Qt framework** I thought, hey, why not just go to this one Qt conference*** in Berlin and visit some of my people there as well? No sooner thought than done. And now, three months something later, another idea struck me - why not write up some impressions? So let us go over things I came to remember most vividly.

Of course you could start moaning that it is much toooo late for a trip report, but better late than sorry, so let us begin!

1. Lars Knoll's talk

Lars Knoll, the CTO of the Qt Company was giving a talk on general directions for the future Qt 6 development and it was rather interesting. You can check it out here (PDF), but basically QML will be reworked to be a typed programming language, Javascript will be only optional and graphics will support not only OpenGL but also newer APIs like Vulcan, Metal or Direct3D 12. All that's very interesting, but what struck me the most was the following slide:


As it seems Qt is predominantly used on Windows! That's kind of surprising, taking into account that all the books and articles you read always assume Linux as a platform! I personally did a lot of Qt work on Windows and couldn't ever understand that.

This slide gave me a nice, fuzzy feeling, because my decision to write my Qt book from a point of view of a Windows developer was a right one!

Other books always describe the tooling you can use on Linux, but this doesn't help me on Windows, because most of that tooling (open source) doesn't exist there. So writing of the Chapter 2 (Profiling and Profilers) was a kind of a discovery journey - how can I make open source tooling run and correctly work on Windows?

2. Keynotes

As much as I don't like keynotes - normally they are rather full of business-y bla bla - but one slide of the Natalie Nahai's presentation really impressed me, I mean this one:
You can see the change of the vibes of a webpage from the left (boring, lots of distractions, unusable!) to right (cool, clear, using 1-click donation buttons). Nice! And it really happened during Obama's campaign.

3. Caliatys hydrogen mobility talk

This one was also a keynote (or I think so...) but the CTO of the company has shown us the slide containing a decision table they used for choosing the Qt framework as a platform for mobile development. The application in question should run on both iPhone and Android device. After the recent switch of Dropbox away from a commonn C++ codebase for both platforms you would maybe expect that C++ isn't good for mobile.

See their reasons for choosing Qt in the pic below:


The cloud connector had to be written separately for each platform, apart from this Qt provided for platform-independence!

4. QML on Microcontrollers

I already said, that the new QML will be a compiled, statically typed language in Qt 6. Already today, we can have a foretaste of the future with Qt Quick Ultralite (Qt QUL) that can be run on MCUs (microcontrollers) - a feat in itself, as up to this day Qt and QML needed a much more beefy processors to be run onto! There were quite a few talks centering around that theme, because it seems to be the future of Qt.

Qt Quick Ultralite is thus basically a subset of QML which can be compiled to C++ and run on bare metal (or an RTOS). This is also a direction in which QML will be going in Qt 6. I was pleasently surprised to learn, that Qt QUL was developed by the Qt Company in cooperation with a polish enterprise that ported it to many MCUs (see the picture below πŸ‘‡).


As it's my native country, I couldn't help but to be very pleased. Good job Poland! 😍

5. People and stories

As it goes, I stumbled upon 2 of my old clients at the conference! I tool the opportunity and asked them about how my old projects fared after I left. We had quite good chats and I wanted to talk to them on the next day also, but - you won't believe it - I couldn't spot them anymore! The conference is a pretty big event with masses of people and finding someone is rather matter of luck.

I also could (and was honored to) meet some, i.e. two πŸ™‚, Qt-involved people, I only knew from Twitter, in the real world. As I expected. they turned out to be very nice indeed! Plus I also wound up talking to people in the queue to the canteen and at the exhibitor stands - I even could ask Qt's CTO a question face-to-face after his talk.

Now let us proceed to the "stories" part of this section:

One of my customers I met at the venue told me a nice story right form the threnches, They had a beast of a performance problem with the embedded device in my old project (accidentally same project as in the perf. story 6.4 in the book**), namely, after a day being powered on, the device started to slow down up to a total grind - the UI became totally unresponsive and you had to reboot it. What is your guess for the reason of that?

Yes, you are right, a memory leak.

But you'll never guess what couse it! When displaying the time of the day, on every update (i.e. every second) the displayed string was changed and then restyled using CSS styles. As it turned out, there was a bug in the Qt version we used and restyling leaked memory at that place! How could you possibly find that?!?!, I asked, quite shocked. Well, it was accomplished by the old and proven method of pinching off parts of the programm until the problem disappears. A kind of "divide and conquer" of debugging. The solution? Quite a pragmatic one - just don't use styling in the updates. Unfortunaltely, I forgot to ask how's the look and feel of the widget now.

Want another story? Here we go - I met 2 guys in the queue in the canteen and chattet with them for quite a long time. At the evening, I went out with my Berlin people to their favourite craft beer bar in the neighbourhood. After a couple of pints I catched a glimple of some guy at the counter and had to ask myself - do I know that guy? No, impossible, only locals frequent this bar... But after a couple of further glimpses I just had to settle that and chatted up the guy and his friend. Guess what - they were the exact people I met at the conference. Then we had one more chat and I even could pitch my book** to them! Moral - everybody can google, there isn't such a thing like a hidden gem or an insider-only venue. πŸ˜”

6. Merchandise

Of course I also got some merchandise:
  • a Qt sticker set πŸ“—,
  • a T-shirt and a lanyard keychain from Qt πŸ‘‰,
  • sleeping mask (Batman style!) πŸ¦‡, also from Qt,
  • some small stickers from exhibitor companies 
But not that much I'd expect. There was a raffle where you could win a cool drone (sponsored by one of the exhibitors), but this time I was kinda outta luck.

7. Summing up

You tell me - do you think it was a good conference? The main lecture hall was very impressive in any case. An you could see the Berlin TV-tower right out of the window.

---
* early supporter! πŸ™‹

** see this book: https://www.packtpub.com/application-development/hands-high-performance-programming-qt-5

*** i.e. to the Qt World Summit conference. BTW, here are all QtWS-2019 videos to watch: https://resources.qt.io/qt-world-summit-2019

Saturday, 29 February 2020

Export your Qt Project from VisualStudio to CMake (...or how I stopped worrying and learned to love CMake!)


Yes, I know, this blog was supposed to discuss the high-church themes of languages and system design, and I didn't quite abandoned these goals, but at the momenet I don't have many time to write about deep and interesting things (as you guess, it's time-consuming). To make a long story short, I decided that I'll write about things I'm working on/with just now.

So let us start with CMake and Qt.

1. Intro

You might already have learned that in the next major Qt version (it will be Qt 6) the framework will abandon its old and trusty qmake_build tool and switch to CMake. Why's that?

Although as of lately CMake has acquired a standard tool status in the C++ community, I don't think the desire to be with the cool crowd motivated that change. Rather (AFAIK), qmake's source code developed into an unmaintainable mess, so that nobody wanted to change anything for fear of a total disaster (but feel free to correct me if I'm wrong).

So, as the last alternative to CMake went away, I couldn't advise my client to use qmake for cross platform builds on Windows and Linux with a clear conscience, so in the current project I voted in favour of CMake as our build tool.

You might ask yourself "So what? Just use another tool!". Well, CMake has quite a reputation for being overcomplicated and error-prone. Additionally, it has a text based format, so you will have to become friends with the text editor again.

Before that we could just use convenient graphical IDEs to define the structure of a project, should we lose that comfort now!? If I use Visual Studio with the Qt plugin, I can just drag and drop the Q_OBJECT files into a project and everything just jumps into its place. And what can I do if I already started out with a Visual Studio in first place (as I did in the current project, silly me)!?

2. Convert your Visual Studio Project

So I was loking for some converter of Visual Studion projects and I stumbled upon the the cmake-converter Python tool*. I decised to give it a try and:

1. installed Python 3 first (just googled for the installer and let ir run)

2. Installed the last stable release of cmake-converter:
  pip install cmake-converter
3. Let it run it with:
  cmake-converter -pi -s path/to/file.sln
Where -pi means that we ant use private** includes with CMake and -s specifies a path to the soultion file. You can list all the tool's options using the -h switch. You will see the following output (here I used the verbose output option):


The tool will generate the CMakeLists.txt file as result.

After reading the result file I decided to delete all the generated contents up to the "Source Groups" section and replaced it by my generic Qt-project prologue, i.e.:
  if(UNIX)
   cmake_minimum_required(VERSION 3.10)
  else()
   cmake_minimum_required(VERSION 3.13)
  endif()

  set(CMAKE_CXX_STANDARD 17)
  set(CMAKE_CXX_STANDARD_REQUIRED ON)

  project(GdmRestApiTest VERSION 0.1.0 LANGUAGES CXX)

  ################################################################################
  # Use solution folders feature
  ################################################################################
  set_property(GLOBAL PROPERTY USE_FOLDERS ON)

  ################################################################################
  # Use Qt
  ################################################################################

  set(CMAKE_AUTOMOC ON)
  set(CMAKE_AUTORCC ON)
  set(CMAKE_AUTOUIC ON)

  #set(CMAKE_AUTOUIC_SEARCH_PATHS "src/ui")

  find_package(Qt5 COMPONENTS Core Widgets Gui Network REQUIRED)
Why did I do that? First, the generated CMake file uses some custom Cmake-Tools file which was a little too complicated at the first sight, and secondly, the generated CMake code doesn't take into account that we are using a Qt plugin!

Thus we added the AUTO-MOC/RC/UI lines and the required Qt packages. However, for that to work we have to tell CMake where the Qt framework files are to be found. It can be done by setting an environment variable CMAKE_PREFIX_PATH to the directory wher the Qt CMake integration files can be found, In my case:

  CMAKE_PREFIX_PATH=C:\Qt\Qt5.12.5\5.12.5\msvc2017_64\lib\cmake .

Next we need to manually add the Form_Files and Resource_Files source groups:
  set(Form_Files
      "./GdmRestApiTest.ui"
  )
  source_group("Form Files" FILES ${Form_Files})

  set(Resource_Files
      "./GdmRestApiTest.qrc"
  )
  source_group("Resource Files" FILES ${Resource_Files})
Now the generated source groups can be reused.

Next we need to include the Form_Files and Resource_Files source groups in ALL_FILES so that AUTO-UI/RC can be applied:
  set(ALL_FILES
      ${Form_Files}
      ${Resource_Files}   
      ${Header_Files__generated}
      ${Source_Files}
      ${Source_Files__generated}
  )
Now, all the source files of the project are specified and we can turn to the definitions needed by compiler and linker. Again I deleted the Target and all the consecutive sections (because, you know, too complicated...) and replaced them by my generic Qt definitions:
  ################################################################################
  # Target
  ################################################################################
  if(MSVC)
   # set /SUBSYSTEM:WINDOWS
   add_executable(${PROJECT_NAME} WIN32 ${ALL_FILES})
  else()
   add_executable(${PROJECT_NAME} ${ALL_FILES})
  endif()

  ################################################################################
  # Include directories
  ################################################################################
  target_include_directories(${PROJECT_NAME} PRIVATE
      "${CMAKE_CURRENT_SOURCE_DIR}/../qt5cpp-openapi/client;"
      "${CMAKE_CURRENT_SOURCE_DIR}/GeneratedFiles;"
  )

  ################################################################################
  # Compiler flags
  ################################################################################
  if(MSVC)
     # quiet warnings related to fopen, sscanf, etc.
     target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS)
  endif()

  # force more warnings!
  target_compile_options(${PROJECT_NAME} PRIVATE
    $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
      Wall>
   $<$<CXX_COMPILER_ID:MSVC>:
     /W4>)

  ################################################################################
  # Dependencies
  ################################################################################
  set(ADDITIONAL_LIBRARY_DEPENDENCIES
    "Qt5::Core;"
    "Qt5::Gui;"
    "Qt5::Network;"
    "Qt5::Widgets"
  )
  target_link_libraries(${PROJECT_NAME} PUBLIC "${ADDITIONAL_LIBRARY_DEPENDENCIES}")
As we see, they define the executable, additional include directories, the compiler flags we need and the library dependencies for the linker. Ready!

3. Run your CMake project

Now it's time to test it out. As Visual Studio has acquired support for directly working with CMake lately, we can use it to test our CMake file right away!

In my Visual Studio 2019 installation (version 16.3.8, Professional) I do the following:
  • Start Visual Studio
  • Choose "Proceed without file" in the starting screen that appears first
  • In Visual Studio's IDE I click "File" > "Open" > "CMake" menu item and choose the CMakeLists.txt file we created.
  • Now we have to wait, as Visual Studio tries to perform the "Configure" and "Generate" steps for the CMakeLists.txt file.
  • After that, we should be able to build the project - select the CMakeLists.txt file in the project panel on the left and choose "Build" in it's context menu (see the pic below).
  • If you want to start the debugger, select the CMakeLists.txt file in the project panel and choose "Set as Current Project". Then just start the debugger clicking on the green arrow button in the toolbar (see the pic below).

Sometimes the automatic CMake generation might fail, or you'd like to reset the project. In that case you select select the CMakeLists.txt file in the project panel and
  • choose "Delete CMake Cache" to reset the project
  • choose "Generate CMake Cache" to recreate the build files
  • start the build as described above
Ready! To thest my Qt application on Linux I have only to:
  • check out the project on the Linux machine
  • open it in Qt Creator
  • and let it build and run!
4. The Moral

I hope you fear CMake no more now! If we aren't overcomplicating things, CMake might indeed be a pretty nice and handy tool for building projects on both Windows and Linux (and of course also on other platforms).

The technique I currently use is:
  • add all .cpp and .hpp files to the Visual Studio project
  • export the project using the cmake-converter tool
  • replace all generated content beside the file lists with my generic CMake prologue and epilogue
  • slightly adapt prologue/epilogue if needed
This works and won't cost you a lot of time.

--
 * "CMake converter for Visual Studio projects" - https://pypi.org/project/cmake-converter/

 ** private CMake includes (i.e. include directories) aren't exported to other CMake projects,