Qt, CMake and Visual Studio Behavior - c++

I'm porting some of my Qt projects into CMake to make them more flexible across different IDE's.
The only sad part with CMake, when I generate VS solution, it won't work amazingly as it works with the Qt VS Extension.
For example if I change a .ui file, I'll need to rebuild the project in order to see the changes in the GUI in comparison to when I use the VS Extension generated project, it will identify the changes automatically and re-moc the class that owns the .ui file without having to re-build the whole project.
If I look at the project configuration the VS Extension generates in the .vcxproj file, it would add ItemDefinitionGroup some items as follows:
And each class/file that is included in the project, will be flagged according to the type of the class(QtMoc, QtUic, QtRcc):
Probably this what gives the Qt VS Extension to identify how to treat each file, so if it's QtUic, then it would check if any changes in the .ui files are present, and if there are new changes, it would re-compile the ui file, then moc the class that belongs to the .ui file and only then re-compile the actual class that owns the .ui file.
In summary, is there any possible way to make CMake generate a project similar to one Qt VS Extension generated when I choose in CMake the VS generator?
I'm guessing CMake doesn't support this internally, as they tend to abstract all this behavior to make all VS projects as generic as possible no matter what framework is used, but CMake does have flags to support Qt like:
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
So I'm assuming it wouldn't be much of a work to implement.
Probably my best bet is to fork CMake and re-implement this behavior myself?
psuedo example:
if CMAKE_AUTOMOC == ON & CMAKE_VS_EXT == ON
Do some custom changes to the .vcxproj file
endif
Sorry for the long post, but any ideas and help would be greatly appreciated. Thanks!

As it's too much (code) for a comment I put that an answer.
AFAIK you do not have to include the generated files to your add_executable call. That is something CMake automoc feature does behind the scenes.
A typical sequence in our CMakeLists.txt files look as follows:
include_directories(${CMAKE_CURRENT_BINARY_DIR})
file(GLOB_RECURSE SOURCES sources/*.cpp)
file(GLOB_RECURSE HEADERS include/*.h)
file(GLOB_RECURSE FORMS ui/*.ui)
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)
file(GLOB_RECURSE RESOURCES resources/*.qrc)
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC TRUE)
set(CMAKE_AUTORCC TRUE)
add_library(theLib ${SOURCES} ${HEADERS} ${FORMS} ${RESOURCES})
target_include_directories(theLib BEFORE
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)

Related

problems with highly specific cmake + qtCreator use case and unit tests

My troubles with CMake keep compounding D:
What I have in mind is to create my project so that when I build it, it runs unit tests and if unit tests fail, it cleans up after itself. Otherwise, if they succeed, the build spits the runnable executable into the run/ directory.
My project directory contains subdirectories sources, headers, build, run, and tst/ut and thus far I have cmakelists at project root as well as inside sources and headers directories
CMakeLists.txt at the project root
project(TaskFour LANGUAGES CXX)
enable_testing()
set(BIN ${CMAKE_PROJECT_NAME})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
add_library(${BIN}_lib)
add_executable(${BIN}_run)
include_directories(sources headers tst/ut)
cmakelists at sources/
set(SRC
main.cpp)
target_sources(${BIN} PUBLIC ${SRC})
and headers
#contents of this list are empty by design for now
set(SRC
"")
target_sources(${BIN} PUBLIC ${SRC})
With these CMake list files, QtCreator fails to see anything beyond the top-level CMake list file. It doesn't acknowledge the existence of the subdirectories in the project directory, the other two cmakeLists.txt files nor the main.cpp that very much exists inside the sources directory.
I have attempted to use the add_subdirectory command and that seemed to help as that made all the subdirectories show up. However, I quickly realized that QtCreator seemingly treated every subdirectory like its own project, and trying to add files into these newfangled "projects" resulted in a simple "failed to add one or more files to project foo" message.
I have understood that the point of CMake list files is to have several per project, each governing their own subsection of the larger project, and the top CMake list file gathering it all together. Before I did my CMake file as one big file at the root of the project, and I've understood that to not be good. I also understand that dividing headers and sources like I do is not exactly the most common practice but I hope you forgive me and help me get this thing working.
So, my actual question is, how do I do this? What am I currently doing wrong in my top-level cmakelists file to cause qtCreator to not find the files in the project? How do I write the CMake lists so that it would allow me to use the QTest framework, maybe even build the skeleton from QtCreator's project wizard (as currently the option to add the autotest project as a subproject is greyed out)?
Any insight is appreciated, and feel free to go into detail about CMake if you feel like it. This is an important piece of software development that I feel I've been missing out on.
There's a couple problems here with how you've organized your CMake file. This should at least get you started on the right path
You're calling add_library(${BIN}_lib) and add_executable(${BIN}_run) but then in your child CMake file you're calling target_sources(${BIN} ...) - target names are evaluated as strings - there is no target named BIN (or the value you set to BIN in this case), and adding sources to a target named BIN would not propagate those sources to targets named BIN_lib and BIN_run
include_directories is for adding entries to the C++ compiler's include search path, not for adding additional directories containing sources/other CMake files. For that, as you seem to have already figured out, you need add_subdirectories(...)

Generating dll from an existing code on Windows using CMake and VS

I have downloaded an SDK written in C++ (OPC UA) that creates a .exe file on compiling with Visual Studio 2015. It has a bunch of CMake files. How could one see if it is possible to generate a .dll from such an SDK? Do the CMake files have this information or should there be any macros inside the headers I would have to search for ? The SDK has Visual Studio sample projects (.sln) that I am using to create .exe.
The CMakeLists.txt looks like this
project(uasdk)
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
include(CMakeDependentOption)
include(MessageUtils)
display_project_header("true")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src")
add_subdirectory(src)
endif ()
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples")
add_subdirectory(examples)
endif ()
# set CMAKE_INSTALL_MESSAGE to LAZY by default to hide 'Up to date' output when building INSTALL target
if (NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
set(CMAKE_INSTALL_MESSAGE LAZY CACHE STRING "")
set(CMAKE_INSTALL_MESSAGE_VALUES "ALWAYS;LAZY;NEVER")
set_property(CACHE CMAKE_INSTALL_MESSAGE PROPERTY STRINGS ${CMAKE_INSTALL_MESSAGE_VALUES})
endif ()
The questions that already have been asked regarding this topic are from the people who are writing their own code. I intend to use the code from the SDK. Apart from changing the CMAKE file to include the dll do I need to make changes in the source code as well?
It has a bunch of CMake files. How could one see if it is possible to generate a .dll from such an SDK? Do, the CMake files have this information or should there be any MACROS inside the headers I would have to search for ?
If the CMake project generates a library, then the statement add_library must appear somewhere. Note, however, that hierarchies of CMakeLists.txt files are possible, for example, the CMakeLists.txt you included adds two subdirectories. Consider the CMakeLists.txt files in there as well. Since an executable is generated, a call to add_executable must appear somewhere as well.
I intend to use the code from the SDK. Apart from changing the CMAKE file to include the dll do I need to make changes in the source code as well?
I am not familiar with this SDK, but I would guess that examples contains the sources for the executable and src contains the sources for a library. If you just want to try something out, you can modify the example code or add a new example. In this case, you only have to modify the CMakeLists.txt in the examples directory (i.e., add your new source code file).
If you want to use the SDK as external dependency, check whether there is a FindNameofmySDK.cmake included in the CMake modules list or whether there is a NameofmySDK-config.cmake somewhere in the SDK sources or your installation. In this case, you can create a CMake project for your application and use find_package to look for the SDK.

cmake - support of Visual Studio filters

I have a cmake file that generate a solution with several sub projects, but I wish a "filter" (VS specific feature) to group all my thirdparty libraries together.
An example, for now I use the ZLIB library, it appear as a project, I use the following:
add_subdirectory(zlib)
To add such filter, I have try the following :
add_subdirectory(zlib)
FILE(GLOB_RECURSE ZLIB_SOURCE "zlib/*")
SOURCE_GROUP("THIRDPARTY" FILES ${ZLIB_SOURCE})
In this example I wish to put the "zlib" project into a "THIRDPARTY" filter.
But nothing is changed in my solution ! I use VS2017 and cmake 3.8
Any idea ?
There are two ways of separating all your own and third-party code of an application in the solution explorer.
Separate multiple Projects and put them into folders which are on top-level.
Do the following:
put this on top of your main CMakeLists.txt
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
after defining your targets add this extra bit
add_executable(MyLib .....)
set_target_properties(MyLib
PROPERTIES
FOLDER "Libraries");
Your project-explorer will then look like this:
credit goes to these guys: http://cmake.3232098.n2.nabble.com/Solution-folders-td6043529.html
To separate multiple source-files inside a project you can do the following:
collect all files of a module with:
set(VARIABLE_NAME src/module/fileName1.cpp
src/module/fileName2.cpp)
make it appear within a filter:
source_group("Source Files\\module" FILES ${VARIABLE_NAME})
group all previously generated filters together:
set(SOURCE_FILES "${VARIABLE_NAME}")
finally make everything appear inside the project explorer:
add_executable(projectName "${SOURCE_FILES}")
The above works for me under CMake 3.6 and Visual Studio 2015, so it should also work with VS2017 and Cmake 3.8.
It looks like this when finished for all files of the project:
Since you are developing with VS here's another hint that I think is very useful:
you can define VS's startup project by the following command. This way you don't have to change anything in VS after remaking the project with CMake.
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ProjectName)

How to configure CLion IDE for Qt Framework?

How to configure CLion IDE for Qt Framework?
Is this IDE compatible with Qt, or are there other IDEs compatible with Qt?
I just want to try to use something else than Qt Creator.
I was as desperate as you, until I read this Quora discussion.
It worked perfectly for me!
To summarize, there are 2 main steps:
Firstly, CLion uses CMake to compile your code. It is based on CMake configuration files (e.g "CMakeLists.txt"). You have to add Qt based CMake commands (the lines with 'find_package' and 'target_link_libraries'):
cmake_minimum_required(VERSION 3.5)
project(myqtproject)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
find_package(Qt5Widgets REQUIRED) <-- this line
add_executable(myqtproject ${SOURCE_FILES})
target_link_libraries(myqtproject Qt5::Widgets) <-- this line
Secondly, CLion has to use the cmake binary installed by Qt. For that, go to:
'Preferences' -> 'Build, Execution, Deployment' -> 'CMake' and in 'CMake options' append the CMake path that Qt uses, which should be in the directory where Qt is installed. For instance, on OSX:
-DCMAKE_PREFIX_PATH=/Users/edouard/Qt/5.7/clang_64/lib/cmake
You can test that everything is working fine, by doing a little test script in main.cpp:
#include <QApplication>
#include <QDebug>
using namespace std;
int main() {
qDebug() << QT_VERSION_STR;
return 1;
}
Which should display something like:
/Users/edouard/Library/Caches/CLion2016.2/cmake/generated/myqtproject-89a4132/89a4132/Debug/untitled
5.7.0
Process finished with exit code 1
UPDATE
I was stuck with the problem of adding Qt5 modules (for instance QSql). You can do this by adding in the CMakeLists.txt:
find_package(Qt5Sql REQUIRED)
just after the other find_package, and adding in the last line:
target_link_libraries(myqtproject Qt5::Widgets Qt5::Sql)
You can do this with all the other Qt5 modules.
UPDATE
There is an now an official tutorial on the Jet Brain website:
https://www.jetbrains.com/help/clion/qt-tutorial.html
Original answer
This approach is one of the simplest way to be used for the newest Qt version.
Qt: 5.10.1
CLion: 2018.1.2
GDB: 8.1
Project setup
In CLion:
Create a C++ Executable/Library project
Use this sample "CMakeLists.txt" for common console/gui projects that uses: QtCore, QtWidgets and QtQuick
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(PROJECT_NAME)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_PREFIX_PATH "PATH_TO_QT/QT_VERSION/QT_ARCH/lib/cmake")
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Quick REQUIRED)
add_executable(PROJECT_NAME main.cpp MainWindow.cpp MainWindow.h qml.qrc)
target_link_libraries(PROJECT_NAME Qt5::Core)
target_link_libraries(PROJECT_NAME Qt5::Widgets)
target_link_libraries(PROJECT_NAME Qt5::Quick)
Resource files (.qrc) should be added to add_executable list, in
order for moc to be able to run its procedure on the resource and the
internal file like qmls, texts, ... be accessible.
qml files should be included in a qrc file and load using QQmlApplicationEngine at runtime
Debuger:
In order to has a human-readable view in debug sessions from Qt types, A new GDB must be installed on the system and pretty printers must be available:
Pretty printers for Qt5:
1- Lekensteyn Qt5 Pretty Printers (Working):
Address: https://github.com/Lekensteyn/qt5printers
Setup: ~/.gdbinit
python
import sys, os.path
sys.path.insert(0, os.path.expanduser('~/.gdb'))
import qt5printers
qt5printers.register_printers(gdb.current_objfile())
end
2- Official (not working!!!):
"PATH_TO_QT/QT_VERSION/QT_ARCH/Tools/QtCreator/share/qtcreator/debugger/"
Setup: ~/.gdbinit
As stated in included readme file (but not working!):
python sys.path.insert(1, '<path/to/qtcreator>/share/qtcreator/debugger/')
python from gdbbridge import *
External tools
In "File -> Settings -> Tools -> External Tools", add 4 external tools:
Qt Creator:
Program: "PATH_TO_QT/QT_VERSION/QT_ARCH/Tools/QtCreator/bin/qtcreator"
Arguments: $FilePath$
UI Designer:
Program: "PATH_TO_QT/QT_VERSION/QT_ARCH/lib/bin/designer")
Arguments: $FilePath$
LUpdate:
Program: "PATH_TO_QT/QT_VERSION/QT_ARCH/lib/bin/lupdate")
Arguments: $FilePath$ -ts $FileNameWithoutExtension$.ts
Linguist:
Program: "PATH_TO_QT/QT_VERSION/QT_ARCH/lib/bin/linguist")
Arguments: $FilePath$
Now you can right click these file types and under the external tool:
For .ui select Qt Creator/Designer and start UI designing
For .qml select Qt Creator and design UI in QML editor
For .qrc select Qt Creator and use resource editor
For .cpp/.ui select LUpdate to create its translation file
For .ts select Linguist and start the translating
Automatic Beautifier
If in Qt Creator you used a beautifier like "Uncrustify" to auto beautify the code on saving a source file, then:
Install the plugin "Save Actions"
Under the "File -> Settings -> Save Actions"
Check:
Active save actions on save
Reformat file
For best performance un-check:
Organize imports
As Tom Lank mentions, Qt projects can now be managed with, and built under CMake, which makes CLion happy.
Qt5's CMake manual describes how. Qt provides a lot of magic under the hood here, and it's explained much better in the CMake documentation.
One thing that isn't mentioned in the Qt CMake manual or above is that you'll also need the lines:
set(CMAKE_AUTOUIC ON) # if you have any .ui files
set(CMAKE_AUTORCC ON) # if you have any .qrc files
All of these calls to set() should probably come before the line find_package(Qt5Widgets REQUIRED). Also include any .ui or .qrc files as dependencies in the call to add_executable() along with your .cpp files.
This was initially very confusing to me from browsing the web, but you shouldn't need any calls to qt_*() or qt5_*(). These have been superseded so far as I can tell.
To test that your CMakeLists.txt actually works correctly, you can try building within Qt Creator, by loading CMakeLists.txt as a project and building.
Once confirmed, you can load the CMakeLists.txt file as a project in CLion.
Most likely, you'll need to tell CMake where to find your Qt packages with a line like this before your find_package's:
set(CMAKE_PREFIX_PATH "C:/Qt/5.9/msvc2015_64")
Finally, if you're running on / building for windows, Qt no longer comes pre-built with GCC/Mingw32 libraries. You need to build with visual studio. Luckily, CLion now supports Visual Studio experimentally and I've found it to work for Qt projects; just be sure to set the architecture (under Settings->Build, Execution, Development->CMake) to x86_amd64, in order to build in 64-bit mode and be compatible with Qt's pre-build libs.
All of this is tested with CLion 2017.1, Qt 5.9, and the Visual Studio 2015 compiler.
You can build QT applications in CLion.
QT Provides CMake modules that take care of all details.
The following CMake script builds the example application 'Dynamic Layouts Example'
cmake_minimum_required(VERSION 3.7)
project(qtlayoutexample)
set(CMAKE_CXX_STANDARD 14)
# Find QT packages
find_package(Qt5Widgets)
# Add the include directories for the Qt 5 Widgets module to
# the compile lines.
include_directories(${Qt5Widgets_INCLUDE_DIRS})
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
# Add compiler flags for building executables (-fPIE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
qt5_generate_moc(main.cpp main.moc)
# Tell CMake to create the qtlayoutexample executable
add_executable(qtlayoutexample main.cpp dialog.cpp main.moc)
#Link the qtlayoutexample executable to the Qt 5 widgets library.
target_link_libraries(qtlayoutexample Qt5::Widgets)
More information regarding building Qt applications with CMake.
This link has a quickstart project, you just have to change your CMAKE_PREFIX_PATH in CMakeLists to the location of the Qt packaged compiler you want to use (mine is gcc_64, his by default is clang_64)-- it has some of the settings mentioned by other answers already set:
https://github.com/ArneGockeln/qtstarter
In addition, (on Ubuntu-based Linux) I had to install the OpenGL libraries as described here (https://askubuntu.com/questions/11378/how-do-i-set-up-an-opengl-programming-environment).
You can easily develop Qt with VC, Eclipse, CLion etc. when you use CMake as a build tool. CMake will generate the project files for each IDE. I was using several IDEs this way. After this journey I am an even happier user of Qt Creator.
The only thing you need is to add QT install ..Qt\5.10.1\mingw53_32\bin; to your PATH. Don't forget to restart PC afterwards, because CLion for some reason isn't able to refresh the path, only full pc restart helps.

CMake: 'AUTOMOC' feature skips sources of executable targets?

There is a medium-sized project with a top level CMakeLists.txt which defines some common stuff and invokes the configuration of all artifacts (subprojects) in the project like this:
add_subdirectory(components/A)
add_subdirectory(components/B)
add_subdirectory(components/C)
add_subdirectory(components/E)
Artifacts are static/shared libraries or executables (which somehow depend on each other). In this example, there is only one executable: E. Everything configures and builds perfectly fine when plain old qt4_wrap_cpp is used to process MOC.
When switching to the (relatively) new AUTOMOC feature by adding the following to the top CMakeLists.txt:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
all the sources of static/shared libraries are AUTOMOC'ed just fine. However, the sources of executable target (E in this example) are never AUTOMOC'ed.
I've tried both MSYS Makefiles and Ninja generators, and both simply do not create the target for AUTOMOC'ing, but only for executable's sources (for static/shared library targets AUTOMOC'ing target is added).
Has anyone experienced that already?
What could be the cause?
Does that smell like a bug?
Update
I found the cause, the discussion is on CMake mailing list.
To summarize, the problem was that E didn't include Qt module neither explicitly:
find_package(Qt4 ...)
nor implicitly:
find_package(MyPrecious ...)
where MyPrecious could be some 3rd party module which includes Qt by itself.
As a result, non-cached variables like QT_VERSION_* are not present in the scope of E subproject, and for that reason AUTOMOC feature cannot function properly. Nasty pitfall I'd say. For more details refer to CMake mailing list.