I would like to compile qml application using cmake.
Here is my cmake file:
cmake_minimum_required(VERSION 3.3)
project(QMLTest)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Quick REQUIRED)
add_executable(QMLTest main.cpp)
include_directories(${Qt5Widgets_INCLUDES})
add_definitions(${Qt5Widgets_DEFINITIONS})
qt5_use_modules(QMLTest Widgets Quick )
And main.cpp:
#include <QGuiApplication>
#include <QQuickView>
int main(int argc, char** argv)
{
QGuiApplication app(argc, argv);
QQuickView view;
view.resize(800, 480);
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl::fromLocalFile("gui/MainWidnow.qml"));
view.show();
return app.exec();
}
When I try to compile it I get an error:
gui/MainWidnow.qml: File not found.
How can I copy all my qt resources into application directory?
Instead of copying your QML files into the application directory, I would instead recommend using Qt's resource system (1), which allows you to embed resources such as QML files directly in your executable. To do this, you need to first create a resource file such as resources.qrc to register your application resources:
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource>
<file>gui/MainWindow.qml</file>
</qresource>
</RCC>
You then add the resource file to your CMake configuration. This will create a source file from the resource file which you need to include in your application sources:
qt5_add_resources(RCC_SOURCES resources.qrc)
add_executable(QMLTest ${RCC_SOURCES} main.cpp)
Once this is done, you can use a file URL in the format :/gui/MainWindow.qml to refer to this resource, which is now embedded in your application binary. Qt will automatically resolve it for you:
view.setSource(QUrl(":/gui/MainWindow.qml"));
There are some more details in the Qt documentation on deploying QML applications (2).
I would like to extend the accepted answer.
I would write this as a comment but I don't have the reputation.
It is possible to use Qt independent CMAKE function calls instead of qt5_add_resources():
set(CMAKE_AUTORCC ON)
add_executable(myexe main.cpp resource_file.qrc)
And then you can refer to the files using :/file_relative_to_qrc
There are multiple ways to do that, for example:
add_custom_target(copy-runtime ALL
COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/gui/MainWindow.qml
${CMAKE_BINARY_DIR}
DEPENDS QMLTest)
I didn't test that, but you'll get the idea. Another option would be e.g. to use CMake's install command to install the runtime files locally with "make install". However, in this case the best option would be to use Qt's resource system like ajshort recommends in his answer and embed the needed files in the executable.
Related
I have read the 5 tutorial from QT-test website. But they are not what I want.
I want to build a project and its unit test part is detached from the main program.
For example:
In main program has a push-botton on widgets and if it was clicked then a Qlabel will show a number.
If I run the test programm, It would mock MouseClicked Event on that button, then verify if the value which shows up on Qlabel is our expectations.
My question is how can I get my test program linked to the main program so that I can access its members? Besides that I want to build the project using CMake, how should I write the CMakeLists for the test project?
---root
|---test
|----CmakeLists.txt
|----test.cpp
|----test.h
|---build
|----main.cpp // only int main function
|----QMainwindows.cpp
|----QMainwindows.h
|----QMainwindows.ui
|----CmakeLists.txt
And the CMakeLists.txt in root
cmake_minimum_required(VERSION 3.5)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
project(myproject VERSION 0.1 LANGUAGES CXX)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
set(PROJECT_SOURCES
main.cpp
QMainwindows.cpp
QMainwindows.h
QMainwindows.ui
)
add_executable(myproject ${PROJECT_SOURCES})
target_link_libraries(myprojectPRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
I am also confused how to access the members from mainwindow in our test. I mean I cant include the ui_mainwindow.h and create an UI_Mainwindow Instance
I found an approach that could answer my question.
In test part I can use findchild<T>("WidgetsName") to get access to ui members of any class.
reference : How do you get a widget's children in Qt?
This may not be a universal solution and if anyone has a better idea, I would be grateful.
Suddenly the linked images in the qrc file are no longer visible, I don't know what happened.
I've already tried deleting the cmake generated files and recompiling, but it still doesn't work...
QRC FILE
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>sprites/peggle_title.png</file>
<file>icons/peggle.ico</file>
<file>sprites/krita.png</file>
<file>sprites/ball.png</file>
<file>sprites/peggles.png</file>
<file>sprites/stage_elements.png</file>
<file>sprites/Peggle_Fonts.png</file>
<file>sprites/sprites.png</file>
<file>sprites/scaricati/Peggle2PegglePS3LeftoverGraphic5.png</file>
<file>sprites/choose_character.png</file>
<file>sprites/mainMenu.png</file>
<file>sprites/gameMode.png</file>
<file>sprites/gameMode_buttons.png</file>
<file>sprites/character_buttons.png</file>
<file>sprites/select_single_character.png</file>
<file>sprites/action_buttons.png</file>
<file>sprites/character_face.png</file>
<file>sprites/select_difficulty.png</file>
<file>sprites/results.png</file>
<file>sprites/results_label.png</file>
<file>sounds/peghit.wav</file>
</qresource>
</RCC>
CMAKELISTS.txt
project(Peggle)
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
file(GLOB my_sources *.h *.cpp *.qrc)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
add_executable(Peggle ${my_sources} resources.qrc)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Multimedia REQUIRED)
find_package(box2d REQUIRED)
include_directories(Box2D)
target_link_libraries(Peggle Qt5::Widgets Qt5::Multimedia box2d)
And for example:
QPixmap *title = new QPixmap(":/sprites/peggle_title.png");
(I'm using Visual Studio 2019 and Cmake gui)
Thanks for the help!
Most of the times, users forget to run qmake. Have you tried that? Just right clicked on the project, and select "Run qmake". If yes then try deleting all of the resource files and create new resource file. Also add the qrc path in the application's pro file.
I have a Visual Studio Qt solution that I am moving to Cmake.
Everything is compiling and working fine, except all icons (.png) that I have in *.qrc file are not displayed at all.
My CMakeLists.txt is standard for a Qt project:
...
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(SOURCE_FILES ...)
set(HEADER_FILES ...)
set(UI_FILES ...)
set(RESOURCE_FILES resources/res.qrc)
add_executable(project WIN32 ${SOURCE_FILES} ${HEADER_FILES} ${UI_FILES} ${RESOURCE_FILES})
find_package(Qt5 REQUIRED COMPONENTS ...)
target_link_libraries(project PRIVATE Qt5::Core etc...)
I think that all icons are in fact embedded into .exe, because:
1. If I remove all paths from the qrc file and recompile, the .exe size is decreased by the icons size
2. I checked the qrc_*.cpp generated by AUTORCC and all the images are there.
But when I am iterating over all my resources using this code snippet
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}
the icons are NOT there.
I have tried an alternative approach with qt5_add_resources() instead of AUTORCC and the result is the same.
I also have all the iconengines, imageformats, platforms, styles folders on the same path as .exe.
Edit:
Added the whole Cmake part of the project to github.
Considering the discussion we had in your post comment, CMake works as expected and the resources are loaded into your application.
As you mentioned "When I run my app from clion it shows the images. If I copy the exe to a folder with *.dll etc it doesn't.", so either:
Some files are missing when you copy them, you should try to use windeployqt to correctly copy what's needed at runtime
Or the problem comes from the way the qrc is neing loaded, then, I suggest that you debug the content of qrc_*.cpp files (your can debug it after you copied it outside clion) and see why it fails to load the resource
Anyway this looks more like a deployment issue than a configuration/compilation issue.
I have a set-up as explained elsewhere, e.g. here. I have Qt5 installed system-wide,
and have the requisite lines in my CMakeLists.txt. My IDE is Clion.
Everything in a simple GUI goes fine until I add Q_OBJECT macro (I want this to connect signals to slots). Now, when I do this, I get the undefined reference to vtable-type error,
that is also found in abundance on the net.
My confusion arises from the fact that some recommend using Qt5-bundled cmake for your project,
which essentially means "just for GUI" I need to change the toolchain. But some actually say nothing about it. What all say is that
Qt runs qmake every time Q_OBJECT is added/deleted
Now, how to capture that in my CMakeLists.txt? -- the relevant part thereof is given below.
I've seenmoc and qmake inside /usr/lib/qt5/bin; so how to communicate this to CLion?
# ----- GUI part -----
# Qt5 inclusion
# The meta object compiler is one of the core functionality of Qt, it reads a C++ header file and if it finds a
# Q_OBJECT macro, it will produces a C++ source file containing meta object code for the class.
# It's the mechanism that allow signal and slots to work.
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# set(CMAKE_PREFIX_PATH $ENV{QT_DIR}/$ENV{QT_VERSION}/gcc_64/lib/cmake)
set(CMAKE_PREFIX_PATH /usr/lib/qt5/bin/)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# Enable user interface compiler (UIC)
# The user interface compiler is a program that read XML from the .ui file
# generated by Qt Interface Designer and generate C++ code from it.
set(CMAKE_AUTOUIC ON)
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
set(CMAKE_MODULE_PATH /usr/lib/qt5)
# #see: https://stackoverflow.com/questions/51994603/cmake-qt5-undefined-reference-to-qprinterqprinterqprinterprintermode
SET(QT5_MODULES Widgets PrintSupport)
find_package(Qt5 COMPONENTS ${QT5_MODULES} REQUIRED)
add_subdirectory(${PROJECT_SOURCE_DIR}/extern/qcustomplot)
add_executable(gui
${PROJECT_SOURCE_DIR}/gui/main.cpp
${PROJECT_SOURCE_DIR}/extern/qcustomplot/qcustomplot.cpp)
set_target_properties(gui PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(gui
PUBLIC
Qt5::Core Qt5::Widgets qcustomplot)
Never mind the verbose comments; my initial GUI training being in Java Swing, I found them useful.
EDIT: what helped me was the qt5_wrapper_cpp thing mentioned in
Qt 5 cmake fails with undefined reference to vtable on hello world with inc & src as subdirs
Q_OBJECT macro requires code generation. That's why you got undefined reference exceptions. I don't remember exactly how to configure a cmake project for Qt, but I would recommend reading https://cmake.org/cmake/help/latest/manual/cmake-qt.7.html.
Something like set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE) should help you.
Summary
I am trying to compile ánd run/debug Qt code in Clion on Windows. Both CMake and the building process return no errors.
The following scenarios occur:
When I try to run I get Process finished with exit code -1073741511 (0xC0000139)
When I try to debug I get Process finished with exit code 1
When I try to run the executable via Windows CMD directly, the executable runs as intended.
When I copy all dll files from ../Qt/5.12.6/mingw73_64/bin to the project's cmake-build-debug folder, the executable runs and debugs within CLion as expected.
My setup
Windows 10
Qt 5.12.6 (mingw73_64 build)
CLion 2019.2.5
MinGW (x86_64-8.1.0-win32-seh-rt_v6_rev0)
CMake (bundled, 3.15.3)
Other findings
I believe there are many related topics on StackOverflow that deal with the same issue. But none manage to provide a definitive answer to what I believe to be a Path/Environment issue. Many suggestions boil down to "Add Qt to your path/PATH/Path environment variable and reboot reboot reboot!", and/or mostly pertain to linux installs. Hence I hope this becomes a more complete question and answer for people running into the same error code within this context, as it is likely related to this same issue.
As things work outside of CLion (as shown by (3)) and work inside of CLion when I copy DLLs (4), I believe I am dealing a dynamic linking issue as a result of CLion related environment issues. Adding the Qt bin folder, which is C:\Qt\5.12.6\mingw73_64\bin, to my System Environment Variables made it so I could run the exe file directly from CMD. Note that I added the Qt bin folder path to the Path variable.
Given that some mentioned online that it is possibly an issue with the user variables due to CLion running as a certain system user, I also added said path as a User Environment Variable, again Path. But alas.
Additionally, I tried adding it as an environment variable directly in CLion via Settings -> Appearance & Behavior -> Path Variables. Here I tried mapping the Qt bin folder to Path, PATH, and QT_DIR respectively. Still no success, even though I tried many reboots. Both Windows restarts and real shutdowns were attempted many times in between changing paths etc.
Main question:
How can I resolve the issue I described, so I can run and debug my Qt builds in CLion without having to copy Qt related DLLs to my cmake-build-debug where the executable is located.
CMakeLists.txt
Within Settings -> Build, Execution, Deployment -> CMake I have set CMake options: to -DCMAKE_PREFIX_PATH=C:\\Qt\\5.12.6\\mingw73_64\\lib\\cmake
cmake_minimum_required(VERSION 3.8)
project(HelloWorld)
set(CMAKE_CXX_STANDARD 14)
# Include a library search using find_package()
# via REQUIRED, specify that libraries are required
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
# specify which libraries to connect
target_link_libraries(${PROJECT_NAME} Qt5::Core)
target_link_libraries(${PROJECT_NAME} Qt5::Gui)
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
main.cpp
#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
int main (int argc, char * argv []) {
QApplication app (argc, argv);
QWidget widget;
widget.resize (640, 480);
widget.setWindowTitle ("Hello, world !!!");
QGridLayout * gridLayout = new QGridLayout (& widget);
QLabel * label = new QLabel ("Hello, world !!!");
label-> setAlignment (Qt :: AlignVCenter | Qt :: AlignHCenter);
gridLayout-> addWidget (label);
widget.show ();
return app.exec ();
}
This has been resolved for me in the meanwhile.
Solution was as follows:
Go to edit configurations
Add the Qt bin folder to Working directory
Hit OK and/or APPLY
Now I am able to run and build my Qt applications from within CLion directly.