扫一扫,微信登陆

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

搜索
查看: 323|回复: 0

CMake简明实用教程 - 青浦海洋数码电脑城

[复制链接]

1万

主题

1万

帖子

5万

积分

论坛元老

Rank: 8Rank: 8

积分
56206
发表于 2022-9-11 20:40:15 | 显示全部楼层 |阅读模式
本文目录
  • CMake简介
  • CMake命令
  • CMake常见指令
  • 常用环境变量
  • Qt应用示例
  • 一个完整的Qt 5项目CMakeLists.txt
  • 参考CMake是一个跨平台、开源的构建工具,在C/C++项目中有广泛应用。本文首先介绍CMake及常用指令,并结合工作时需要用到的Qt 5,给出一个完整的CMake项目配置。, ]; j; L" T- @8 ]4 H1 P1 c
    CMake简介返回目录CMake如其名”Cross-platform Make”,是一个 跨平台、开源 的构建工具。与make不同,CMake并不直接构建软件,而是生成用于构建的Makefile、.sln等工程文件,相当于高阶构建工具。
    3 D' k% e$ L* p: o2 {/ _与另一构建工具Automake相比,CMake使用上更方便,支持更多的编译套件(Ninja、VS等)。许多编辑器和IDE,如VS Code(宇宙第一编辑器/IDE)、Clion、Visual Studio等都内置了对CMake的支持。特别的,CMake已经是QT 6的默认构建工具,官方给出从qmake迁移的理由是CMake成熟稳定、用户基数大生态完善。因此,对于需要跨平台编译运行的C/C++项目,很推荐学习和使用CMake作为构建工具,能方便的转换成各种IDE项目,团队成员无需切换编辑器/IDE即可工作。) ?$ t0 Z% s; j' \' w% ]* k% P
    值得一提的是,CMake由Kitware公司开发和维护,VTK和ParaView等知名开源产品均出自该公司。从这方面看,CMake也算出身名门,因此能很快流行开来。
    $ e5 \! k8 ~$ H+ G4 d CMake命令返回目录CMake基于CMakeLists.txt文件来生成对应目标(generator)的构建文件,一个标准的CMake项目构建操作为(命令行方式):& w! v  X" O6 a9 U' n+ ^0 I+ D
    cd PROJECT_DIR: S8 Q; J/ S% @  ^& Q
    cmake! |( H7 Q  t" o: W0 v5 m
    make TARGET或者使用用CMake GUI:1 u1 X" B; j& g0 o" z

    # {; O  x7 [8 h  ]  U; V! E8 X. m6 |* M
    CMake-GUI操作示意图然后使用VS打开生成的.sln项目,即可编译、运行和调试项目。
    ! U' a5 ?$ p- J: p, E6 G9 ILinux/Unix/MacOS平台上,CMake默认生成标准的makefile;Windows平台上则会检测Visual Studio版本,生成对应的VS .sln项目工程文件(在MSYS/Cygwin/WSL环境下执行除外)。可以使用 -G 选项切换生成目标,例如生成Ninja构建文件:
    4 e5 o0 i, v( W  vcmake . -G Ninja
    ' D  N  P$ p  ?0 w. wninja TARGETCMake一个非常棒的特性是“外部构建”(out-of-source build),即支持在源码目录外构建。由于这个特性,以及CMake生成的makefile没有clean命令,一般来说都推荐在单独的build目录中构建:4 S! Z; \! |( _* ~
    mkdir -p build# y8 n7 K& ^" u( d2 j6 s3 k' q
    cd $_
    + v6 _9 e' e* O5 X- K1 C; i1 @3 ocmake ..& y6 u7 S. a/ r9 M) E7 d; o& B( s& e
    make TARGET -j4如果使用CMake GUI,Browse Build时请选择单独的构建目录。
    # N4 o% {  l6 E+ |命令行方式下编译Debug/Release版本、传递C++编译参数,请使用 -D 选项,例如:
    , O& t, R1 a( H9 d+ I) N3 acmake .. -DCMAKE_BUILD_TYPE=Release
    % v, l, _* w0 J7 t, Zmake TARGET -j4一些内置的宏定义参数可参考下文的环境变量。4 }& A+ ?9 ?2 a
    如果是生成VS项目,则只需在VS中选择构建版本、设置编译和链接参数即可。
    5 L3 P3 M4 `5 R+ T, ^6 W CMake常见指令返回目录CMake基于CMakeLists.txt文件生成项目构建文件,因此编写CMakeLists.txt文件是CMake项目的核心。本小节介绍一些用在CMakeLists.txt文件中的常用指令。& w. C8 ?3 x3 F& I0 l- M
    CMakeLists.txt 使用  # 作为注释,# 所在行后续字符均作为注释被忽略& w5 d) R5 s3 h. v, M
  • cmake_minimum_required一般这条指令出现在文件的最前面,用来指定项目支持的最低版本。对于Qt 5项目,建议为:cmake_minimum_required(VERSION 3.7)。' h  G" f0 ~6 j' ^3 V% o; [  J( m
  • project指定项目名称及属性。C/C++项目的建议值为:project(项目名称 C CXX)。
      u& L! d8 F; r% d& e( m
  • set定义一些变量、宏的值。该指令一般会出现多次,例如设置C++语法标准:set(CMAKE_CXX_STANDARD 11)。相反的指令是unset。
    ; Q) u' y! A1 `& ?/ h
  • if…else[if]…endif条件控制语句,注意指令后的括号不可省略:' K& q: l- N% m4 l9 A$ z
    if (WIN32)7 c  h6 A  A* V2 e$ b) W
    xxxx9 K- W9 K; z$ P. T
    else() # 括号不可省略
    / a$ Z6 q  `7 |9 `xxxx
    1 _( `  [) u  I# F5 Vendif()
    ) w7 E! ^5 w- p7 Y
  • find_package查找指定模块,例如OpenMP。Qt 5项目一般需要:find_package(Qt5 COMPONENTS Widgets REQUIRED)。
    0 n- W' o1 B' x- P$ R: t
  • include_directories添加头文件include路径,一个更推荐使用的指令是 target_include_directories,其不污染后续目标的include路径,且能精细控制是否暴露依赖的包含路径。但是 target_include_directories 需要CMake 3.13 版本才支持,在Visual Studio 2017中使用会有问题。
    9 z% B5 l; L) s3 P) v
  • link_directories设置链接库的路径,更推荐的指令是 target_link_directories,理由见 include_directories。8 R3 ]. m7 ?9 M5 c% i, @5 M
  • aux_source_directory将指定目录下的源文件添加到变量中,例如:aux_source_directory(./src SRC)。注意该命令不会递归包含子目录源文件。# a' t6 ^, V/ G
  • filefile命令是一个功能丰富的目录和文件操作指令,例如递归找出目录下的所有源文件保存到SRC变量中:file(GLOB_RECURSE SRC "src/*.cpp" "src/*/*.cpp")。
    6 u3 s! u# G- P8 W& b( g相对于把每个需要编译的文件添加到CMakeLists.txt中,aux_source_directory 和 file 等指令可方便的引入多个文件,但其弊端之一是CMake不能感知文件变化。当新增文件、文件被删除、重命名时需刷新CMake缓存才能被应用到项目中。
    + B. c: j" c' m& H' }
  • find_library查找指定库的路径并保存到变量中。9 z* p! O/ _! a
  • add_custom_command添加自定义命令,可用于构建前进行moc,构建后拷贝文件等用途。
    3 {: Z5 n) L/ d& d/ n! t  f
  • add_subdirectory添加一个需要构建的子目录,子目录下有CMakeLists.txt文件设定好构建规则。+ n+ U& d" A  ]) s% @1 B* s  V0 }
  • add_executable构建可执行程序,一般项目的主CMakeLists.txt中会有这条指令。
      r/ c8 r6 F1 @5 x) p( i! \
  • add_library构建动态或静态库,一般存在于子目录或者库的CMakeLists.txt文件中。, l4 R9 E# E, q/ A2 U2 b# |, u
  • message可在cmake构建时输出信息。
    4 n5 ?2 j6 |3 ]6 w4 n* ^. t8 ICMakeLists.txt文件中指令不区分大小写,但一般来说同一个文件中指令应保持大小写风格一致。* @8 U( n) b* |) X; F7 a% a: G% i6 |
    更多指令可参考 CMake官方文档。- Q% y, s$ z$ y" I, v) u
    常用环境变量返回目录本小节介绍几个常用的环境变量(编译宏)。! w7 G! \3 Z' @4 x& D5 F
  • 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的使用方式。
    9 O; p4 k6 f$ @新建Qt项目时,可以选择CMake作为构建工具:
    + Z6 F# x) K! o4 U
    # c# X, D, P5 l- D1 `( y5 H: Q) D$ U# m( L
    Qt新建项目使用CMake生成项目后,项目文件夹将出现CMakeLists.txt和CMakeLists.txt.user两个文件,熟悉的.pro文件没有了(CMakeLists.txt.user充当了Qt Creator工程文件的角色,其他IDE用不到,可删除)。* m& {8 _$ c; O% _0 Q) ]
    但需要注意的是,此时Qt Creator中编译项目是没问题的,但是在CLion/VS Code中打开,或者生成Visual Studio用的.sln文件会有问题,因为CMake无法检测到Qt是否安装及其安装路径。
    & d( F& j- B2 \& ?6 P7 M解决办法便是在 project 指令后增加如下指令告知Qt的安装位置:
    4 `# U' D" ?" q7 q+ n+ J9 D& F# 具体路径请根据自身情况替换
    1 I3 \9 ^$ C+ {9 T# i' u" [2 kset(QT_MSVC_PATH "C:\\Qt\\Qt5.12.8\\5.12.8\\msvc2017_64")4 V1 V4 l; B7 R+ l
    set(CMAKE_PREFIX_PATH "${QT_MSVC_PATH}/lib/cmake")
      x* y0 ]% h! Z6 S然后再次运行 cmake 指令或者使用CMake GUI重新运行,构建文件夹下便能正常生成.sln项目文件。
    9 G! Q5 ?; ~# {* {, @VS中编译好后,运行时会提示无法找到Qt相关的dll导致程序不能正常运行。解决办法包括:
    . ?& i7 L3 \/ |- `) p* `1. 设置VS选项,将Qt的dll路径包含进去;5 |; s1 R6 {5 F  b% `" j7 K
    2. 将Qt相关dll拷贝到编译输出文件夹;
    9 g3 `  l; {% i- d: U/ w  r. n 3. 设置CMake,使其能自动复制所需要的dll。
    ( j" O: g! O; J7 n  w/ v这里介绍第三种方式,原理是借助Qt自带的windeployqt.exe程序自动部署程序所需dll到目标文件夹。具体操作为,在项目根目录的CMakeLists.txt最后添加部署dll的指令:' l" N, l6 I7 q# ]9 ~2 D- M
    set(QT_BIN_PATH "${QT_MSVC_PATH}/bin")
    8 R" O: p! C) \0 g! Efunction(windeployqt target)" G  g% l7 l9 |8 i0 N2 @
    # POST_BUILD step* I  m5 u( p/ X* J2 Y0 u
    # - after build, we have a bin/lib for analyzing qt dependencies
    % @' u1 s6 m; F2 C# - we run windeployqt on target and deploy Qt libs
    ! V* p7 E; C8 R  N7 e3 h7 Jadd_custom_command(TARGET ${target} POST_BUILD
    ! z6 Y% n! c& i3 t0 B( gCOMMAND "${QT_BIN_PATH}/windeployqt.exe"
      Q8 t+ i( |5 K+ `) P--verbose 14 H+ O% o/ |1 l7 D4 s
    #--release # uncomment this line if built with Release! W3 X- _) }8 x0 `: X. Y" ]
    #--no-svg
    7 ]" j2 p, o2 M- j  [- F: c#--no-angle
    4 [  V& n+ Z( o#--no-opengl  J" H& x0 e& P1 K: f
    #--no-opengl-sw# B9 ?) M0 Q, o) [. E* ]( @) r
    #--no-compiler-runtime# R2 w& U6 S2 _! x  K6 ~
    #--no-system-d3d-compiler0 B7 Q7 R) `  [7 s$ _: ?/ a
    \"$\"  Z3 n6 x" U8 z7 V/ ]8 @# }, a
    COMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ...". l1 p  x7 J- v9 B9 F# ^8 ~
    )2 b. i9 Z0 t. i6 P9 k+ ]$ u
    endfunction()* o3 s) E% t4 j
    if (WIN32)8 B& G9 Z! x' D) c# l- D
      windeployqt(${PROJECT_NAME})
    & x) d8 {7 W1 vendif()最后,转换成VS项目时,默认是Console项目,运行时会有cmd窗口。一个解决办法是在生成可执行文件时设置目标为 WIN32:& ?. y0 N% M) F# a$ |" r
    add_executable(${PROJECT_NAME} WIN32 xxxx)6 \2 n+ s, B6 w1 o" S2 S, F& k# \( Z
    一个完整的Qt 5项目CMakeLists.txt返回目录以下是一个适用于Windows平台的Qt 5项目完整CMakeLists.txt,实际使用时请替换名字和Qt 5安装路径等:
    ( y' [) B! Y8 I5 _- Ocmake_minimum_required(VERSION 3.7)$ U" q; x9 E/ K& ?" Q/ n+ O
    # 请将myproject改成实际的应用名字
    ' L) g) G8 q& J- vproject(myproject LANGUAGES CXX)
    7 [2 V5 F' h: H# D( v' w* S! m0 mset(CMAKE_INCLUDE_CURRENT_DIR ON)
    " [. F; Z5 }( m8 H/ }# 请更改为实际的Qt安装目录
    % x0 c7 x. |- ]) m  zset(QT_MSVC_PATH "C:\\Qt\\Qt5.12.8\\5.12.8\\msvc2017_64"), b+ Y8 [) H1 B, x8 G
    set(CMAKE_PREFIX_PATH "${QT_MSVC_PATH}/lib/cmake")
    . p& x. ]( w/ u( cset(QT_BIN_PATH "${QT_MSVC_PATH}/bin")
    & w% O( z" w3 I) N, X8 {set(CMAKE_AUTOUIC ON)
    & O9 i4 Z4 Q+ r% {% w& {5 \4 V( _! zset(CMAKE_AUTOMOC ON)7 F; m; e* c- H5 X- Z! j2 M8 t; q
    set(CMAKE_AUTORCC ON)
    6 ?8 q2 e& p0 s, _$ uset(CMAKE_CXX_STANDARD 11): t1 ]: v# ~6 z2 E; e# r  g
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    , A* q8 C' r# n7 o2 Tfind_package(Qt5 COMPONENTS Widgets REQUIRED)7 i# Q) N% A4 \! z$ V
    # 默认Release构建
    & K4 G0 ]' y' Gif (NOT CMAKE_BUILD_TYPE)
    / k* w$ ?+ p  v" u    set( CMAKE_BUILD_TYPE "Release" )5 O2 t+ K/ H' z6 Q/ s/ ~
    endif()( P+ w$ S  z& \: `& a
    message("build type: ${CMAKE_BUILD_TYPE}")8 T2 N; _2 g/ O4 H
    # 按照自己的项目结构添加文件' |9 u& z; u* h! Y
    # 也可使用file/aux_source_directory批量引入,注意不要引入自动生成的文件!1 p) _" J$ i& b4 P+ u+ [
    add_executable(${PROJECT_NAME} WIN32; I4 ]% G& a  Q: i+ h/ D* q
      main.cpp: S4 {( L3 N2 V$ p
      mainwindow.cpp8 r4 I- j$ G+ e% T, M' [  d
      mainwindow.h+ V; Q1 T4 m0 N; E0 ^& A7 H2 ~
    )7 ]9 j* h4 U3 A5 n2 {" j8 }! e  G
    target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)' Z8 b6 h8 l1 g5 D( G
    function(windeployqt target)
      ~, T/ U5 V) a- @' l8 x4 T# POST_BUILD step6 z( R6 ?% M7 \+ q
    add_custom_command(TARGET ${target} POST_BUILD
    4 B' {/ m! i7 K- \COMMAND "${QT_BIN_PATH}/windeployqt.exe"0 d: v, `* D+ a  G/ d) B) W0 f- _
    --verbose 1
    ( y4 L$ `( s- [, Z- k4 u! W#--release 8 I! C" C( ?3 L
    #--no-svg' |: A. B$ V. O
    #--no-angle: z7 Y; l. ^( e* h: v6 L0 d
    #--no-opengl7 g. z, d, ~1 |7 _5 U
    #--no-opengl-sw3 g6 Q8 A, L; X# m3 W
    #--no-compiler-runtime! A: T5 y: J' L' l& r! m
    #--no-system-d3d-compiler
    ! F0 b; p& t0 m\"$\"
    3 `1 e* f, N' y) `COMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ..."
    " n- G8 Z" m6 _); \4 w) J; R# ^* T% \- k5 E0 x* ^$ ^
    endfunction()& b, F) m& ^+ q  z9 ^6 b
    if (WIN32)! f) l: t* k$ @$ q0 o0 o+ _
      windeployqt(${PROJECT_NAME})
    " G4 n, C1 U  L( p. iendif()
    - |: q" |, L' g# h! R8 M2 @- S````通过上面的配置,我们的Qt项目既可在Qt Creator中正常编译运行,也可在CLion/Visual Studio中正常编译运行而 无需安装Qt插件。* H9 }4 G% d  ]4 Y) |9 l
    参考返回目录1. CMake官网3 N( E& }" k5 J$ `5 B! Z
    2. CMake教程. h$ d- q3 N' {" |0 V
    3. CMake FAQ2 z5 R8 E: l8 v% g- [  p- M
    4. CMake指定编译器1 ]5 R- J+ V+ a/ C1 x# C9 `2 E1 C
    AD:【国外VPS推荐】 搬瓦工三网回程CN2 GIA VPS,季付46.87$打赏赞(3)
  • 本帖子中包含更多资源

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

    x
    回复

    使用道具 举报

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

    本版积分规则

    Copyright © 2001-2013 Comsenz Inc.Powered by Discuz!X3.4( 沪ICP备18024137号 )
    快速回复 返回顶部 返回列表