请选择 进入手机版 | 继续访问电脑版

 青浦修电脑 青浦笔记本维修 青浦手机维修 青浦电器维修

找回密码
立即注册
搜索
热搜: 活动 交友 discuz
发新帖

5万

积分

0

好友

1万

主题
发表于 2022-9-11 20:40:15 | 查看: 1559| 回复: 0
本文目录
  • CMake简介
  • CMake命令
  • CMake常见指令
  • 常用环境变量
  • Qt应用示例
  • 一个完整的Qt 5项目CMakeLists.txt
  • 参考CMake是一个跨平台、开源的构建工具,在C/C++项目中有广泛应用。本文首先介绍CMake及常用指令,并结合工作时需要用到的Qt 5,给出一个完整的CMake项目配置。
    % K+ D$ W( S# a% \
    CMake简介返回目录CMake如其名”Cross-platform Make”,是一个 跨平台、开源 的构建工具。与make不同,CMake并不直接构建软件,而是生成用于构建的Makefile、.sln等工程文件,相当于高阶构建工具。
    - R+ |- R# P' n# i- x5 n与另一构建工具Automake相比,CMake使用上更方便,支持更多的编译套件(Ninja、VS等)。许多编辑器和IDE,如VS Code(宇宙第一编辑器/IDE)、Clion、Visual Studio等都内置了对CMake的支持。特别的,CMake已经是QT 6的默认构建工具,官方给出从qmake迁移的理由是CMake成熟稳定、用户基数大生态完善。因此,对于需要跨平台编译运行的C/C++项目,很推荐学习和使用CMake作为构建工具,能方便的转换成各种IDE项目,团队成员无需切换编辑器/IDE即可工作。0 @4 A' u5 P& X: F: X# q$ j
    值得一提的是,CMake由Kitware公司开发和维护,VTK和ParaView等知名开源产品均出自该公司。从这方面看,CMake也算出身名门,因此能很快流行开来。( |# d4 |2 j2 z
    CMake命令返回目录CMake基于CMakeLists.txt文件来生成对应目标(generator)的构建文件,一个标准的CMake项目构建操作为(命令行方式):* A8 E& t9 Z% P  T4 \( J  l! }
    cd PROJECT_DIR0 P% U; g7 d7 m  o; k
    cmake
    - c0 I3 g, [2 a" ?make TARGET或者使用用CMake GUI:
    : Z* `+ }7 _% W$ R9 t6 P4 Z7 n: l
    " r- ]. _7 B7 w$ A
    ; ?0 p/ u+ g- I9 o6 `' nCMake-GUI操作示意图然后使用VS打开生成的.sln项目,即可编译、运行和调试项目。
    & V  f) W+ |4 l0 [Linux/Unix/MacOS平台上,CMake默认生成标准的makefile;Windows平台上则会检测Visual Studio版本,生成对应的VS .sln项目工程文件(在MSYS/Cygwin/WSL环境下执行除外)。可以使用 -G 选项切换生成目标,例如生成Ninja构建文件:
    * @+ e) P$ m- h% o/ v3 acmake . -G Ninja. L& m& w+ E/ U, m3 B# R% r
    ninja TARGETCMake一个非常棒的特性是“外部构建”(out-of-source build),即支持在源码目录外构建。由于这个特性,以及CMake生成的makefile没有clean命令,一般来说都推荐在单独的build目录中构建:
    ' E5 u3 ]& V8 J6 Z7 t* z9 zmkdir -p build
      d& c, w: D/ Lcd $_
    % D& d, X+ D" wcmake ..3 m. R2 `6 w/ E, a
    make TARGET -j4如果使用CMake GUI,Browse Build时请选择单独的构建目录。
    + }: |6 v- G( W0 z% j6 \9 @( G命令行方式下编译Debug/Release版本、传递C++编译参数,请使用 -D 选项,例如:
    ( L4 r; h/ O* M2 z( B% hcmake .. -DCMAKE_BUILD_TYPE=Release( Y: ], R! g( m' r. Q5 V% ?
    make TARGET -j4一些内置的宏定义参数可参考下文的环境变量。
    " L7 T' b+ @* c) u1 v如果是生成VS项目,则只需在VS中选择构建版本、设置编译和链接参数即可。
    8 G% _+ C+ E* m  U6 l- J" q CMake常见指令返回目录CMake基于CMakeLists.txt文件生成项目构建文件,因此编写CMakeLists.txt文件是CMake项目的核心。本小节介绍一些用在CMakeLists.txt文件中的常用指令。* X+ M/ F; o5 S  w. d5 \
    CMakeLists.txt 使用  # 作为注释,# 所在行后续字符均作为注释被忽略
    ) {- s3 ]  j0 m1 A, C1 E1 C/ g9 O# b
  • cmake_minimum_required一般这条指令出现在文件的最前面,用来指定项目支持的最低版本。对于Qt 5项目,建议为:cmake_minimum_required(VERSION 3.7)。
      a% `' R4 |6 G6 e% h; [( G
  • project指定项目名称及属性。C/C++项目的建议值为:project(项目名称 C CXX)。. Q: [/ i. L- k
  • set定义一些变量、宏的值。该指令一般会出现多次,例如设置C++语法标准:set(CMAKE_CXX_STANDARD 11)。相反的指令是unset。
    # D& Z% Y$ ^! W
  • if…else[if]…endif条件控制语句,注意指令后的括号不可省略:
    & f  g( ]. D. Wif (WIN32)* L9 y  l4 A( B! k. }$ Q
    xxxx
    ' Z. i5 y: N' L# A& f( t4 Aelse() # 括号不可省略+ i  ~) W* P0 B5 Y
    xxxx. |) r8 t! y9 g5 m( `+ U: n
    endif()
    ) g, v! \: {3 J, q6 D1 q  A& Z
  • find_package查找指定模块,例如OpenMP。Qt 5项目一般需要:find_package(Qt5 COMPONENTS Widgets REQUIRED)。
    2 f, c! ^8 ~" e- Z. G
  • include_directories添加头文件include路径,一个更推荐使用的指令是 target_include_directories,其不污染后续目标的include路径,且能精细控制是否暴露依赖的包含路径。但是 target_include_directories 需要CMake 3.13 版本才支持,在Visual Studio 2017中使用会有问题。
    " b' v: ~/ J# u8 E1 P
  • link_directories设置链接库的路径,更推荐的指令是 target_link_directories,理由见 include_directories。
    # M7 g$ f: \6 |+ }- G
  • aux_source_directory将指定目录下的源文件添加到变量中,例如:aux_source_directory(./src SRC)。注意该命令不会递归包含子目录源文件。! `$ x1 z4 Y4 M% O
  • filefile命令是一个功能丰富的目录和文件操作指令,例如递归找出目录下的所有源文件保存到SRC变量中:file(GLOB_RECURSE SRC "src/*.cpp" "src/*/*.cpp")。
    " x( W; ~$ h  D/ s  W相对于把每个需要编译的文件添加到CMakeLists.txt中,aux_source_directory 和 file 等指令可方便的引入多个文件,但其弊端之一是CMake不能感知文件变化。当新增文件、文件被删除、重命名时需刷新CMake缓存才能被应用到项目中。3 G( r( c; s' V; `
  • find_library查找指定库的路径并保存到变量中。" f4 {: s1 v% f/ ~" T
  • add_custom_command添加自定义命令,可用于构建前进行moc,构建后拷贝文件等用途。7 X( z4 F& s# n  v( r6 B- k
  • add_subdirectory添加一个需要构建的子目录,子目录下有CMakeLists.txt文件设定好构建规则。  O) ^: D) l  _6 w
  • add_executable构建可执行程序,一般项目的主CMakeLists.txt中会有这条指令。
    9 f- p& |* _8 E2 w% K0 m
  • add_library构建动态或静态库,一般存在于子目录或者库的CMakeLists.txt文件中。. A+ U9 F  r& _5 p% L4 e' Y
  • message可在cmake构建时输出信息。
    & [6 _" n7 h6 }CMakeLists.txt文件中指令不区分大小写,但一般来说同一个文件中指令应保持大小写风格一致。% }; m6 J$ [7 F. ?( v
    更多指令可参考 CMake官方文档。" ^* z- b* O* {) e
    常用环境变量返回目录本小节介绍几个常用的环境变量(编译宏)。
    1 D. v$ w  N, }, Q3 s! r
  • CMAKE_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的使用方式。
    8 a- q+ o+ ?, e新建Qt项目时,可以选择CMake作为构建工具:
    & |5 R# j7 B4 _2 \* g, K
    3 W/ O) u4 S7 J- s/ f* K% D' _4 j1 d* |8 ^# O! I' P
    Qt新建项目使用CMake生成项目后,项目文件夹将出现CMakeLists.txt和CMakeLists.txt.user两个文件,熟悉的.pro文件没有了(CMakeLists.txt.user充当了Qt Creator工程文件的角色,其他IDE用不到,可删除)。$ M$ y( _: w) D; p3 c
    但需要注意的是,此时Qt Creator中编译项目是没问题的,但是在CLion/VS Code中打开,或者生成Visual Studio用的.sln文件会有问题,因为CMake无法检测到Qt是否安装及其安装路径。% G1 m7 p3 N3 I8 r/ T- }5 ~
    解决办法便是在 project 指令后增加如下指令告知Qt的安装位置:2 U; Q6 W% o, _6 i: w2 c7 x
    # 具体路径请根据自身情况替换; J- s4 s: C; i
    set(QT_MSVC_PATH "C:\\Qt\\Qt5.12.8\\5.12.8\\msvc2017_64")# @- O% X! y! e5 [3 G7 q6 F
    set(CMAKE_PREFIX_PATH "${QT_MSVC_PATH}/lib/cmake")
    + H7 x- U5 |$ E5 V然后再次运行 cmake 指令或者使用CMake GUI重新运行,构建文件夹下便能正常生成.sln项目文件。' J9 s- ?# V+ ]0 _. {6 [
    VS中编译好后,运行时会提示无法找到Qt相关的dll导致程序不能正常运行。解决办法包括:1 s* J' q' v: }! n+ V) T# A; D, s4 Y2 _
    1. 设置VS选项,将Qt的dll路径包含进去;$ U4 F' N: ?1 P8 N
    2. 将Qt相关dll拷贝到编译输出文件夹;
    $ R- D5 F2 T+ }( | 3. 设置CMake,使其能自动复制所需要的dll。  ]- ?- W0 O4 }0 N
    这里介绍第三种方式,原理是借助Qt自带的windeployqt.exe程序自动部署程序所需dll到目标文件夹。具体操作为,在项目根目录的CMakeLists.txt最后添加部署dll的指令:
    , x! I7 V7 W6 l9 J6 Lset(QT_BIN_PATH "${QT_MSVC_PATH}/bin")( q& u9 b) }, ]% _7 O' J- `
    function(windeployqt target)
    1 g" \5 ^* k' q5 |9 A8 G# POST_BUILD step, R3 S9 J# Y" w5 \
    # - after build, we have a bin/lib for analyzing qt dependencies; `- E9 V$ b1 P3 O& W4 s2 ^" g$ i+ r
    # - we run windeployqt on target and deploy Qt libs! _8 V' ^/ @- C0 |3 J
    add_custom_command(TARGET ${target} POST_BUILD
    # ^# u9 A. X4 U! P/ l0 T( ]COMMAND "${QT_BIN_PATH}/windeployqt.exe". Q6 F6 [7 Z7 c8 n* W, V! Q
    --verbose 18 C: P+ z6 ~6 s0 _  }
    #--release # uncomment this line if built with Release: e, P5 D6 i( A. N9 R2 H! Z3 ~
    #--no-svg
    ; o1 `5 A5 z2 k5 z, C# k7 A#--no-angle" |* d5 ~, w" U' U3 ]: k
    #--no-opengl
    . `; Z. T  s4 A' Y! l! j( q#--no-opengl-sw
    / q* U$ X0 o2 k/ t& t#--no-compiler-runtime4 |  P9 _* M1 v5 W
    #--no-system-d3d-compiler7 w4 L1 f$ v$ y: h2 W! X1 |; j
    \"$\"3 p# X: v' L; I+ I  k
    COMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ...". e4 V" G  n+ E9 U! h7 U6 A( U
    )1 l4 B+ x* a/ V2 I. K
    endfunction()
    8 r6 ]# v4 R" \2 h3 Y! @if (WIN32)
      N" V' {; b& p1 ?: ?  windeployqt(${PROJECT_NAME})
    & f1 L* C" n9 n; Bendif()最后,转换成VS项目时,默认是Console项目,运行时会有cmd窗口。一个解决办法是在生成可执行文件时设置目标为 WIN32:
    4 F2 T7 z% d! x* ~. @add_executable(${PROJECT_NAME} WIN32 xxxx)" l, c* N5 m# P, y; ^
    一个完整的Qt 5项目CMakeLists.txt返回目录以下是一个适用于Windows平台的Qt 5项目完整CMakeLists.txt,实际使用时请替换名字和Qt 5安装路径等:. @' l; F5 P! p! m7 b
    cmake_minimum_required(VERSION 3.7); q0 v, {0 @0 a- n2 p/ ]2 X
    # 请将myproject改成实际的应用名字
    " d  S: o5 g' l8 Y" Vproject(myproject LANGUAGES CXX)
    $ O$ s& ]5 G/ E- u. `+ D$ Pset(CMAKE_INCLUDE_CURRENT_DIR ON)
    # z8 t/ i5 `4 G0 E0 _2 t# u# 请更改为实际的Qt安装目录
    / N/ v9 s: q3 [0 O8 b( ^2 d+ [set(QT_MSVC_PATH "C:\\Qt\\Qt5.12.8\\5.12.8\\msvc2017_64")
    5 e" h6 x) E8 e& A4 d: n  g0 w3 ^set(CMAKE_PREFIX_PATH "${QT_MSVC_PATH}/lib/cmake")
    . C" `0 W) j7 Y7 W  N5 aset(QT_BIN_PATH "${QT_MSVC_PATH}/bin")0 @5 z3 X; x: Y+ j4 z8 z
    set(CMAKE_AUTOUIC ON)# V; I$ \; G' A' Q8 f3 q# |0 w  @
    set(CMAKE_AUTOMOC ON)
    ! k. _; l4 x. {; r" a0 Yset(CMAKE_AUTORCC ON)$ T9 x" \  U/ Q4 D, v9 v$ u
    set(CMAKE_CXX_STANDARD 11)7 V7 H( z0 A: P- b$ k
    set(CMAKE_CXX_STANDARD_REQUIRED ON)0 e& C* I. t9 t2 F7 R
    find_package(Qt5 COMPONENTS Widgets REQUIRED)
    0 }5 ~2 `* g: M# 默认Release构建. q4 Q; k, a+ p) R# u
    if (NOT CMAKE_BUILD_TYPE)% g& J* t6 `. l% f8 O
        set( CMAKE_BUILD_TYPE "Release" )1 b$ ^) O! H( k  X$ E+ i2 R8 Z' H
    endif()
    , q* K! D% t) [( wmessage("build type: ${CMAKE_BUILD_TYPE}")
    " U1 A0 }- p9 w6 ?! x6 v/ B3 `9 ]# 按照自己的项目结构添加文件5 i) P: x% W" n* K1 c
    # 也可使用file/aux_source_directory批量引入,注意不要引入自动生成的文件!
    8 ?8 z( h8 p5 U3 B! Gadd_executable(${PROJECT_NAME} WIN32$ v8 k4 f* y% ^9 w2 \9 t
      main.cpp
    + v, H; f6 V- O. ~  mainwindow.cpp9 }5 Y8 \) m+ o- I
      mainwindow.h6 {$ d# {: d4 h( E) C0 a; V
    )
    3 J  z6 N6 Q! j% b  C; Itarget_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)# N; E! P9 D9 _/ A
    function(windeployqt target)- h( E$ W0 f; X" }" O; s, H% X
    # POST_BUILD step
    5 j. R* l! `6 Jadd_custom_command(TARGET ${target} POST_BUILD
    1 N. M5 M9 b8 v$ ^% [, r5 }COMMAND "${QT_BIN_PATH}/windeployqt.exe"  z% J, c6 O, x3 h
    --verbose 1
    1 A: W- M1 x# K2 }8 Y/ i#--release
    + O1 y$ x) ~4 M& y3 }; s#--no-svg8 H4 W0 T. E0 x/ J: C0 }
    #--no-angle
    1 l  l2 Y7 [1 ^2 b& M! X3 f#--no-opengl
    : f& U! K5 e/ g* y* w9 E" _#--no-opengl-sw! J% D! g9 Q7 }. s0 N( R6 {
    #--no-compiler-runtime1 E5 k) ^" O8 h2 ?3 h
    #--no-system-d3d-compiler( c' c! T" z  G1 U$ |+ g6 P0 X
    \"$\"9 Q( |/ \& D5 j5 F' [( X% H7 R
    COMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ..."9 T% n# ~, D3 _& `( X
    )& O; t- e3 C! _) a
    endfunction()
    9 J0 I3 P0 ^$ v9 `; \9 [% |if (WIN32)8 U7 d9 E0 P1 h, e' ^' j! Q
      windeployqt(${PROJECT_NAME})
    " Q) J/ `5 t: j6 iendif()1 T! g0 U$ \0 d8 P3 x% Z
    ````通过上面的配置,我们的Qt项目既可在Qt Creator中正常编译运行,也可在CLion/Visual Studio中正常编译运行而 无需安装Qt插件。& m0 u" q  q. `" A6 ^
    参考返回目录1. CMake官网
    $ b, q, b) _" ^/ F$ O2. CMake教程
    0 l* _9 s# P/ A+ c: E$ y+ c3. CMake FAQ
    ( n& m; ]0 |3 u% {' d4. CMake指定编译器
    * s9 d( V6 o+ ^# ?- OAD:【国外VPS推荐】 搬瓦工三网回程CN2 GIA VPS,季付46.87$打赏赞(3)
  • 本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    收藏回复 显示全部楼层 道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    QQ|Archiver|手机版|小黑屋|青浦海洋数码电脑城 ( 沪ICP备18024137号 )

    GMT+8, 2026-10-15 19:21 , Processed in 0.113202 second(s), 22 queries .

    Powered by Discuz! X3.4

    © 2001-2023 Discuz! Team.

    快速回复 返回顶部 返回列表