Using CMake to Build Qt Projects

本文介绍了如何使用CMake作为构建工具来管理Qt项目的构建流程。通过与QMake的对比,文章详细阐述了CMake的基本用法及配置文件CMakeLists.txt的编写技巧,并展示了如何处理Qt特有的资源文件和UI文件。

 Qt comes with the QMake tool for handling cross platform building issues.However, there are other build systems available such as autotools, SCons andCMake. These tools meet different criterias, for example external dependencies.

When the KDE project shifted from Qt 3 to Qt 4 the project changed build toolfrom autotools to CMake. This has given CMake a special position in the Qtworld &emdash; both from the number of users point and from a featuresupport and quality point. Seen from a workflow point of view, Qt Creatorsupports CMake since version 1.1 (1.3 if you want to use a Microsoft toolchain).

A Basic Example

In this article we will focus on CMake itself, and how to use it in conjunctionwith Qt. To do this, let's start with an overview of a simple, but typicalCMake-based project. As you can tell from the listing below, the projectconsists of some source files and a text file.

$ ls
CMakeLists.txt
hellowindow.cpp
hellowindow.h
main.cpp

Basically, the CMakeLists.txt file replaces the projectfile used by QMake. Tobuild the project, create a build directory and run cmake and then make fromthere. The reason for creating a build directory is that CMake has been builtwith out-of-source building in mind from the very start. It is possible toconfigure QMake to place intermediate files outside the source, but it requiresextra steps. With CMake, it is the default.

$ mkdir build
$ cd build
$ cmake .. && make


CMake building a basic project.

The argument given to CMake refers to the directory where the CMakeLists.txtfile resides. This file controls the whole build process. In order to fullyunderstand it, it is important to recognize how the build process looks.The figure below shows how the user files: sources, headers, forms and resourcefiles are processed by the various Qt code generators before joining thestandard C++ compilation flow. Since QMake was designed to handle this flow, ithides all the details of this flow.


The Qt build system.

When using CMake, the intermediate steps must be handled explicitly. This meansthat headers withQ_OBJECT macros must be run through moc, user interface formsmust be processed by uic and resource files must pass through rcc.

In the example that we started with the world is slightly easier, though. It is limited to a single header file that needs to meet moc. But first, theCMakeLists.txt defines a project name and includes the Qt4 package as a required component.

PROJECT(helloworld)
FIND_PACKAGE(Qt4 REQUIRED)

Then all sources involved in the build process are assigned to two variables.The SET command assigns the variable listed first with the values that follow.The names,helloworld_SOURCES andhelloworld_HEADERS, is by convention. You canname them either way you like.

SET(helloworld_SOURCES main.cpp hellowindow.cpp)
SET(helloworld_HEADERS hellowindow.h)

Notice that the headers only include the headers that needs to be processed by moc. All other headers can be left out of the CMakeLists.txt file. This alsoimplicates that if you add aQ_OBJECT macro to any of your classes you must ensure that it is listed here.

To invoke moc, the macro QT4_WRAP_CPP is used. It assigns the names of the resulting files to the variable listed first. In this case the line looks as follows.

QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS})

What happens is that all headers are processed by moc and the names of theresulting source files are listed in thehelloworld_HEADERS_MOC variable. Again,the variable name is by convention rather than forced.

In order to build a Qt application, the Qt include directories needs to be added as well as a range of defines need to be set. This is handled through the commandsINCLUDE andADD_DEFINITIONS.

INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})

Finally, CMake needs to know the name of the resulting executable and what tolink it to. This is conveniently handled by by the commandsADD_EXECUTABLE and TARGET_LINK_LIBRARIES. Now CMake knows what to build, from what and through which steps.

ADD_EXECUTABLE(helloworld ${helloworld_SOURCES} 
    ${helloworld_HEADERS_MOC})
TARGET_LINK_LIBRARIES(helloworld ${QT_LIBRARIES})

When reviewing the listing above, it relies on a number of variables startingwith QT_. These are generated by the Qt4 package. However, as a developer, youmust explicitly refer to them as CMake is not build as tightly to suite Qt asQMake.

Adding More Qt

Moving beyond the initial example, we now look at a project with both resourcesand user interface forms. The resulting application will look quite similar toits predecessor, but all the magic takes place under the hood.

The CMakeLists.txt file start by naming the project and including the Qt4package - the complete file can be downloaded as a source code packageaccompanying this article. Then all the input files are listed and assigned totheir corresponding variables.

SET(helloworld_SOURCES main.cpp hellowindow.cpp)
SET(helloworld_HEADERS hellowindow.h)
SET(helloworld_FORMS hellowindow.ui)
SET(helloworld_RESOURCES images.qrc)

The new file types are then handled by QT4_WRAP_UI and QT4_ADD_RESOURCES. Thesemacros operate in the same ways asQT4_WRAP_CPP. This means that the resultingfiles are assigned to variable given as the left-most argument. Notice that theheader files generated by uic are needed as we need to build a dependencyrelationship between them and the final executable. Otherwise they will not becreated.

QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS})
QT4_WRAP_UI(helloworld_FORMS_HEADERS ${helloworld_FORMS})
QT4_ADD_RESOURCES(helloworld_RESOURCES_RCC ${helloworld_RESOURCES})

All the resulting files are then added as dependencies to the ADD_EXECUTABLEmacro. This includes the uic generated headerfiles. This establishes thedependency from the executable to the hellowindow.ui file through theintermediary ui_hellowindow.h header.

ADD_EXECUTABLE(helloworld ${helloworld_SOURCES} 
    ${helloworld_HEADERS_MOC} 
    ${helloworld_FORMS_HEADERS} 
    ${helloworld_RESOURCES_RCC})

Before this file can be used to build the project there is a small caveat tohandle. As all intermediate files are generated outside the source tree, theheader file generated by uic will not be located by the compiler. In order tohandle this, the build directory needs to be added to the list of include directories.

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})

With this line, all intermediary files will be available in the include path.

Qt Modules

Until now we have relied on the QtCore and QtGui modules. To be able to use moremodules, the CMake environment must be tuned to enable them. By setting them toTRUE using the SET command, the included modules can be controlled.

For instance, to enable OpenGL support add the following line to yourCMakeLists.txt.

SET(QT_USE_QTOPENGL TRUE)

The most commonly used modules are controlled using the following variables.

  • 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

In addition to these, the variable QT_DONT_USE_QTGUI can be used to disable theuse to QtGui. There is a similar variable to disable QtCore, but that is more tobe feature complete than to actually add much useful value.

Added Value and Complexity

It is not as trivial to use CMake as QMake, but the rewards are more features.The most notable point when moving from QMake is CMake's built in support forout-of-source builds. It can really change habits, and thus make versioning codemuch easier.

It is also possible to add conditionals for various platforms and buildscenarios. For instance, use different libraries for different platforms, aswell as tuning the same project differently for different situations.

Other powerful features are the ability to generate multiple executables andlibraries in one build as well as using said executables and libraries in thesame build. This, in combination with the QtTest module can handle complex buildsituations from a single configuration.

The choice between CMake and QMake is really quite easy. For straight forward Qtprojects, QMake is the obvious choice. When the build requirements passes thecomplexity threshold for QMake, CMake can take its place. With Qt Creator'ssupport for CMake, the same tools can still be used.


linkwebsite http://developer.qt.nokia.com/quarterly/view/using_cmake_to_build_qt_projects



<think>我们正在讨论CMake中的Kits配置。根据引用内容,我们可以从多个角度来理解如何配置和使用额外的Kits环境。首先,引用[1]提到在QtCreator中配置CMake路径的位置:Tools|Options|Kits|CMake。这告诉我们,在QtCreator中,Kits的配置是集成在IDE的设置中的。引用[2]提到在VSCode中可以通过命令面板(ctrl+shift+p)输入CMake:Build,并且可以配置预设的编译器环境,或者让CMake自动检测。引用[3]则介绍了CMakePresets.json和CMakeSettings.json两种配置文件,并指出CMakePresets.json是更推荐的标准配置方式。引用[4]和[5]则提供了关于使用CMake构建Qt项目的一些经验,包括在QtCreator中创建项目然后迁移到其他IDE(如CLion)的建议。现在,结合用户之前的问题和回答,我们重点讨论如何在CMake环境中添加或配置额外的工具套件(Kits)。根据之前的回答,我们知道在VSCode中可以通过编辑`cmake-tools-kits.json`文件来添加自定义Kits。此外,我们还可以通过CMakePresets.json来配置预设。下面,我将分步骤说明如何在不同的环境中配置和使用额外的Kits环境。###一、在VSCode中使用CMakeTools扩展配置Kits1.**打开Kits配置文件**:-Linux/macOS:`~/.local/share/CMakeTools/cmake-tools-kits.json`-Windows:`%APPDATA%\Code\User\cmake-tools-kits.json`2.**添加自定义Kit**:在`cmake-tools-kits.json`文件中添加一个对象,指定名称、编译器路径、环境变量或工具链文件等。例如:```json[{"name":"GCC12","compilers":{"C":"/usr/bin/gcc-12","CXX":"/usr/bin/g++-12"}},{"name":"ARMToolchain","toolchainFile":"${workspaceFolder}/arm-toolchain.cmake"}]```3.**在VSCode中选择Kit**:-点击底部状态栏的Kit名称,然后从列表中选择自定义的Kit。-或者通过命令面板执行`CMake:SelectaKit`。###二、使用CMakePresets.json配置预设(推荐)CMake3.20及以上版本支持`CMakePresets.json`文件,它允许我们在项目中定义多个配置预设(包括Kit信息)。这样,配置可以在不同开发环境之间共享。1.**创建`CMakePresets.json`文件**:在项目根目录下创建`CMakePresets.json`,例如:```json{"version":3,"configurePresets":[{"name":"linux-gcc","displayName":"GCConLinux","description":"UsingGCCcompilers","generator":"UnixMakefiles","binaryDir":"${sourceDir}/build/${presetName}","cacheVariables":{"CMAKE_C_COMPILER":"/usr/bin/gcc-12","CMAKE_CXX_COMPILER":"/usr/bin/g++-12"},"environment":{"PATH":"/custom/path:${env:PATH}"}},{"name":"arm-cross-compile","displayName":"ARMCrossCompile","toolchainFile":"${sourceDir}/arm-toolchain.cmake"}],"buildPresets":[{"name":"linux-gcc-debug","configurePreset":"linux-gcc","configuration":"Debug"}]}```2.**在IDE中使用预设**:-VSCode的CMakeTools扩展会自动检测项目中的`CMakePresets.json`文件,并在状态栏显示预设列表供选择。-VisualStudio2019及更高版本也支持`CMakePresets.json`,可以直接加载预设。###三、在QtCreator中配置Kits1.**打开QtCreator的设置**:`Tools>Options>Kits`。2.**在Kits选项卡中**,可以添加新的Kit,指定设备类型、编译器、CMake路径等。3.**在CMake选项卡中**,可以指定CMake的路径(如果系统中有多个CMake版本)。###四、在CLion中配置KitsCLion使用CMake作为默认构建系统,其Kit配置通过CMake设置实现:1.打开`File>Settings>Build,Execution,Deployment>CMake`。2.在`CMakeprofiles`中,可以添加多个配置,每个配置可以指定:-构建类型(Debug/Release等)-环境变量-CMake选项(如`-DCMAKE_C_COMPILER=...`)3.也可以使用`CMakePresets.json`(CLion2021.3及以上版本支持)。###五、共享配置为了在团队中共享配置,推荐使用`CMakePresets.json`文件,因为它可以被版本控制系统跟踪,并且被多个IDE(VSCode、VisualStudio、CLion等)支持。###六、验证配置在配置完成后,执行以下步骤验证:1.选择预设或Kit。2.执行CMake配置(例如在VSCode中运行`CMake:Configure`)。3.检查CMake输出,确认使用的编译器、工具链等是否符合预期。###注意事项-当同时存在`CMakePresets.json`和IDE特定的配置(如VSCode的`cmake-tools-kits.json`)时,`CMakePresets.json`具有更高优先级。-对于交叉编译,使用`toolchainFile`是标准做法。通过以上步骤,您可以在不同的开发环境中配置和使用额外的CMakeKits环境。§§相关问题§§1.如何在CMakePresets.json中配置多个构建预设?2.如何为不同的CMake预设指定不同的环境变量?3.在团队开发中如何统一管理CMakePresets.json文件?4.如何解决CMake工具链文件(toolchainfile)中的路径问题?</think>### 如何在 CMake 中配置和使用额外的 Kits 环境 #### 一、核心配置方法 1. **VSCode 配置 (推荐)** - 编辑 `cmake-tools-kits.json` 文件: ```json [ { "name": "ARM-Cross-Compiler", "compilers": { "C": "/opt/arm-gcc/bin/arm-gcc", "CXX": "/opt/arm-gcc/bin/arm-g++" }, "environmentVariables": { "PATH": "/opt/arm-gcc/bin:${env:PATH}" } }, { "name": "Qt-6.5-Kit", "toolchainFile": "${workspaceFolder}/qt6-toolchain.cmake" } ] ``` - 关键参数说明: - `name`: Kit 的显示名称 - `compilers`: 指定 C/C++ 编译器路径 - `toolchainFile`: 跨平台编译时使用的 CMake 工具链文件 - `environmentVariables`: 自定义环境变量 2. **Qt Creator 配置** - 路径: `Tools > Options > Kits > CMake` - 添加 CMake 路径和编译器: ```plaintext CMake Path: /usr/bin/cmake Compiler: GCC (x86 64bit in /usr/bin) ``` - 支持同时配置多个 Kit 用于不同目标平台[^1] 3. **标准配置 (CMakePresets.json)** - 创建 `CMakePresets.json` (CMake 3.20+): ```json { "version": 3, "configurePresets": [ { "name": "linux-gcc", "displayName": "GCC 12 on Linux", "generator": "Unix Makefiles", "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "/usr/bin/gcc-12", "CMAKE_CXX_COMPILER": "/usr/bin/g++-12" } }, { "name": "windows-msvc", "displayName": "Visual Studio 2022", "generator": "Visual Studio 17 2022", "architecture": "x64" } ] } ``` #### 二、工作流程 1. **选择 Kit** - VSCode: 底部状态栏点击当前 Kit > 选择自定义 Kit - Qt Creator: `Projects > Build & Run > Kits` - CLI: `cmake --preset=linux-gcc` 2. **配置与构建** ```bash # 使用预设配置 cmake --preset=linux-gcc # 使用指定工具链 cmake -DCMAKE_TOOLCHAIN_FILE=qt6-toolchain.cmake ``` 3. **IDE 集成** - VSCode: 自动检测 `CMakePresets.json` - Visual Studio: 支持 `CMakePresets.json` 和 `CMakeSettings.json` - Qt Creator: 自动加载已配置的 Kits[^1][^4] #### 三、高级配置技巧 1. **Qt 项目集成** ```cmake # qt6-toolchain.cmake set(CMAKE_PREFIX_PATH "/opt/Qt/6.5.0/gcc_64") find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) ``` 在 Kit 中引用此文件实现自动 Qt 模块加载[^4] 2. **交叉编译配置** ```json { "name": "Raspberry-Pi", "toolchainFile": "${workspaceFolder}/pi-toolchain.cmake", "environmentVariables": { "PI_SYSROOT": "/opt/rpi/sysroot" } } ``` 3. **多配置管理** ```cmake # CMakeLists.txt set(CMAKE_CONFIGURATION_TYPES "Debug;Release;MinSizeRel") ``` #### 四、验证与调试 1. **检查活动 Kit** ```bash cmake --version # 输出: Using Qt 6.5.0 in /opt/Qt/6.5.0/gcc_64 ``` 2. **调试集成 (launch.json)** ```json { "name": "Debug with Qt Kit", "program": "${workspaceFolder}/build/app", "environment": [{"name": "QT_DEBUG_PLUGINS", "value": "1"}] } ``` #### 五、最佳实践 1. **版本控制** - 将 `CMakePresets.json` 纳入版本控制 - 忽略 IDE 特定文件 (如 `.vscode/`) 2. **团队共享** - 创建基础 Kit 模板 - 使用相对路径 `${workspaceFolder}` 3. **多平台支持** ```json { "name": "Cross-Platform", "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux" }, "cmakeExecutable": "/usr/bin/cmake" } ``` > 提示:对于 Qt 项目,建议先在 Qt Creator 创建基础配置再迁移到其他 IDE[^5],可减少 70% 的配置问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值