StupidBeauty
Read times:2766Posted at:Fri Dec 20 20:21:53 2013
- no title specified

Qt文档翻译:使用CMake来构建Qt项目,Using CMake to Build Qt Projects

作者: Johan Thelin

Qt自带了QMake工具,用于处理跨平台的构建事项。然而,世界上还有其它的一些构建系统,例如autotools、SCons和CMake。这些工具各有特点,比如说有的工具可以更方便地处理外部依赖。

当KDE项目从Qt 3迁移到Qt 4时,也将构建工具从autotools迁移到了CMake。这就使得CMake在Qt的世界里拥有了一个特殊地位——这既是指用户数量的方面也是指功能和质量方面。从工作流的方面来看,Qt Creator从1.1版本开始就支持CMake了。

基本用法

在这篇文章里,我们将关注于CMake本身的功能,以及如何将它与Qt配套使用。让我们先来看看一个简单但是典型的基于CMake的项目。从下面的文件列表可以看出,该项目由多个源代码文件和一个文本文件组成。

$ ls

CMakeLists.txt

hellowindow.cpp

hellowindow.h

main.cpp

在这里,CMakeLists.txt这个文件取代了QMake所使用的项目文件。要构建这个项目,就创建一个构建目录,然后在那个目录里运行cmake和make。这里为什么要创建一个构建目录呢?因为CMake从一开始就被设计为要对项目进行“源代码目录”之外的构建。其实也可以让QMake将编译过程中的中间文件放置在源代码目录之外,但是这需要花费一些步骤来实现。而对于CMake 呢,这就是默认行为。

$ mkdir build

$ cd build

$ cmake .. && make

CMake所需要的参数就是CMakeLists.txt文件所在的目录的路径。这个文件控制着整个构建过程。为了能够完整地理解这个过程,就需要先了解一下构建过程的大致情况。下图展示的是,用户编写的各种文件(源代码、头文件、界面文件和资源文件)在参与标准的C++编译流程之前都被Qt 的各种代码生成器作了哪些处理。由于QMake就是设计用来处理这个流程的,所以,它隐藏了这个流程中的所有细节。

当使用CMake时,这些中间步骤都必须显式处理。也就是说,含有Q_OBJECT宏的头文件必须用moc处理,用户界面文件必须用uic处理,资源文件必须用rcc处理。

不过,我们最开始使用的这个示例比较简单。其中只有一个头文件是需要由moc处理的。不过还是要仔细看一下,首先,CMakeLists.txt中定义了一个项目名字,并且将Qt4软件包作为一个必需组件包含进来。

PROJECT(helloworld)

FIND_PACKAGE(Qt4 REQUIRED)

然后,所有牵涉到构建过程的源代码文件都被记录到两个变量中。SET命令用于对变量赋值,参数列表中第一个单词就表示变量名,之后所有的值都会进入这个变量的值列表中。这里所用的名字,helloworld_SOURCEShelloworld_HEADERS,只是按照习惯来取的。妳可以根据个人喜好来使用别的名字。

SET(helloworld_SOURCES main.cpp hellowindow.cpp)

SET(helloworld_HEADERS hellowindow.h)

注意,这里所说的头文件,仅仅指的是那些需要由moc处理的头文件。其它的头文件都不用包含在CMakeLists.txt文件里。这也表明,如果妳在自己的某些类里加了Q_OBJECT 这个宏,那么也要把它们的头文件加入到列表里。

要调用moc,就需要使用QT4_WRAP_CPP 这个宏。它的参数中第一个单词同样指的是变量名,它会将处理结果中的各个文件名赋值给第一个参数所表示的变量。在我们当前这个例子中,对应的代码就是下面这样的。

QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS})

这句代码将会导致,所有的头文件被moc处理一遍,所产生的对应源代码文件会以列表的形式记录在helloworld_HEADERS_MOC 变量中。同样地,变量名是按照惯例来取的,妳可以自由发挥。

要构建一个Qt程序,就需要把Qt的头文件包含目录加入到项目里,另外还需要设置一些定义(defines)。这两点是使用INCLUDE ADD_DEFINITIONS 命令来实现的。

INCLUDE(${QT_USE_FILE})

ADD_DEFINITIONS(${QT_DEFINITIONS})

最后,CMake需要知道最终产生的可执行程序的名字,以及要链接哪些库。这两点,可使用ADD_EXECUTABLE TARGET_LINK_LIBRARIES 命令来实现。现在,CMake知道要构建出一个什么东西,要使用哪些文件来构建,以及要做哪些步骤了。

ADD_EXECUTABLE(helloworld ${helloworld_SOURCES}

${helloworld_HEADERS_MOC})

TARGET_LINK_LIBRARIES(helloworld ${QT_LIBRARIES})

现在来回顾一下以上的代码,可以看到,其中依赖了几个以QT_开头的变量。这些变量是由Qt4软件包生成的。然而,作为一个开发者,妳必须显式地引用它们,因为CMake并不像QMake 那样是专为Qt 而设计的。

加入更多的Qt资源

让我们更进一步,创建一个包含了资源文件和用户界面文件的项目。所构建出来的程序与上面那个简单示例类似,但是我们还是需要做一些额外的工作。

CMakeLists.txt文件的开头,定义了项目的名字,包含了Qt4软件包——完整的文件可在这篇文章附带的源代码包里找到。然后,所有的输入文件都被列出,赋值给对应的变量。

SET(helloworld_SOURCES main.cpp hellowindow.cpp)

SET(helloworld_HEADERS hellowindow.h)

SET(helloworld_FORMS hellowindow.ui)

SET(helloworld_RESOURCES images.qrc)

这里新加入的两种类型的文件分别是由QT4_WRAP_UI QT4_ADD_RESOURCES 来处理的。这两个宏的工作原理是与QT4_WRAP_CPP一样的。也就是说,所产生的结果文件名列表会被赋值给最左边的那个参数对应的变量。注意,由uic 所产生的那些头文件也是必需的,因为我们需要在它们与最终的可执行程序之间建立一个依赖关系。否则它们就不会被创建。

QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS})

QT4_WRAP_UI(helloworld_FORMS_HEADERS ${helloworld_FORMS})

QT4_ADD_RESOURCES(helloworld_RESOURCES_RCC ${helloworld_RESOURCES})

所有的中间文件都已经加入进来作为ADD_EXECUTABLE 宏的依赖对象了。其中也包括由uic 生成的头文件。这就使得最终的可执行程序通过中间的ui_hellowindow.h 头文件来依赖hellowindow.ui 这个文件。

ADD_EXECUTABLE(helloworld ${helloworld_SOURCES}

${helloworld_HEADERS_MOC}

${helloworld_FORMS_HEADERS}

${helloworld_RESOURCES_RCC})

在妳开始使用这个文件进行构建之前,还需要注意做一件事情。因为所有的中间文件都是在源代码目录之外构建的,所以,编译器无法定位到uic所生成的头文件。对于这种情况,需要将构建目录本身加入到包含目录列表中去。

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})

有了这一行代码之后,所有的中间文件都会被找到了。

Qt模块

到目前为止,我们还只是依赖了QtCore和QtGui模块。要想使用更多的模块的话,就需要调整相应的CMake 环境变量。通过使用SET 命令来将相应的变量设置为TRUE,就可以引入对应的模块。

比如,要启用OpenGL 支持,只需要将以下这一行代码加入到CMakeLists.txt文件中。

SET(QT_USE_QTOPENGL TRUE)

最常见的模块是通过以下变量来控制的。

  • •. QT_USE_QTNETWORK

  • •. QT_USE_QTOPENGL

  • •. QT_USE_QTSQL

  • •. QT_USE_QTXML

  • •. QT_USE_QTSVG

  • •. QT_USE_QTTEST

  • •. QT_USE_QTDBUS

  • •. QT_USE_QTSCRIPT

  • •. QT_USE_QTWEBKIT

  • •. QT_USE_QTXMLPATTERNS

  • •. QT_USE_PHONON

除了以上变量之外,还可以使用QT_DONT_USE_QTGUI这个变量来明确地禁用QtGui。还有一个类似的变更可用来禁用QtCore,但是那个变量只是为了功能上的完备性而设计的,本身没有什么实际用处。

(这种迁移)所提升的价值和复杂性

使用CMake并不像使用QMake那么简单,但是妳能得到的好处就是拥有更多特性。最明显的好处就是,CMake内在地就支持“源代码之外”的构建。它确实可以改变一些不良习惯,也使得代码的版本维护更轻松。

还可以针对不同的平台及构建场景来加入一些条件。比如,在不同的平台上使用不同的库,或者在不同的情况下对同一个项目做不同的调整。

其它的强大功能包括:在一次构建过程中生成多个可执行程序;还可以在同一次构建中使用刚刚生成的可执行程序和库。这个功能,与QtTest 模块结合起来使用,就可以使用单个配置文件来处理非常复杂的构建场景。

究竟是选择CMake还是QMake?这其实很容易决定。对于只使用Qt的项目,显然应当使用QMake。当妳的项目复杂到超出QMake的能力时,就可以使用CMake了。因为Qt Creator本身就支持CMake,所以底层的工具是直接复用的。

咦 v这里还景笠苜人i平i仑口屋 !

赶紧空仓个箩少发口巴l

绿叶

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands