Podczas tworzenia projekt w Qt4 z poziomu QtCreatora, do budowania projektu (generowania plików Makefile i tak dalej) QtCreator używa narzędzia qmake. Okazuje się jednak, że to nie wszystko:) QtCreator potrafi także używać CMake! Niestety nie ma póki co gotowego narzędzia, które automatycznie przekonwertuje projekt z qmake na CMake. Możemy jednak zrobić to sami. Jak? O tym jest właśnie ten tutorial.
Tworzymy CMakeLists.txt
Na sam początek warto wiedzieć, że sercem CMake jest plik CMakeLists.txt
. To w nim definiowane są zasady, jakie biblioteki trzeba znaleźć i dołączyć, które pliki zbudować itd.
W pierwszym kroku trzeba zatem utworzyć plik CMakeLists.txt
. Dodajemy go w głównym katalogu projektu. Natomiast folder wyżej (ponad źródłami i plikiem CMakeLists.txt
) warto stworzyć dodatkowy folder, w którym będzie budowany nasz program.
Oto wersja pierwsza przykładowego pliku CMakeLists.txt
– oferuje automatyczne wyszukiwanie plików ui i moc i generowanie na tej podstawie kodu. Odpowiadają za to zmienne: CMAKE_AUTOMOC
i CMAKE_AUTOUIC
.
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) PROJECT(V1) set(QT_SRC ${QT_SRC} "${PROJECT_SOURCE_DIR}") https://wiki.qt.io/Using_CMake_build_system FIND_PACKAGE(Qt4 REQUIRED QtGui QtXml) INCLUDE(${QT_USE_FILE}) QT4_WRAP_UI(UISrcs mainwindow.ui) QT4_WRAP_CPP(MOCSrcs mainwindow.h) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${QT_SRC}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/gui) add_executable(DemoQt ${PROJECT_SOURCE_DIR}/main.cpp mainwindow) TARGET_LINK_LIBRARIES(DemoQt Qt4::QtGui Qt4::QtXml)
Aby wypisać wartości zmiennych, warto użyć polecenia MESSAGE
, np.:
MESSAGE("MyProjectLib_src:\t\t${MyProjectLib_src}")
Moje wartości zmiennych są zatem następujące:
MOCSrcs | /home/d9k/ProstyProjektQtCmake/qponiższytcreator-build/moc_mainwindow.cxx |
MOCSrcs | /home/d9k/ProstyProjektQtCmake/qtcreator-build/ui_mainwindow.h |
QT_SRC | /home/d9k/ProstyProjektQtCmake/zrodla |
PROJECT_SOURCE_DIR | /home/d9k/ProstyProjektQtCmake/zrodla |
QT_USE_FILE | /usr/share/cmake-2.8/Modules/UseQt4.cmake |
CMAKE_CURRENT_SOURCE_DIR | /home/d9k/ProstyProjektQtCmake/zrodla |
CMAKE_CURRENT_BINARY_DIR | /home/d9k/ProstyProjektQtCmake/qtcreator-build |
QT_LIBRARIES | /usr/lib/x86_64-linux-gnu/libQtGui.so;/usr/lib/x86_64-linux-gnu/libQtCore.so |
Okazuje się jednak, że używanie automatu nie zawsze jest dobre – zwłaszcza, jeśli projekt jest rozbudowany i struktura katalogów jest drzewiasta. Wzorując się na poniższych wpisach w serwisie StackOverflow, udało mi się zmodyfikować poprzednią wersję, aby nie używała automatycznego przypisywania plików ui
i moc
.
Przechodzimy na sterowanie manualne
Usuwamy zatem fragment ze zmiennymi CMAKE_AUTOMOC
i CMAKE_AUTOUIC
, by zastąpić go własnym wskazaniem ścieżek:
cmake_minimum_required (VERSION 2.8.7) set(CMAKE_VERBOSE_MAKEFILE ON) project (V2) find_package (Qt4 REQUIRED) set (MyProjectLib_src ${PROJECT_SOURCE_DIR}/mainwindow.cpp) set (MyProjectLib_hdr ${PROJECT_SOURCE_DIR}/mainwindow.h) set (MyProjectLib_ui ${PROJECT_SOURCE_DIR}/mainwindow.ui) set (MyProjectBin_src ${PROJECT_SOURCE_DIR}/main.cpp) QT4_WRAP_CPP(MyProjectLib_hdr_moc ${MyProjectLib_hdr}) QT4_WRAP_UI (MyProjectLib_ui_moc ${MyProjectLib_ui}) https://wiki.qt.io/Using_CMake_build_system INCLUDE(${QT_USE_FILE}) include_directories (${PROJECT_SOURCE_DIR}) include_directories (${PROJECT_BINARY_DIR}) add_library (MyProjectLib SHARED ${MyProjectLib_src} ${MyProjectLib_hdr_moc} ${MyProjectLib_ui_moc} ) target_link_libraries (MyProjectLib ${QT_LIBRARIES}) add_executable(MyProject ${MyProjectBin_src}) target_link_libraries (MyProject MyProjectLib)
Co natomiast kryje się pod ścieżkami w tym przypadku?
QT_USE_FILE | /usr/share/cmake-2.8/Modules/UseQt4.cmake |
PROJECT_SOURCE_DIR | /home/d9k/ProstyProjektQtCmake/zrodla |
PROJECT_BINARY_DIR | /home/d9k/ProstyProjektQtCmake/qtcreator-build |
QT_LIBRARIES | /usr/lib/x86_64-linux-gnu/libQtGui.so;/usr/lib/x86_64-linux-gnu/libQtCore.so |
MyProjectLib_hdr_moc | /home/d9k/ProstyProjektQtCmake/qtcreator-build/moc_mainwindow.cxx |
MyProjectLib_ui_moc | /home/d9k/ProstyProjektQtCmake/qtcreator-build/ui_mainwindow.h |
MyProjectLib_src | /home/d9k/ProstyProjektQtCmake/zrodla/mainwindow.cpp |
MyProjectLib_hdr | /home/d9k/ProstyProjektQtCmake/zrodla/mainwindow.h |
MyProjectLib_ui | /home/d9k/ProstyProjektQtCmake/zrodla/mainwindow.ui |
MyProjectBin_src | /home/d9k/ProstyProjektQtCmake/zrodla/main.cpp |
Warto zwrócić uwagę, że CMake wypisuje wartości w innej kolejności, niż podaliśmy w skrypcie.
Ważna rzecz: jeżeli wcześniej kombinowaliśmy z CMake i budowaliśmy projekt pod innymi nazwami (targetami), w QtCreatorze należy wybrać (w moim Qt Creatorze w wersji 2.4.1 w lewym, dolnym rogu), która konkretnie konfiguracja uruchamiania ma zostać włączona.
Źródła:
- https://cmake.org/Wiki/CMake/Tutorials/Qt
- https://wiki.qt.io/Using_CMake_build_system
- https://cmake.org/cmake/help/v3.0/module/FindQt4.html
- https://stackoverflow.com/questions/25989448/implementing-qt-project-through-cmake
- https://stackoverflow.com/questions/37151163/cmake-automoc-with-files-on-different-folders
- https://forum.qt.io/topic/38518/solved-qt-4-8-cmake-project
- http://www.vtk.org/Wiki/VTK/Tutorials/CMakeListsFileForQt4