原文:https://blog.csdn.net/qq_32768743/article/details/80056316 

写在前面的话:强烈建议优先阅读Qt官网文档对cmake的使用介绍——CMake Manual

前言
我去年用clion写Qt的时候,找了很多教程,也没有什么让我觉得很满意的。后来自己摸索,构建了一个我自己比较喜欢的方式。我的环境是Deepin 15.5。

在Deepin上,获取Qt环境最快的方式莫过于sudo apt install qtcreator-dde。它会帮你安装qt开发包,qt集成环境等。由于我自己非常喜欢JetBrains家的产品,如Intellij IDEA等,当它出了c++的IDE时,也非常希望能用JetBrains家的产品做Qt开发。我目前的环境是Clion 2018.1。

一个简单的案例
首先介绍一下创建一个Qt的工程,这和创建一个普通的C++工程是一样的。

接下来,我们进行Qt工程的改造。

目录结构

pikachu@pikachu-PC:~/src/Demo/QtDemo$ tree
.
├── CMakeLists.txt
└── src
├── CMakeLists.txt
└── main.cpp

把模板代码贴上

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(QtDemo)
add_subdirectory(src) src/CMakeLists.txt cmake_minimum_required(VERSION 3.7)
set(TARGET_NAME QtDemo)
set(CMAKE_CXX_STANDARD )
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
file(GLOB_RECURSE SOURCES "*.cpp")
file(GLOB_RECURSE HEADERS "*.h")
file(GLOB_RECURSE FORMS "*.ui")
file(GLOB_RECURSE RESOURCES "*.qrc")
find_package(PkgConfig REQUIRED)
set(QT Core Gui Widgets Network DBus Sql)
find_package(Qt5 REQUIRED ${QT})
pkg_check_modules(3rd_lib REQUIRED
dtkwidget dframeworkdbus
)
add_executable(${TARGET_NAME} ${SOURCES} ${HEADERS} ${FORMS} ${RESOURCES})
target_include_directories(${TARGET_NAME} PUBLIC ${3rd_lib_INCLUDE_DIRS} )
target_link_libraries(${TARGET_NAME} ${3rd_lib_LIBRARIES} )
qt5_use_modules(${TARGET_NAME} ${QT})
set(CMAKE_INSTALL_PREFIX /usr)
install(TARGETS ${TARGET_NAME} DESTINATION bin)

使用了DTK的模板代码

#include <DApplication>
#include <DUtil>
#include <DMainWindow>
#include <DWidgetUtil>
#include <DLog>
#include <zconf.h> DWIDGET_USE_NAMESPACE
DCORE_USE_NAMESPACE
int main(int argc, char *argv[]) {
DLogManager::registerConsoleAppender();
DLogManager::registerFileAppender();
DApplication::loadDXcbPlugin();
DApplication app(argc, argv);
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
const QString socket_path(QString("QtDemo_%1").arg(getuid()));
if (app.setSingleInstance(socket_path)) {
app.setTheme("light");
app.loadTranslator();
const QString descriptionText = QApplication::tr("A simple Qt Demo by CLion 2018.1 and CMake");
const QString acknowledgementLink = "https://github.com/PikachuHy";
app.setOrganizationName("pikachu");
app.setApplicationName("QtDemo");
app.setApplicationDisplayName(QObject::tr("Qt Demo"));
app.setApplicationVersion("1.0.0");
app.setProductName(QApplication::tr("Qt Demo"));
app.setApplicationDescription(descriptionText);
app.setApplicationAcknowledgementPage(acknowledgementLink); DMainWindow window;
window.setFixedWidth();
Dtk::Widget::moveToCenter(&window);
window.show();
return app.exec();
}
qDebug() << "app has started";
return ;
}

分析与解释

首先是目录结构,我是在根目录下又套了一个src目录,为什么这样做呢?

自然,这是有使用Qt的原因在的。Qt自己有一个moc编译器,会自动生成一些代码。下面的代码就是让Qt自动生成相关的代码,无需我们自己干预。

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

另一个是CLion本身的原因。CLion会为每个项目创建如cmake-build-debug这样的配置文件,而我常常是使用后缀名来匹配文件,如果不隔离,会导致函数重定义的问题。建立一个src目录可以很好的解决这个问题。搜索文件的代码如下

file(GLOB_RECURSE SOURCES "*.cpp")
file(GLOB_RECURSE HEADERS "*.h")
file(GLOB_RECURSE FORMS "*.ui")
file(GLOB_RECURSE RESOURCES "*.qrc")

通常,我们会用到Qt的很多模块,在cmake中怎么体现呢?我在寻找了很久后,发现了一个非常简洁的写法。你只需要在set(QT ...)这里添加你需要的模块即可。代码如下:

set(QT Core Gui Widgets Network DBus Sql)
find_package(Qt5 REQUIRED ${QT})
qt5_use_modules(${TARGET_NAME} ${QT})

嗯,看样子还是很好的。可是,使用C++,经常要用到的是它的生态,如何使用第三方库呢?在这里,我是这样定义的,先看代码:

find_package(PkgConfig REQUIRED)
pkg_check_modules(3rd_lib REQUIRED
dtkwidget dframeworkdbus
)
target_include_directories(${TARGET_NAME} PUBLIC ${3rd_lib_INCLUDE_DIRS} )
target_link_libraries(${TARGET_NAME} ${3rd_lib_LIBRARIES} )

我依赖了2个第三方的包,dtkwidget和dframeworkdbus,以及定义一个3rd_lib的变量,然后通过target_include_directories和target_link_libraries用在项目中。如果需要添加新的库,也仅仅是在pkg_check_modules(3rd_lib REQUIRED ...)中,写上你库的名字,非常方便。

如果你对QtCreator的配置文件.pro文件很熟悉的话,你会很惊讶的发现,我用CMake的写法和用pro文件的写法有诸多类似的地方。为什么呢?因为我常常需要在QtCreator和CLion两个IDE之间切换,以便我更好的利用两个IDE的优势,(QtCreator对Qt良好的支持,CLion对重构的良好支持)。

对CMakeLists.txt的介绍就到这里了,如果你对它的代码还有什么疑问,可以参考附录中的注释。

附:
CMakeLists.txt

# 需用使用的最小的CMake版本
cmake_minimum_required(VERSION 3.7)
# 本次构建的可执行文件名称
set(TARGET_NAME QtDemo)
# 本次使用C++标准版本
set(CMAKE_CXX_STANDARD )
# 字面意思,包含当前目录,可以方便开发
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# 开启Qt代码自动生成,不再需用自己手写了。按顺序,分别是`Q_OBJECT`宏展开,资源文件,界面文件。
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
# 简单粗暴的把源码搜集起来。按顺序,分别是实现文件,头文件,界面文件,资源文件
file(GLOB_RECURSE SOURCES "*.cpp")
file(GLOB_RECURSE HEADERS "*.h")
file(GLOB_RECURSE FORMS "*.ui")
file(GLOB_RECURSE RESOURCES "*.qrc")
# 使用第三方库需要用到的一个包
find_package(PkgConfig REQUIRED)
# 使用Qt的模块,写法和.pro文件类似
set(QT Core Gui Widgets Network DBus Sql)
find_package(Qt5 REQUIRED ${QT})
# 使用的第三方模块
pkg_check_modules(3rd_lib REQUIRED
dtkwidget dframeworkdbus
)
add_executable(${TARGET_NAME} ${SOURCES} ${HEADERS} ${FORMS} ${RESOURCES})
target_include_directories(${TARGET_NAME} PUBLIC ${3rd_lib_INCLUDE_DIRS} )
target_link_libraries(${TARGET_NAME} ${3rd_lib_LIBRARIES} )
# 在CMake中使用Qt最快捷的方式,一句代码搞定
qt5_use_modules(${TARGET_NAME} ${QT})
# 字面意思,安装文件的前缀
set(CMAKE_INSTALL_PREFIX /usr)
# 安装可执行文件
install(TARGETS ${TARGET_NAME} DESTINATION bin)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

# 项目名
PROJECT(VRVDZWDYWTX CXX) # 增加 QT 支持
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON) set(CMAKE_SKIP_BUILD_RPATH FALSE)
# 帮助信息
SET(${PROJECT_NAME}_HELP_MSG "\n编译选项:
cmake -DDDM_INSTALL_PREFIX=</absolute/path> \\
-DCOMMON_SRCS=<relative/path/from/current/to/common-ddm> \\
-DPLATFROM=<RUN_ON_UBUNTU|RUN_ON_FANGDE|RUN_ON_FANGDE32|RUN_ON_YINHE|RUN_ON_ZHONGBIAO|RUN_ON_ZBx86> \\
-DCMAKE_BUILD_TYPE=<Debug|Release>\\
<relative/path/to/${PROJECT_NAME}> ") # 检查相关设置
INCLUDE (../CommonCode.cmake) ## 检查变量是否定义
IF (NOT DEFINED COMMON_SRCS)
MESSAGE(FATAL_ERROR "COMMON-DDM 源码到该 build 目录的相对路径没有指定. ${${PROJECT_NAME}_HELP_MSG}")
ENDIF() ## COMMON_DDM 项目的源码路径
SET(COMMON_PATH ${CMAKE_BINARY_DIR}/${COMMON_SRCS}) ## 设置安装路径
IF (NOT DEFINED DDM_INSTALL_PREFIX)
GET_DEFUAT_INSTALL(DDM_INSTALL_PREFIX)
ENDIF() ## 检查目标平台
IF (NOT DEFINED PLATFROM)
MESSAGE(FATAL_ERROR "没有指定目标平台。${${PROJECT_NAME}_HELP_MSG}")
ENDIF()
GET_PLATFROM(${PLATFROM} TGT_PF ${${PROJECT_NAME}_HELP_MSG})
ADD_DEFINITIONS(-D${TGT_PF})
MESSAGE(STATUS "${PROJECT_NAME} 目标平台为:${TGT_PF}") ## RPATH 设置
GET_RPATH(${TGT_PF} ${PROJECT_NAME} TGT_RPATH ${${PROJECT_NAME}_HELP_MSG})
SET(CMAKE_INSTALL_RPATH "${TGT_RPATH}")
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
MESSAGE(STATUS "${PROJECT_NAME} RPATH 为:${TGT_RPATH}") # COMMON_DDM 项目的源码路径
SET(COMMON_PATH ${CMAKE_BINARY_DIR}/${COMMON_SRCS}) # 源文件列表
SET(${PROJECT_NAME}_SRC src/main.cpp
src/server.cpp
src/webinterface.cpp
${COMMON_PATH}/common/SoImport/SoImport.cpp
${COMMON_PATH}/common/common/common.cpp)
SET(${PROJECT_NAME}_HDR src/server.h
src/webinterface.h
${COMMON_PATH}/common/SoImport/SoImport.h
${COMMON_PATH}/common/common/common.h) # RPATH
SET(CMAKE_INSTALL_RPATH "${DDM_INSTALL_PREFIX}/lib/vrvlib")
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) # 可执行程序及依赖库
FIND_PACKAGE(Qt5Widgets CONFIG REQUIRED)
FIND_PACKAGE(Qt5Gui CONFIG REQUIRED)
FIND_PACKAGE(Qt5Network CONFIG REQUIRED)
FIND_PACKAGE(Qt5Xml CONFIG REQUIRED) ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SRC} ${${PROJECT_NAME}_HDR}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} Qt5::Widgets Qt5::Gui Qt5::Network Qt5::Xml)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} rt pthread) # 头文件路径
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${COMMON_PATH})
INCLUDE_DIRECTORIES(${COMMON_PATH}/common)
INCLUDE_DIRECTORIES(${COMMON_PATH}/libs) # Flags 选项
SET(CMAKE_CXX_FLAGS " -Wall")
SET(CMAKE_CXX_FLAGS_DEBUG " $ENV{CXXFLAGS} -O0 -Wall -g ") # 安装选项
INSTALL(TARGETS ${PROJECT_NAME}
DESTINATION ${DDM_INSTALL_PREFIX}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)

qt cmake的更多相关文章

  1. OpenCV+Qt+CMake安装+十种踩坑

    平台:win10 x64+opencv-3.4.1 + qt-x86-5.9.0 + cmake3.13.4 x64 OpenCV+Qt+CMake安装,及目前安装完后打包:mingw32-make时 ...

  2. 【linux学习笔记】在ubuntu下使用QT Cmake支持C++11

    今天在ubuntu下使用QT来进行C++编程,选择了Cmake,当用到initializer_list的时候提示不支持C++11,现提供一下解决方案: 错误提示: error: This file r ...

  3. 用CMake 构建Qt 项目

    译:用CMake构建Qt项目作者: Johan Thelin  译者:赖敬文原链接:http://developer.qt.nokia.com/quarterly/view/using_cmake_t ...

  4. Ubuntu 15.04 安装配置 Qt + SQLite3

    序 最近需要在Ubuntu下使用Qt开发项目,选择简单小巧的SQLite数据库,现将安装配置以及简单操作记录如下,以便日后查阅. 安装Qt CMake和Qt Creator是Linux下开发C++程序 ...

  5. windows10下vscode+cmake编译Qt5代码

    概述 本文演示环境: windows10 cmake version:3.18 qt version: 5.14 vscode version: 1.54.1 本文演示环境基于在线模式, 离线使用VS ...

  6. 浅谈 qmake 之 shadow build(就是将源码路径和构建路径分开)

    shadow build shadow build 是什么东西?就是将源码路径和构建路径分开(也就是生成的makefile文件和其他产物都不放到源码路径),以此来保证源码路径的清洁. 这不是qmake ...

  7. OBS源码编译开发

    本文来自网易云社区 作者:梁敏 OBS简介 OBS(Open Broadcaster Software)是免费开源的视频录制和直播软件,支持运行在windows,Mac和linux平台.官方链接 ht ...

  8. 《OpenCV图像处理编程实例》

    <OpenCV图像处理编程实例>例程复现 随书代码下载:http://www.broadview.com.cn/28573 总结+遇到的issue解决: 第一章 初识OpenCV 1.VS ...

  9. VS 2013编译64位版本QT 4.8.6及使用cmake为依赖QT生成VS项目时Could NOT find Qt4

    对于一些已经解决的问题,本博客不再讨论.只将本人遇到的问题做简单的说明. 一.VS 2013编译64位版本QT 4.8.6 QT项目官网中,对于QT4,其只提供了windows X86的版本,并且支持 ...

随机推荐

  1. 【DB2】How to resolve SQL20249N the statement was not processed with error

    相关链接 https://vinaysdb2blog.blogspot.com/2017/11/how-to-resolve-sql20249n-statement-was-not-processed ...

  2. Java之集合(六)PriorityQueue

    转载请注明源出处:http://www.cnblogs.com/lighten/p/7299233.html 1.前言 本章介绍队列中的PriorityQueue--优先队列,顾名思义,这是一个可以指 ...

  3. Java学习之路(十二):IO流<二>

    字符流 字符流是可以直接读写字符的IO流 使用字符流从文件中读取字符的时候,需要先读取到字节数据,让后在转换为字符 使用字符流向文件中写入字符时,需要把字符转为字节在写入文件 Reader和Write ...

  4. hadoop2.x 异常

    运行mr,出现如下异常 需要配置yarn-site.xml中配置如下信息 参考地址: https://issues.apache.org/jira/browse/MAPREDUCE-2983 http ...

  5. css 边框颜色渐变的半圆

    1.需求有这么个东西,个人不习惯背景图片来解决,开始了css尝试. <!DOCTYPE html> <html> <head> <meta charset=& ...

  6. Maven 学习笔记(一)

    什么是 maven? 对于已经使用过 maven 的用户来说 maven 就是一个架构工具,使用它可以将代码构建成一个可发布的工具.当然也有人会说maven是一个项目管理的工具.当然各有各的说法,那么 ...

  7. golang---interface结合reflect的泛型应用

    大致思路:序列化未知json放入一个interface{}中再通过反射将其内容解析出来 str1:=`{ , , , , , , "type_key": "testnow ...

  8. ssh 登录进入 docker container

    1.Container安装ssh服务,博主的linux是centos ① 安装ssh sudo yum install openssh-server #安装ssh服务器 service sshd st ...

  9. Git的gitattributes文件详解

    转自:Git的gitattributes文件详解 Git的gitattributes文件是一个文本文件,文件中的一行定义一个路径的若干个属性. 1. gitattributes文件以行为单位设置一个路 ...

  10. KafkaOffsetMonitor监控kafka

    KafkaOffsetMonitor监控kafka 1. KafkaOffsetMonitor是一个可以用于监控Kafka的Topic及Consumer消费状况的工具,其配置和使用特别的方便.源项目G ...