使用CMake构建/开始使用CMake

Getting started with CMake

开始使用CMake

CMake is a group of tools that allow to build, test, and package applications. Just like Qt, it is available on all major development platforms. It is also supported by various IDE's, including Qt Creator.

​CMake是一组允许构建、测试和打包应用程序的工具。和Qt一样,它也可以在所有主要的开发平台上使用。它还受到各种IDE的支持,包括Qt Creator。

In this section we will show the most basic way to use Qt in a CMake project. First, we create a basic console application. Then, we extend the project into a GUI application that uses Qt Widgets.

​在本节中,我们将展示在CMake项目中使用Qt的最基本方法。首先,我们创建一个基本的控制台应用程序。然后,我们将该项目扩展为一个使用Qt Widgets的GUI应用程序。

Building a C++ console application

构建C++控制台应用程序

CMake project is defined by files written in the CMake language. The main file is called CMakeLists.txt, and is usually placed in the same directory as the actual program sources.

CMake项目由用CMake语言编写的文件定义。主文件名为CMakeLists.txt,并且通常与实际程序源放在同一目录中。

Here is a typical CMakeLists.txt file for a console application written in C++ using Qt:

这是一个典型的CMakeLists.txr文件,用C++编写的控制台应用程序

cmake_minimum_required(VERSION 3.16)

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Core)
qt_standard_project_setup()

add_executable(helloworld
    main.cpp
)

target_link_libraries(helloworld PRIVATE Qt6::Core)

Let's go through the content.

让我们浏览一下内容。

cmake_minimum_required(VERSION 3.16)

cmake_minimum_required() specifies the minimum CMake version that the application requires. Qt itself requires at least CMake version 3.16. If you use a Qt that was built statically - the default in Qt for iOS and Qt for WebAssembly - you need CMake 3.21.1 or newer.

​cmake_minimum_required()指定应用程序所需的最小cmake版本。Qt本身至少需要CMake版本3.16。如果使用静态构建的Qt(iOS的默认Qt和WebAssembly的默认Qt),则需要CMake 3.21.1或更高版本。

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

project() sets a project name and the default project version. The LANGUAGES argument tells CMake that the program is written in C++.

project()设置项目名称和默认项目版本。LANGUAGES参数告诉CMake,程序是用C++编写的。

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Qt 6 requires a compiler supporting C++ version 17 or newer. Enforcing this by setting the CMAKE_CXX_STANDARDCMAKE_CXX_STANDARD_REQUIRED variables will let CMake print an error if the compiler is too old.

Qt 6需要支持C++ 17或更新的编译器。通过设置CMAKE_CXX_STANDARD强制执行此操作,CMAKE_CXX_STANDARD_REQUIRED变量将允许CMAKE在编译器太旧时打印错误。

find_package(Qt6 REQUIRED COMPONENTS Core)

This tells CMake to look up Qt 6, and import the Core module. There is no point in continuing if CMake cannot locate the module, so we do set the REQUIRED flag to let CMake abort in this case.

这将告诉CMake查找Qt 6,并导入Core模块。如果CMake找不到模块,那么继续下去就没有意义了,所以我们设置了REQUIRED标志,让CMake在这种情况下中止。

If successful, the module will set some CMake variables documented in Module variables. It furthermore imports the Qt6::Core target that we use below.

​如果成功,模块将设置模块变量中记录的一些CMake变量。它还导入了我们下面使用的Qt6::Core目标。

For find_package to be successful, CMake must find the Qt installation. There are different ways you can tell CMake about Qt, but the most common and recommended approach is to set the CMake cache variable CMAKE_PREFIX_PATH to include the Qt 6 installation prefix. Note that Qt Creator will handle this transparently for you.

​要使find_package成功,CMake必须找到Qt安装。有不同的方法可以告诉CMake有关Qt的信息,但最常见和推荐的方法是将CMake缓存变量CMake_PREFIX_PATH设置为包含Qt 6安装前缀。请注意,Qt Creator将为您透明地处理此问题。

qt_standard_project_setup()

The qt_standard_project_setup command sets project-wide defaults for a typical Qt application.

​qt_standard_project_setup命令为典型的qt应用程序设置项目范围内的默认值。

Among other things, this command sets the CMAKE_AUTOMOC variable to ON, which instructs CMake to automatically set up rules so that Qt's Meta-Object Compiler (moc) is called transparently, when required.

​除此之外,该命令将CMAKE_AUTOMOC变量设置为ON,指示CMAKE自动设置规则,以便在需要时透明地调用Qt的元对象编译器(moc)。

See qt_standard_project_setup's reference for details.

​有关详细信息,请参阅qt_standard_project_setup的参考。

add_executable(helloworld
    main.cpp
)

add_executable() tells CMake that we want to build an executable (so not a library) called helloworld as a target. The target should be built from the C++ source file main.cpp.

add_executable()告诉CMake我们想要构建一个名为helloworld的可执行文件(所以不是库)作为目标。目标应该从C++源文件的main.cpp文件中构建。

Note that you typically do not list header files here. This is different from qmake, where header files need to be explicitly listed so that they are processed by the Meta-Object Compiler (moc).

​请注意,这里通常不列出头文件。这与qmake不同,qmake需要显式列出头文件,以便元对象编译器(Meta-Object Compiler,moc)处理它们。

For less trivial projects, you may want to call qt_add_executable() instead. It is a wrapper around the built-in add_executable() command, providing additional logic to automatically handle things like linking of Qt plugins in static Qt builds, platform-specific customization of library names and so on.

​对于不那么琐碎的项目,您可能需要调用qt_add_executable()。它是内置add_executable()命令的包装器,提供额外的逻辑来自动处理静态Qt构建中的Qt插件链接、特定于平台的库名称定制等事情。

target_link_libraries(helloworld PRIVATE Qt6::Core)

Finally, target_link_libraries tells CMake that the helloworld executable makes use of Qt Core by referencing the Qt6::Core target imported by the find_package() call above. This will not only add the right arguments to the linker, but also makes sure that the right include directories, compiler definitions are passed to the C++ compiler. The PRIVATE keyword is not strictly necessary for an executable target, but it is good practice to specify it. If helloworld was a library rather than an executable, then either PRIVATE or PUBLIC should be specified (PUBLIC if the library mentions anything from Qt6::Core in its headers, PRIVATE otherwise).

​最后,target_link_libraries告诉CMake,helloworld可执行文件通过引用上面的find_package()调用导入的Qt6::Core目标来使用Qt Core。这将不仅为链接器添加正确的参数,而且确保权限包括目录、编译器定义传递给C++编译器。对于可执行目标来说,PRIVATE关键字并不是绝对必要的,但是指定它是一种很好的做法。如果helloworld是一个库而不是一个可执行文件,那么应该指定PRIVATE或PUBLIC(如果库在其头中提到Qt6::Core中的任何内容,则为PUBLIC,否则为PRIVATE)。

Building a C++ GUI application

构建C++ GUI应用程序

In the last section we showed the CMakeLists.txt file for a simple console application. We will now extend it to create a GUI application that uses the Qt Widgets module.

​在最后一节中,我们展示了CMakeLists.txt文件,一个简单的控制台应用程序。现在,我们将对其进行扩展,以创建一个使用Qt Widgets模块的GUI应用程序。

This is the full project file:

这是完整的项目文件:

cmake_minimum_required(VERSION 3.16)

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()

add_executable(helloworld
    mainwindow.ui
    mainwindow.cpp
    main.cpp
)

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

Let's walk through the changes we have made.

让我们浏览一下我们所做的更改。

find_package(Qt6 REQUIRED COMPONENTS Widgets)

In the find_package call, we replace Core with Widgets. This will locate the Qt6Widgets module and provide the Qt6::Widgets targets we later link against.

find_package调用中,我们将Core替换为Widgets。这将定位Qt6Widgets模块,并提供我们稍后链接的Qt6::Widgets目标。

Note that the application will still link against Qt6::Core, because Qt6::Widgets depends on it.

请注意,应用程序仍将链接到Qt6::Core,因为Qt6::Widgets依赖于它。

qt_standard_project_setup()

In addition to CMAKE_AUTOMOCqt_standard_project_setup sets the CMAKE_AUTOUIC variable to ON. This will automatically create rules to invoke Qt's User Interface Compiler (uic) on .ui source files.

​除了CMAKE_AUTOMOC之外,qt_standard_project_setup还将CMAKE_AUTOUIC变量设置为ON。这将自动创建规则以在上调用Qt的用户界面编译器(uic)转换ui源文件。

add_executable(helloworld
    mainwindow.ui
    mainwindow.cpp
    main.cpp
)

We add a Qt Designer file (mainwindow.ui) and its corresponding C++ source file (mainwindow.cpp) to the application target's sources.

​我们将一个qt设计器文件(mainwindow.ui)及其相应的C++源文件(mainwindow.cpp)添加到应用程序目标的源代码中。

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

In the target_link_libraries command, we link against Qt6::Widgets instead of Qt6::Core.

在target_link_libraries命令中,我们链接Qt6::Widgets,而不是Qt6::Core。

set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

Finally, we set properties on our application target with the following effects:

最后,我们在应用程序目标上设置属性,具有以下效果:

  • Prevent the creation of a console window on Windows.
  • 防止在Windows上创建控制台窗口。
  • Create an application bundle on macOS.
  • 在macOS上创建应用程序包。

See the CMake Documentation for more information about these target properties.

​有关这些目标属性的更多信息,请参阅CMake文档。

Structuring projects

构建项目

Projects that contain more than just one target will benefit from a clear project file structure. We will use CMake's subdirectory feature.

​包含多个目标的项目将受益于清晰的项目文件结构。我们将使用CMake的子目录功能。

As we plan to extend the project with more targets, we move the source files of the application into a subdirectory and create a new CMakeLists.txt in there.

当我们计划用更多的目标扩展项目时,我们将应用程序的源文件移动到一个子目录中,并创建一个新的CMakeLists.text在那里。

<project root>
├── CMakeLists.txt
└── src
    └── app
        ├── CMakeLists.txt
        ├── main.cpp
        ├── mainwindow.cpp
        ├── mainwindow.h
        └── mainwindow.ui

The top-level CMakeLists.txt contains the overall project setup, find_package and add_subdirectory calls:

顶级CMakeLists.txt包含整个项目设置、find_packageadd_subdirectory调用:

cmake_minimum_required(VERSION 3.16)

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()

add_subdirectory(src/app)

Variables that are set in this file are visible in subdirectory project files.

在此文件中设置的变量在子目录项目文件中可见。

The application's project file src/app/CMakeLists.txt contains the executable target:

应用程序的项目文件src/app/CMakeLists.txt包含可执行目标:

add_executable(helloworld
    mainwindow.ui
    mainwindow.cpp
    main.cpp
)

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)
Such a structure will make it easy to add more targets to the project such as libraries or unit tests.

这样的结构可以很容易地向项目中添加更多目标,例如库或单元测试。

Building libraries

构建库

As the project grows, you may want to turn parts of your application code into a library that is used by the application and possibly unit tests. This section shows how to create such a library.

随着项目的发展,您可能希望将应用程序代码的一部分转换为一个库,供应用程序和可能的单元测试使用。本节介绍如何创建这样的库。

Our application currently contains business logic directly in main.cpp. We extract the code into a new static library called businesslogic in the subdirectory "src/businesslogic" as explained in the previous section.

​我们的应用程序目前在main.cpp中直接包含业务逻辑。如前一节所述,我们将代码提取到子目录“src/businesslogic”中名为businesslogic的新静态库中。

For the sake of simplicity, the library consists of just one C++ source file and its corresponding header file that is included by the application's main.cpp:

为了简单起见,库只包含一个C++源文件及其相应的头文件,该文件由应用程序的main.cpp所包含:

<project root>
├── CMakeLists.txt
└── src
    ├── app
    │   ├── ...
    │   └── main.cpp
    └── businesslogic
        ├── CMakeLists.txt
        ├── businesslogic.cpp
        └── businesslogic.h

Let's have a look at the library's project file (src/businesslogic/CMakeLists.txt).

让我们看一下库的项目文件(src/businesslogic/CMakeLists.txt)。

add_library(businesslogic STATIC
    businesslogic.cpp
)
target_link_libraries(businesslogic PRIVATE Qt6::Core)
target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

Let's go through the content.

让我们浏览一下内容。

add_library(businesslogic STATIC
    businesslogic.cpp
)

The add_library command creates the library businesslogic. Later, we will let the application link against this target.

​add_library命令创建库businesslogic。稍后,我们将让应用程序链接到此目标。

The STATIC keyword denotes a static library. If we wanted to create a shared or dynamic library, we would use the SHARED keyword.

STATIC关键字表示静态库。如果我们想创建一个共享的或动态的库,我们会使用shared关键字。

target_link_libraries(businesslogic PRIVATE Qt6::Core)

We have a static library and don't actually have to link other libraries. But as our library uses classes from QtCore, we add a link dependency to Qt6::Core. This pulls in the necessary QtCore include paths and preprocessor defines.

我们有一个静态库,实际上不需要链接其他库。但是,由于我们的库使用来自QtCore的类,我们向Qt6::Core添加了一个链接依赖项。这将引入必要的QtCore include路径和预处理器定义。

target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

The library API is defined in the header file businesslogic/businesslogic.h. By calling target_include_directories, we make sure that the absolute path to the businesslogic directory is automatically added as an include path to all targets using our library.

​库API在头文件businesslogic/businesslogic.h中定义。 通过调用target_include_directories,我们确保businesslogic目录的绝对路径自动添加为使用我们的库的所有目标的包含路径。

This frees us in main.cpp from using relative paths to locate businesslogic.h. Instead, we can just write

这让我们基本理解了main.cpp使用相对路径来定位businesslogic.h。 相反,我们可以直接写

#include <businesslogic.h>

Last, we must add the library's subdirectory to the top-level project file:

最后,我们必须将库的子目录添加到顶级项目文件中:

add_subdirectory(src/app)
add_subdirectory(src/businesslogic)

Using libraries

使用库

To use the library we created in the previous section, we instruct CMake to link against it:

​要使用我们在上一节中创建的库,我们将指示CMake与它进行链接:

target_link_libraries(helloworld PRIVATE
    businesslogic
    Qt6::Widgets)

This ensures that businesslogic.h is found when main.cpp is compiled. Furthermore, the businesslogic static library will become a part of the helloworld executable.

这确保了businesslogic.h是在main.cpp编译时找到。此外,businesslogic静态库将成为helloworld可执行文件的一部分。

In CMake terms, the library businesslogic specifies usage requirements (the include path) that every consumer of our library (the application) has to satisfy. The target_link_libraries command takes care of that.

在CMake术语中,库businesslogic指定usage requirements (the include path),确保每个使用者必须满足的使用要求(包含路径)。target_link_libraries命令会处理这个问题。

Adding resources

增加资源

We want to display some images in our application, so we add them using the Qt Resource System.

​我们希望在应用程序中显示一些图像,所以我们使用Qt资源系统添加它们。

qt_add_resources(helloworld imageresources
    PREFIX "/images"
    FILES logo.png splashscreen.png
)

The qt_add_resources command automatically creates a Qt resource containing the referenced images. From the C++ source code, you can access the images by prepending the specified resource prefix:

​qt_add_resources命令自动创建包含引用图像的qt资源。从C++源代码中,可以通过预先指定指定的资源前缀来访问图像:

​
logoLabel->setPixmap(QPixmap(":/images/logo.png"));

The qt_add_resources command takes as the first argument either a variable name or a target name. We recommend to use the target-based variant of this command as shown in the example above.

​qt_add_resources命令将变量名或目标名作为第一个参数。我们建议使用该命令的基于目标的变量,如上面的示例所示。

Adding translations

添加翻译

Translations of strings in a Qt project are encoded in .ts files. See Internationalization with Qt for details.

​Qt项目中字符串的翻译编码为.ts文件。有关详细信息,请参阅Qt国际化。

To add .ts files to your project, use the qt_add_translations command.

​将.ts文件添加到项目中,请使用qt_add_translations命令。

The following example adds a German and a French translation file to the helloworld target:

以下示例将德语和法语翻译文件添加到helloworld目标:

qt_add_translations(helloworld
    TS_FILES helloworld_de.ts helloworld_fr.ts)

This creates build system rules to automatically generate .qm files from the .ts files. By default, the .qm files are embedded into a resource and are accessible under the "/i18n" resource prefix.

这将创建生成系统规则,从ts文件自动生成qm文件。默认情况下.qm文件嵌入到资源中,可以在“/i18n”资源前缀下访问。

To update the entries in the .ts file, build the update_translations target:

更新.ts文件文件条目,生成update_translations目标:

$ cmake --build . --target update_translations

To trigger the generation of the .qm files manually, build the release_translations target:

手动触发生成新的.qm文件,构建release_translations目标:

$ cmake --build . --target release_translations

For more information about how to influence the handling of .ts files and the embedding into a resource, see the qt_add_translations documentation.

​有关如何处理.ts文件和嵌入到资源中的更多信息,请参阅qt_add_translations文档。

The qt_add_translations command is a convenience wrapper. For more fine-grained control of how .ts files and .qm files are handled, use the underlying commands qt_add_lupdate and qt_add_lrelease.

​qt_add_translations命令是一个方便的包装器。对于如何进行更细粒度的控制.ts文件和.qm文件,如果要处理,请使用下面的命令qt_add_lupdate和qt_add_lrelease。

Further reading

扩展阅读

The official CMake Documentation is an invaluable source for working with CMake.

​CMake官方文档是使用CMake的宝贵资源。

The official CMake Tutorial covers common build system tasks.

​官方的CMake教程涵盖了常见的构建系统任务。

The book Professional CMake: A Practical Guide provides a great introduction to the most relevant CMake features.

​《专业CMake:实用指南》一书对最相关的CMake功能进行了很好的介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值