|
本文目录CMake简介CMake命令CMake常见指令常用环境变量Qt应用示例一个完整的Qt 5项目CMakeLists.txt参考CMake是一个跨平台、开源的构建工具,在C/C++项目中有广泛应用。本文首先介绍CMake及常用指令,并结合工作时需要用到的Qt 5,给出一个完整的CMake项目配置。; s0 C) A( D9 Y7 c4 s* O
CMake简介返回目录CMake如其名”Cross-platform Make”,是一个 跨平台、开源 的构建工具。与make不同,CMake并不直接构建软件,而是生成用于构建的Makefile、.sln等工程文件,相当于高阶构建工具。, a& E. }) _$ t* w
与另一构建工具Automake相比,CMake使用上更方便,支持更多的编译套件(Ninja、VS等)。许多编辑器和IDE,如VS Code(宇宙第一编辑器/IDE)、Clion、Visual Studio等都内置了对CMake的支持。特别的,CMake已经是QT 6的默认构建工具,官方给出从qmake迁移的理由是CMake成熟稳定、用户基数大生态完善。因此,对于需要跨平台编译运行的C/C++项目,很推荐学习和使用CMake作为构建工具,能方便的转换成各种IDE项目,团队成员无需切换编辑器/IDE即可工作。5 a1 Y; ^! q+ }7 j* p' M! r
值得一提的是,CMake由Kitware公司开发和维护,VTK和ParaView等知名开源产品均出自该公司。从这方面看,CMake也算出身名门,因此能很快流行开来。
% W& @% a5 W8 \. N CMake命令返回目录CMake基于CMakeLists.txt文件来生成对应目标(generator)的构建文件,一个标准的CMake项目构建操作为(命令行方式):
4 z$ I$ T* ]# c6 X2 l/ d: I! Hcd PROJECT_DIR
" x: e' d4 }3 _cmake7 R6 E. z- Y% y2 E
make TARGET或者使用用CMake GUI:
7 H: i$ c. ]9 W2 K1 ?% h* V+ ]# b, N( U
4 |+ F; H+ o7 z9 O+ r4 ^CMake-GUI操作示意图然后使用VS打开生成的.sln项目,即可编译、运行和调试项目。
& O; L2 r2 o; T; {% gLinux/Unix/MacOS平台上,CMake默认生成标准的makefile;Windows平台上则会检测Visual Studio版本,生成对应的VS .sln项目工程文件(在MSYS/Cygwin/WSL环境下执行除外)。可以使用 -G 选项切换生成目标,例如生成Ninja构建文件:
5 N( d) p3 a, V! U# q2 qcmake . -G Ninja
, g9 _& p' {7 bninja TARGETCMake一个非常棒的特性是“外部构建”(out-of-source build),即支持在源码目录外构建。由于这个特性,以及CMake生成的makefile没有clean命令,一般来说都推荐在单独的build目录中构建:+ e1 m2 Z# q& U. i$ n5 _% G+ m
mkdir -p build: H5 ^% G+ ?2 N [
cd $_
I5 \% s9 g5 h" ]5 R" fcmake ..
0 C- Q( P/ Z) s6 J# Z" Lmake TARGET -j4如果使用CMake GUI,Browse Build时请选择单独的构建目录。
/ J$ U( h" `, G3 F/ _命令行方式下编译Debug/Release版本、传递C++编译参数,请使用 -D 选项,例如:
% a! f( L/ d: ~+ O1 S4 d2 ^. mcmake .. -DCMAKE_BUILD_TYPE=Release
) X1 @( T; ^. q" V9 c1 x9 E( fmake TARGET -j4一些内置的宏定义参数可参考下文的环境变量。, a9 F8 K6 P" Y( ~. b# T" z
如果是生成VS项目,则只需在VS中选择构建版本、设置编译和链接参数即可。
7 K+ c/ V+ Z, F% V2 ^ CMake常见指令返回目录CMake基于CMakeLists.txt文件生成项目构建文件,因此编写CMakeLists.txt文件是CMake项目的核心。本小节介绍一些用在CMakeLists.txt文件中的常用指令。- D" H. B3 F) R. y6 j2 l6 y3 o- y
CMakeLists.txt 使用 # 作为注释,# 所在行后续字符均作为注释被忽略
" y$ o" x* V+ L4 Ccmake_minimum_required一般这条指令出现在文件的最前面,用来指定项目支持的最低版本。对于Qt 5项目,建议为:cmake_minimum_required(VERSION 3.7)。4 l3 S a) N3 B c$ D4 C8 p# y5 V
project指定项目名称及属性。C/C++项目的建议值为:project(项目名称 C CXX)。
3 l) p# z6 r$ [: }9 r4 Fset定义一些变量、宏的值。该指令一般会出现多次,例如设置C++语法标准:set(CMAKE_CXX_STANDARD 11)。相反的指令是unset。' d! }7 A; m% [1 }. w* O- S6 u
if…else[if]…endif条件控制语句,注意指令后的括号不可省略:
5 q) D7 e1 L* ~% G/ s2 ^if (WIN32)
1 B: f& z% v# r+ {; ~. exxxx
! ~, B' _ }! c; a' Ielse() # 括号不可省略
# j4 U% l- V4 ?( ~xxxx s. V, K! F7 O% x6 \/ B" B
endif()
- z+ h5 @5 F8 g! y+ ~7 H( A, q7 nfind_package查找指定模块,例如OpenMP。Qt 5项目一般需要:find_package(Qt5 COMPONENTS Widgets REQUIRED)。
/ d/ Z0 m8 e" Ginclude_directories添加头文件include路径,一个更推荐使用的指令是 target_include_directories,其不污染后续目标的include路径,且能精细控制是否暴露依赖的包含路径。但是 target_include_directories 需要CMake 3.13 版本才支持,在Visual Studio 2017中使用会有问题。
4 R6 a0 D v. w' W1 l link_directories设置链接库的路径,更推荐的指令是 target_link_directories,理由见 include_directories。& ~5 R1 u8 `% u* B% Y2 Q! H/ p
aux_source_directory将指定目录下的源文件添加到变量中,例如:aux_source_directory(./src SRC)。注意该命令不会递归包含子目录源文件。9 S- V, A; Z I' Y( S2 h9 Z
filefile命令是一个功能丰富的目录和文件操作指令,例如递归找出目录下的所有源文件保存到SRC变量中:file(GLOB_RECURSE SRC "src/*.cpp" "src/*/*.cpp")。: [ T( C: ~: r2 D3 P. [& c$ d
相对于把每个需要编译的文件添加到CMakeLists.txt中,aux_source_directory 和 file 等指令可方便的引入多个文件,但其弊端之一是CMake不能感知文件变化。当新增文件、文件被删除、重命名时需刷新CMake缓存才能被应用到项目中。 }4 S4 W) n y9 f/ m
find_library查找指定库的路径并保存到变量中。
0 \2 D$ U; S. r( e+ v5 w" a3 Q" j8 zadd_custom_command添加自定义命令,可用于构建前进行moc,构建后拷贝文件等用途。
5 n$ P1 g2 l; c9 wadd_subdirectory添加一个需要构建的子目录,子目录下有CMakeLists.txt文件设定好构建规则。 B9 |! o, f0 l
add_executable构建可执行程序,一般项目的主CMakeLists.txt中会有这条指令。" w% {2 C7 Z7 z# m: q/ Q, r4 B4 V
add_library构建动态或静态库,一般存在于子目录或者库的CMakeLists.txt文件中。- C D+ P' K8 b K3 ^
message可在cmake构建时输出信息。
" s- V' b! R; J& s+ E) z7 GCMakeLists.txt文件中指令不区分大小写,但一般来说同一个文件中指令应保持大小写风格一致。! x- _( r( _/ }
更多指令可参考 CMake官方文档。, V" g4 f% p; @2 y# H
常用环境变量返回目录本小节介绍几个常用的环境变量(编译宏)。
& n6 c3 U" _6 J8 fCMAKE_BUILD_TYPE: 指定构建类型,常用值为 Debug、Release、RelWithDebInfo 和 MinSizeRel;CMAKE_C(XX)_FLAGS:传递给C/C++编译器的编译选项,例如输出所有警告: -DCMAKE_CXX_FLAGS="-Wall";– CMAKE_EXE/MODULE/_LINKER_FLAGS:传递给C/C++链接器的编译选项,例如指定链接数学库:-DCMAKE_LINKER_FLAGS="-lmath"。 Qt应用示例返回目录本节结合工作时需要用到的Qt 5,介绍Qt 5工程中CMake的使用方式。
) z8 d# O { ?4 V新建Qt项目时,可以选择CMake作为构建工具:* l' |" H$ h: w& w/ G" }# K0 b$ M3 P* `
) ]8 d( t9 w& E: }, Z( e v
. Y; Y7 z& ^# I, _ w' SQt新建项目使用CMake生成项目后,项目文件夹将出现CMakeLists.txt和CMakeLists.txt.user两个文件,熟悉的.pro文件没有了(CMakeLists.txt.user充当了Qt Creator工程文件的角色,其他IDE用不到,可删除)。
c% o- B3 t+ y W但需要注意的是,此时Qt Creator中编译项目是没问题的,但是在CLion/VS Code中打开,或者生成Visual Studio用的.sln文件会有问题,因为CMake无法检测到Qt是否安装及其安装路径。+ M' b7 D, J3 [6 H
解决办法便是在 project 指令后增加如下指令告知Qt的安装位置:0 [8 `/ f+ i" r* b2 R8 V' \
# 具体路径请根据自身情况替换
3 l3 f# r' K- F5 o+ W: {( x: dset(QT_MSVC_PATH "C:\\Qt\\Qt5.12.8\\5.12.8\\msvc2017_64")4 l) ~) f4 p/ O8 R: T4 I
set(CMAKE_PREFIX_PATH "${QT_MSVC_PATH}/lib/cmake")
+ m4 K7 B1 h4 u然后再次运行 cmake 指令或者使用CMake GUI重新运行,构建文件夹下便能正常生成.sln项目文件。/ y+ T$ ?% x- H
VS中编译好后,运行时会提示无法找到Qt相关的dll导致程序不能正常运行。解决办法包括:5 E1 u: @5 i5 s- L4 v i8 ^$ b9 u
1. 设置VS选项,将Qt的dll路径包含进去;; O( g) ?, K( M
2. 将Qt相关dll拷贝到编译输出文件夹;5 ?" ?- V- P( l+ b! W
3. 设置CMake,使其能自动复制所需要的dll。
% ?" E0 f$ K+ M2 V% d: O9 k3 V( d这里介绍第三种方式,原理是借助Qt自带的windeployqt.exe程序自动部署程序所需dll到目标文件夹。具体操作为,在项目根目录的CMakeLists.txt最后添加部署dll的指令:, r, r& G; ~( v# A
set(QT_BIN_PATH "${QT_MSVC_PATH}/bin"): h5 q" \" I7 c' a3 S
function(windeployqt target)
b8 G3 O& z9 M: }- ?9 Q1 ~# POST_BUILD step# c6 j* o2 N m. a* Q
# - after build, we have a bin/lib for analyzing qt dependencies
" p0 X' S, M, ?0 l! C/ E# - we run windeployqt on target and deploy Qt libs
& q# K# r% U' R& a; C n$ Sadd_custom_command(TARGET ${target} POST_BUILD
- l3 Q6 w4 C* j/ z/ \& w- vCOMMAND "${QT_BIN_PATH}/windeployqt.exe"
) C+ [/ E2 F& R7 G, ?+ O5 T) o--verbose 1
" ?$ U& {' \6 v% m% |2 Q6 ]#--release # uncomment this line if built with Release' Z# m' l3 B8 X. H) N. d
#--no-svg
, x' Z% k3 w: P. A9 m0 E" {#--no-angle
* H: v2 Y; G* f% r( s) L. J7 m3 `5 P& P#--no-opengl
+ C9 V5 r" j- h#--no-opengl-sw
0 P2 X2 ~8 e" C, ~$ M#--no-compiler-runtime
1 K3 v9 R; a; { D' Y#--no-system-d3d-compiler
) [4 y% s- M* L: A& _: t- O\"$\"
# K2 ~3 @. a5 H# H2 M3 q5 OCOMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ..."/ |- D0 ]- L# J: T
)
, w1 n$ d4 T# m8 b4 @) Kendfunction()
, Y1 d1 d- D+ [6 q2 Kif (WIN32)
4 M9 z4 e8 L2 t! j' F% a9 \% z windeployqt(${PROJECT_NAME})
$ }0 x) z8 O9 X T9 tendif()最后,转换成VS项目时,默认是Console项目,运行时会有cmd窗口。一个解决办法是在生成可执行文件时设置目标为 WIN32:
. q0 |: X9 h' V/ d6 h Radd_executable(${PROJECT_NAME} WIN32 xxxx)( ?! k' ]9 w% x: Y
一个完整的Qt 5项目CMakeLists.txt返回目录以下是一个适用于Windows平台的Qt 5项目完整CMakeLists.txt,实际使用时请替换名字和Qt 5安装路径等:" o4 y7 D1 N! Q& c5 ~+ p
cmake_minimum_required(VERSION 3.7)
% j5 @5 K8 l; c9 `2 P# 请将myproject改成实际的应用名字
6 A6 C% U% p" a2 j: I# Q# K5 uproject(myproject LANGUAGES CXX)/ D# g% ?' q: N, X( \: W
set(CMAKE_INCLUDE_CURRENT_DIR ON)1 Z* T8 e2 v# \
# 请更改为实际的Qt安装目录
& ?' [% i3 c( | P" T3 p- Hset(QT_MSVC_PATH "C:\\Qt\\Qt5.12.8\\5.12.8\\msvc2017_64")3 h! k% p) u- \6 [$ ~3 d& \
set(CMAKE_PREFIX_PATH "${QT_MSVC_PATH}/lib/cmake"); C& Q5 d, H8 T" \# f
set(QT_BIN_PATH "${QT_MSVC_PATH}/bin")
9 r {4 M) p" E4 m( Qset(CMAKE_AUTOUIC ON)2 |. v5 S& C2 y+ {/ L+ c6 Q
set(CMAKE_AUTOMOC ON)
, y. n* F" [7 Y7 ?6 Oset(CMAKE_AUTORCC ON)
; o8 ~7 Y+ Q5 Tset(CMAKE_CXX_STANDARD 11)3 o, I$ c- O9 U9 p0 v
set(CMAKE_CXX_STANDARD_REQUIRED ON)
/ T8 k( Z$ `$ w/ U. b: Yfind_package(Qt5 COMPONENTS Widgets REQUIRED)
3 ^) c6 e) i$ ?' z$ Q# 默认Release构建9 c# w% s7 G' x$ G8 [
if (NOT CMAKE_BUILD_TYPE)
2 R9 a2 E) Y. k( r0 o! G, a set( CMAKE_BUILD_TYPE "Release" )/ ]% G$ R: {* E
endif()
' P: u- x# v9 c4 G$ g1 Hmessage("build type: ${CMAKE_BUILD_TYPE}")
4 G0 g- k$ W; X# ^. W7 V0 C# 按照自己的项目结构添加文件. L4 |# l* {$ v& [( B9 w7 b
# 也可使用file/aux_source_directory批量引入,注意不要引入自动生成的文件!' i) Q$ x; k1 j% Q) U
add_executable(${PROJECT_NAME} WIN32
, ?$ ?2 c0 e p1 F/ r8 S main.cpp
7 ~, W* u$ k. @8 O' I& P mainwindow.cpp$ ]$ R* b6 b6 p. | z* q+ N
mainwindow.h
: Q2 d* r2 A9 T+ l% z)
) l5 L" x) v2 ^2 A, vtarget_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)
+ y7 [# Q3 S: H* C8 |$ Tfunction(windeployqt target)/ s( f3 _& V) w) o- a
# POST_BUILD step
! d# ?. n z2 Oadd_custom_command(TARGET ${target} POST_BUILD4 k, J0 X& ?1 q2 \: u( ?* z$ u
COMMAND "${QT_BIN_PATH}/windeployqt.exe"
* z1 [, N7 G* y7 X4 V--verbose 1
7 d9 L, v( _/ C+ H1 N. Y#--release ! A$ W; v0 p! \- H6 X
#--no-svg+ a, Q1 R9 a" ~0 [% {
#--no-angle1 z9 L) Y6 ^+ r- H9 @1 J
#--no-opengl
9 {0 E1 M5 C, n! S+ U8 ?6 d6 E/ i#--no-opengl-sw# E9 K: h! o) X) @- g
#--no-compiler-runtime* s5 [, q2 J: Z( z& C2 T( h
#--no-system-d3d-compiler2 p- Z, y: N# |( G$ F
\"$\"/ M1 {. M- y+ g& L6 [
COMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ..."
{' L& L- H* G, D; L% Q e)
: B( ^% F0 }) {6 n/ K7 j+ Sendfunction()6 `- J* E& M# L4 E
if (WIN32)
$ ?" m1 i$ u/ { windeployqt(${PROJECT_NAME})
& v# T- b) a# r% F- d7 uendif()
" H2 X9 `/ K5 Y& q````通过上面的配置,我们的Qt项目既可在Qt Creator中正常编译运行,也可在CLion/Visual Studio中正常编译运行而 无需安装Qt插件。
" u @, P9 J) h" e' \ 参考返回目录1. CMake官网
/ r- Z, k2 T2 _2. CMake教程2 D$ h$ y( {3 t( w9 t
3. CMake FAQ8 `+ G6 j! ^3 s% I9 w
4. CMake指定编译器
2 W* h4 [, b1 I1 d: V- }& p0 A {AD:【国外VPS推荐】 搬瓦工三网回程CN2 GIA VPS,季付46.87$打赏赞(3) |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|