参见博客: 用CMake 构建Qt 项目
[C++/Qt] CMake et Qt
主要是QT5将qt库的相应模块进行了分离,必须将自己用到的模块分别添加进去,find_package(Qt5Widgets REQUIRED),find_package(Qt5Core REQUIRED) 等而qt4可以直接 FIND_PACKAGE(Qt4 REQUIRED) 找到相应的lib与include 路径。
在QTcreator 中使用完findpackage 就会顺着路径差找到对应的.cmake文件。打开就会找到设置的几个相应变量值,例如,${Qt5Widgets_INCLUDE_DIRS},${Qt5Widgets_LIBRARIES} ${Qt5Core_INCLUDE_DIRS} ${Qt5Core_LIBRARIES}${Qt5SerialPort_INCLUDE_DIRS}${Qt5SerialPort_LIBRARIES}
#find QT libraries find_package(Qt5Widgets REQUIRED) find_package(Qt5Core REQUIRED) find_package(Qt5Gui REQUIRED) find_package(Qt5SerialPort REQUIRED) SET(serialport_SOURCES ${treebot_SOURCE_DIR}/serialport/serialport.cpp) SET(serialport_HEADERS ${treebot_SOURCE_DIR}/serialport/serialport.h) QT5_WRAP_CPP(serialport_HEADERS_MOC ${serialport_HEADERS}) qt5_wrap_ui(UI_HEADERS ${treebot_SOURCE_DIR}/serialport/serialport.ui) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${LIBRARY_OUTPUT_PATH}) add_library( serialportLIB ${serialport_SOURCES} ${serialport_HEADERS_MOC} ${serialport_HEADERS} ${UI_HEADERS} ) TARGET_LINK_LIBRARIES(serialportLIB ${Qt5Core_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5SerialPort_LIBRARIES})
你可以通过变量输出形式查看对应的路径信息:(cmake时会看到)
message(" Qt5Widgets_INCLUDE_DIRS =${Qt5Widgets_INCLUDE_DIRS} ") message(" Qt5Widgets_LIBRARIES =${Qt5Widgets_LIBRARIES} ") message(" Qt5Core_INCLUDE_DIRS =${Qt5Core_INCLUDE_DIRS} ") message(" Qt5Core_LIBRARIES =${Qt5Core_LIBRARIES} ") message(" Qt5SerialPort_INCLUDE_DIRS =${Qt5SerialPort_INCLUDE_DIRS}") message(" Qt5SerialPort_LIBRARIES =${Qt5SerialPort_LIBRARIES}")
qt 编译一般采用的是qmake编译.pro文件。 要用cmake编译需要理解qmake的编译方式并依据相应的过程设置进行。
CMake中使用的参数代表指CMakeLists.txt文件所在的目录。这个CMakeLists.txt文件控制了整个编译的过程。为了更彻底地理解它,我们用以下这个图来看看整个编译的流程。下面这张图表明用户编写的文件(源代码,头文件,.ui文件,.qrc文件)在编译过程中是如何被Qt的工具进行处理,并整合到整个编译流程中的。因为qmake是用于处理这个流程的,它隐藏了这个流程中的很多细节。
Qt编译系统
当使用CMake的时候,这些中间过程必须要显式地进行处理。
在头文件中如果有使用Q_OBJECT宏的话,则这个文件需要被moc进行处理,
.ui文件也必须要由uic处理,
.qrc文件需要由rcc程序处理。
Q_OBJECT宏的作用
The Q_OBJECT macro at the beginning of the class definition is necessary for all classes that define signals or slots
只有加入了Q_OBJECT,你才能使用QT中的signal和slot机制。 Q_OBJECT宏使用注意事项
1) 含有Q_Object的头文件需要生成对应的moc文件;
SET(serialport_SOURCES ${AR_SOURCE_DIR}/serialport/main.cpp ${AR_SOURCE_DIR}/serialport/serialport.cpp) SET(serialport_HEADERS ${AR_SOURCE_DIR}/serialport/serialport.h) #serialport.h含有<span style="color:#FF0000;"><strong><span style="font-size:14px;">Q_OBJECT</span></strong></span> QT5_WRAP_CPP(serialport_HEADERS_MOC ${serialport_HEADERS})2) 生成了moc文件后,你要包含到工程中来。
add_executable(serialport ${serialport_SOURCES} ${serialport_HEADERS_MOC} ${serialport_HEADERS} ${UI_HEADERS} ) TARGET_LINK_LIBRARIES(serialport ${Qt5Core_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5SerialPort_LIBRARIES})
对.ui文件通过调用uic程序对其处理。 qt5_wrap_ui(UI_HEADERS ${AR_SOURCE_DIR}/serialport/serialport.ui)
.qrc文件及.ui文件通过宏 QT4_WRAP_UI 和 QT4_ADD_RESOURCES进行处理。这些宏与QT4_WRAP_CPP的宏的作用是一样的,实际上都是在编译过程中调用相应的应用程序对其进行处理。即针对.qrc文件通过调用rcc程序对其处理,对.ui文件通过调用uic程序对其处理。
这些中间生成的文件在最终生成应用程序的时候需要用到,因此,add_executable要将其添加进去。
add_executable(serialport ${serialport_SOURCES} ${serialport_HEADERS_MOC} ${serialport_HEADERS} ${UI_HEADERS} )在编译之前,还有一个问题要处理,如上所述,我们要进行的是在源代码之外 的编译,因此,这些生成的中间文件都会在build目录下,这样的话,编译器则不能定位由uic程序产生的诸如ui_serialport.h等文件。所以,我们需要把build目录添加到包含目录中,如下:
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
1) undefined reference to `vtable for ***
#这个错误是说你没有对包含有Q_Object的头文件没有生成对应的moc文件,或者是生成了moc文件,但是你没有给包含到工程中来。
2)
参考:http://www.kuqin.com/qtdocument/qapplication.html
QApplication 包含主事件循环,在其中来自窗口系统和其它资源的所有事件被处理和调度。它也处理应用程序的初始化和结束,并且提供对话管理。它也处理绝大多数系统范围和应用程序范围的设置。对于任何一个使用Qt的图形用户界面应用程序,都正好存在一个QApplication 对象,而不论这个应用程序在同一时间内是不是有0、1、2或更多个窗口。
需要调用这个函数来开始事件处理。主事件循环从窗口系统中接收事件并且把它们分派给应用程序窗口部件。
通常来说,在调用exec()之前,没有用户交互可以发生。作为一个特例,像QMessageBox这样的模式对话框可以在调用exec()之前使用,因为模式对话框调用exec()来开始本地事件循环。
为了使你的应用程序执行空闲处理,例如,只要没有未处理地事件,执行一个特殊的函数,使用QTimer,0超时。更高级的空闲处理方案可以使用processEvents()来完成。
cmake_minimum_required(VERSION 2.8) project(ARqtpnp) #find QT libraries find_package(Qt5Widgets REQUIRED) find_package(Qt5Core REQUIRED) find_package(Qt5Gui REQUIRED) find_package(Qt5SerialPort REQUIRED) SET(serialport_SOURCES ${AR_SOURCE_DIR}/serialport/main.cpp ${AR_SOURCE_DIR}/serialport/serialport.cpp) SET(serialport_HEADERS ${AR_SOURCE_DIR}/serialport/serialport.h) QT5_WRAP_CPP(serialport_HEADERS_MOC ${serialport_HEADERS}) # ADD_DEFINITIONS(${Qt5Core_DEFINITIONS}) # add_definitions(${Qt5Widgets_DEFINITIONS}) # add_definitions(${Qt5SerialPort_DEFINITIONS}) # INCLUDE_DIRECTORIES(${Qt5Widgets_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5SerialPort_INCLUDE_DIRS}) # INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) qt5_wrap_ui(UI_HEADERS ${AR_SOURCE_DIR}/serialport/serialport.ui) message(" Qt5Widgets_INCLUDE_DIRS =${Qt5Widgets_INCLUDE_DIRS} ") message(" Qt5Widgets_LIBRARIES =${Qt5Widgets_LIBRARIES} ") message(" Qt5Core_INCLUDE_DIRS =${Qt5Core_INCLUDE_DIRS} ") message(" Qt5Core_LIBRARIES =${Qt5Core_LIBRARIES} ") message(" Qt5SerialPort_INCLUDE_DIRS =${Qt5SerialPort_INCLUDE_DIRS}") message(" Qt5SerialPort_LIBRARIES =${Qt5SerialPort_LIBRARIES}") add_executable(serialport ${serialport_SOURCES} ${serialport_HEADERS_MOC} ${serialport_HEADERS} ${UI_HEADERS} ) TARGET_LINK_LIBRARIES(serialport ${Qt5Core_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5SerialPort_LIBRARIES}) ##这个错误是说你没有对包含有Q_Object的头文件没有生成对应的moc文件,或者是生成了moc文件,但是你没有给包含到工程中来。
利用
add_definitions:添加编译参数
>> add_definitions(-DDEBUG)将在gcc命令行添加DEBUG宏定义;
在CMakeLists.txt文件中
if(WIN32) ADD_DEFINITIONS(-DWINDOWS_H_) endif() if(UNIX) ADD_DEFINITIONS(-DUNIX_H_) endif()
#ifdef WINDOWS_H_ #include <windows.h> #endif #include <stdlib.h> #include <stdio.h> #ifdef UNIX_H_ #include <unistd.h> #endif
CMAKE的使用