使用CMake构建Qt项目
- 由于要做新的GUI设计加入更多的功能,在windows上已经安装了QtCreator,不想在Ubuntu下再装一个,于是采用在windows下开发,拿到Linux下编译运行,故使用CMake构建Qt项目。
1.Qt中的qmake
- qmake可以利用源文件、头文件、qt的ui文件等生成各种不同类型的工程和工程需要的Makefile文件。
- pro文件,添加各种源文件,还可以设定平台相关的不同源文件,设置各种规则,利用qmake命令生成工程。
QT中编译三步走:
- qmake -project (用于创建.pro文件,将所有的文件编译成一个与平台无关的工程文件)
- qmake (读取本身的Qt设置,生成与库一致的相应的Makefile)
- make (根据生成的Makefile,将文件编译为二进制可执行程序)
2.CMake中的构建
-
CMake中使用的参数代表指CMakeLists.txt文件所在的目录。这个CMakeLists.txt文件控制了整个编译的过程。为了更彻底地理解它,我们用以下这个图来看看整个编译的流程。下面这张图表明用户编写的文件(源代码,头文件,.ui文件,.qrc文件)在编译过程中是如何被Qt的工具进行处理,并整合到整个编译流程中的。因为qmake是用于处理这个流程的,它隐藏了这个流程中的很多细节。
-
Qt 不是使用的“标准的” C++ 语言,而是对其进行了一定程度的“扩展”。这里我们从Qt新增加的关键字就可以看出来:signals、slots 或者 emit。所以有人会觉得 Qt 的程序编译速度慢,这主要是因为在 Qt 将源代码交给标准 C++ 编译器,如 gcc 之前,需要事先将这些扩展的语法去除掉。完成这一操作的就是 moc。
-
Qt中,如果一个类要使用信号/槽功能,就必须在其中声明Q_OBJECT。只有加入了Q_OBJECT,你才能使用QT中的signal和slot机制。
这时候,就必须在头文件派生类的时候,首先像下面那样引入Q_OBJECT宏:
class MyMainWindow : public QWidget
{
Q_OBJECT
…
} -
moc是QT的预编译器,用来处理代码中的slot,signal,emit,Q_OBJECT等。moc文件是对应的处理代码,也就是Q_OBJECT宏的实现部分
-
在头文件中如果有使用Q_OBJECT宏的话,则这个文件需要被moc进行处理,.ui文件也必须要由uic处理,.qrc文件需要由rcc程序处理。
3.具体构建过程
-
下面是我在windows下写的扫雷程序文件(包含.ui .qrc)
-
下面是CMakeList.txt的内容。
#cmake版本
cmake_minimum_required(VERSION 3.5.1)
#项目名称
project(Minesweeper)
#让cmake自动去寻找Qt5
FIND_PACKAGE(Qt5 COMPONENTS Widgets REQUIRED)
#采用C++11标准
set(CMAKE_CXX_STANDARD 11)
#添加所有的源文件
SET(Minesweeper_SOURCES
dialog.cpp
main.cpp
mainwindow.cpp
minemap.cpp
myitem.cpp
myscene.cpp
setpro.cpp
)
#添加所有的头文件
SET(Minesweeper_HEADERS
dialog.h
mainwindow.h
minemap.h
myitem.h
myscene.h
setpro.h
)
#添加所有的.ui文件
SET(Minesweeper_FORMS
dialog.ui
mainwindow.ui
setpro.ui
)
#添加资源文件
SET(Minesweeper_RESOURCES
img.qrc
)
#调用预编译器moc,需要使用 QT5_WRAP_CPP宏
QT5_WRAP_CPP(Minesweeper_HEADERS_MOC ${Minesweeper_HEADERS})
#使用uic处理.ui文件
QT5_WRAP_UI(Minesweeper_FORMS_HEADERS ${Minesweeper_FORMS})
#使用rcc处理.qrc文件
QT5_ADD_RESOURCES(Minesweeper_RESOURCES_RCC ${Minesweeper_RESOURCES})
#这些生成的中间文件都会在build目录下,这样的话,编译器则不能定位由uic程序产生的诸如_ui_mainwindow.h等文件。所以,我们需要把build目录添加到包含目录中
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
#生成可执行文件
ADD_EXECUTABLE(Minesweeper
${Minesweeper_SOURCES}
${Minesweeper_HEADERS_MOC}
${Minesweeper_FORMS_HEADERS}
${Minesweeper_RESOURCES_RCC}
)
#为target添加需要链接的共享库
TARGET_LINK_LIBRARIES(Minesweeper ${Qt5Widgets_LIBRARIES})
- 下面是build的结果:
- 下面是运行之后的结果:
4.结尾
- 有了上面的构建,也可以完成其他资源的添加,结合新的底层就可以开发出好的界面和功能了。