33

CMake后置-IDE的选择和VSCode配置细节

 4 years ago
source link: http://alanli7991.github.io/2019/12/10/CMake10不同IDE的差别和选择/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

IDE的概念是集成开发环境(Integrated Development Environment)

所谓集成就是集中了编译配置、编译、调试等功能,例如Xcode、Android Studio、CLion等

方便开发者专注于代码逻、快速实现功能或者减少指令输入

不过随着集成开发环境加入了越来越多的东西,变得越来越卡,现在也出现了简化的趋势,例如VSCode的流行

CLion如何工作

使用 CLion 创建一个 “New Project —— C++ Executable” 的工程,可以发现其根目录为

----Project
    --cmake-build-debug
    --CMakeLists.txt
    --main.cpp

对应该系列的 第一篇文章HelloWorld 可以发现 CLion也是使用CMake来组织工程

点击菜单栏 “Run” 存在 “Build、Run、Debug” 三个选项,指定一个断点,然后点击Debug就可以进行调试

操作工程你会发现以下几个重点

  • “cmake .” 产生的一系列文件被放在了 cmake-build-debug
  • 在根本的任何改动,都会使得CMakeLists.txt变化,并且刷新工程
  • 和Xcode不一样,CLion没有模糊编译、运行、调试的概念
  • CLion中 Build不会执行程序、Run的话断点不会停止、Debug才是Xcode的 Command+R

由于CLion 变的越来越卡了(2018年6月——2019年9月),导致很多人选择使用更加轻量级的VSCode来开发

VSCode的配置、编译、调试

VSCode就对程序员的专业程度要求比较高了,下载官方的C/C++插件之后

根据 官方教程 可以完成配置、编译、调试三个步骤

命令台(Command Palette)和命令行(Shell Command)工具code

命令台有两种打开方法

  • 点击菜单栏 “View —— Command Palette”
  • 使用组合键 Shift + Command + P

打开 “Command Palette” 可以执行 “Shell command: Install ‘code’ command in PATH” 来安装code指令

code指令把一个空文件夹配置成C/C++工程的基本命令,在完成配置后存在三个文件,目录结构如下

----HelloWorld
    --.vscode
        --c_cpp_properties.json
        --tasks.json
        --launch.json
文件名 作用 英文原文 c_cpp_properties.json 工程配置文件,让这个目录拥有基本的Workspace、Project的能力 (compiler path and IntelliSense settings) tasks.json 编译文件,指定使用哪种目录编译 (build instructions) launch.json 调试文件,指定调试哪个程序,调试前提是编译结果是Debug配置 (debugger settings)

工程配置文件 c_cpp_properties.json

打开 “Command Palette” 执行以下任意一个指令来配置基本的Workspace或Project的能力

  • “C/C++: Edit Configurations (UI)” 可以使用可视化界面配置
  • “C/C++: Edit Configurations (JSON)” 可以使用JSON文件配置

注意如上篇文章所陈述,工程和编译的概念很模糊,不同平台和语言的定义不完全一致,所以职责划分并不是绝对的

如果采用可视化界面配置,最终生效的还是 “.vscode/c_cpp_properties.json” 文件

//这个文件是不能加注释的,不然VSCode会报解析失败,这里加注释只是为了讲解
{
    //配置的数组,成员是字典
    "configurations": [
        {
            // 配置名称
            "name": "Mac",
            // 头文件目录 (重要)
            // 1. 当人为引用HelloWorld目录以外的头文件时需要自己新增配置
            // 2. 当引用第三方库时需要自己新增配置,例如OpenCV的 ${OpenCV_INCLUDE_DIRS}
            "includePath": [
                "${workspaceFolder}/**"
            ],
            // 本地变量
            "defines": [],
            // Mac系统的系统库
            "macFrameworkPath": [
                "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks"
            ],
            // 编译器的路径
            "compilerPath": "/usr/bin/clang",
            // 编译器的C语言版本 (重要)
            "cStandard": "c11",
            // 编译器的C++版本 (重要)
            "cppStandard": "c++17",
            // 自动补全和智能提示使用哪个
            "intelliSenseMode": "clang-x64"
        }
    ],
    //c_cpp_properties 配置的版本
    "version": 4
}

编译任务文件 tasks.json

打开 “Command Palette” 执行 “Tasks: Configure Default Build Task”

然后选择“Create tasks.json file from template —— Others” 来配置默认的编译任务 “.vscode/tasks.json”

编译的配置就没有UI界面了(怀疑是懒得做),为了体现VSCode的高自由度(对新人不友好)

这里举例了 官方文档的配置示例 、CMake的HelloWorld、模仿CLion指令三种配置,说明了不同指令之间的关系

命令 作用 参考配置 clang 编译文件,最基本的指令 官方的配置示例 cmake & make cmake完成配置,make进行调度clang CMake的HelloWorld clang cmake进行配置,cmake调用make使用clang进行编译 CLion

其中CLion的作法才是比较成熟的作法,这里仅仅是举例整个演进的过程

官方配置示例(不重要)

官方配置是使用最基本的clang指令,完成文件编译

//这个文件是不能加注释的,不然VSCode会报解析失败,这里加注释只是为了讲解
{
  "version": "2.0.0",
  "tasks": [
    {
      // 任务名称
      "label": "Build with Clang",
      // 任务是一个Shell命令
      "type": "shell",
      // 使用 clang++ 命令
      "command": "clang++",
      // 对命令传入的参数 “clang++ -std=c++17 ....”
      "args": [
        "-std=c++17",
        "-stdlib=libc++",
        "main.cpp",
        "-o",
        "main",
        "--debug"
      ],
      // 设置这个任务是默认的任务,可以被快捷键直接启动
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    //此处可以添加别的Task
    ....
  ]
}

CMake和Make指令分别使用 (不重要)

当文件结构足够多以及目录结构十分复杂的情况的时候,使用一条clang编译指令的参数就过于复杂

可以使用make文件来调度clang,可以参考 CMake配置完成后的 CMakeFiles/HelloWorld.dir/build.make 文件

{
  // 任务名称
  "label": "Build with CMake & Make",
  // 任务是一个Shell命令
  "type": "shell",
  // 1. 使用 cmake 进行配置
  // 2. 使用 make 指令进行编译
  "command": "cmake . && make",
  "args": [ ]
}

文件中使用的指令是 XcodeDefault.xctoolchain/usr/bin/c++ ,使用man之后可以看到是clang的一个别名指令

CMakeFiles/HelloWorld.dir/main.cpp.o: ../main.cpp
	.......
	/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++  .....
  ......

CLion的CMake流程(成熟工程的作法)

由于CMake本身就是对make的包装,那么可以把make指令本身也对大家隐藏起来,只使用cmake

例如CLion 就是仅使用 cmake 组织工程,可以分为配置和编译两步

配置过程在 New Project的过程中已经完成,我们没有抓到日志但是可以模拟出来

{
  // 任务名称
  "label": "Configure with CLion CMake",
  // 任务是一个Shell命令
  "type": "shell",
  // 模拟 CLion 新建工程文件
  // 1. 创建 cmake-build-debug 用于存放CMake的临时文件
  // 2. 切换到 cmake-build-debug
  // 3. 使用 cmake 指令配置 CMakeLists.txt 所在目录
  "command": "mkdir \"${workspaceFolder}/cmake-build-debug\" || cd \"${workspaceFolder}/cmake-build-debug\" && cmake ../.",
  "args": [ ]
}

而在编译阶段可以看到编译指令

"~/Library/Application Support/JetBrains/Toolbox/apps/CLion/ch-0/192.6262.62/CLion.app/Contents/bin/cmake/mac/bin/cmake" --build ~/Desktop/HelloWorld/cmake-build-debug --target main -- -j 2

我们在VSCode中使用Task来模拟,配置如下

{
  // 任务名称
  "label": "Build with CLion CMake",
  // 任务是一个Shell命令
  "type": "shell",
  // 模拟 CLion 编译工程目标
  // 1. 使用 cmake 指令替代 make 进行编译,底层还是调用的make
  "command": "cmake",
  // 2. 给 cmake 传入参数
  "args": [
      // 3-1. 指定编译配置所在目录 cmake参数
      "--build",
      // 3-2. 编译配置所在的目录取决于 CLion 生成时指定的目录
      "${workspaceFolder}/cmake-build-debug",
      // 4-1. 指定编译目标 cmake参数 
      "--target",
      // 4-2. 编译目标由 CMakeLists.txt 内 add_executable 决定
      "main",
      // 5-1. 透传参数给底层make
      "--",
      // 5-2. jobs 任务数 make参数
      "-j",
      // 5-3. 最多并发2个job
      "2"
  ]
}

调试启动文件 launch.json

打开 “Command Palette” 执行 “Debug: Open launch.json”

选择 “C++(GDB/LLDB)” 就是生成文件 “.vscode/launch.json” 可以用来调试采用Debug编译的可执行程序

//这个文件是不能加注释的,不然VSCode会报解析失败,这里加注释只是为了讲解
{
  // 版本号
  "version": "0.2.0",
  "configurations": [
    {
      // 名称
      "name": "(lldb) Launch",
      // 调试类型 cpp debug 
      "type": "cppdbg",
      // 请求分为 launch 和 attach,后者是附着到已经运行的程序上
      "request": "launch",
      // 被调试的程序(重要)
      // 程序所在的位置,根据tasks编译的结果决定
      // 如果采用上述的 cmake 和 clion 的指令就会和官方的有区别
      "program": "${workspaceFolder}/helloworld.out",
      // 启动时传入的参数
      "args": [],
      // 是否在入口的默认启动一个断点
      "stopAtEntry": true,
      // 工作目录,即 program 的io时的根目录
      "cwd": "${workspaceFolder}",
      // 环境变量
      "environment": [],
      // 是否启动额外的窗口
      "externalConsole": true,
      // 微软调试引擎 microsoft/MIEngine 接入的模式
      "MIMode": "lldb",
      // 日志输出
      "logging": {
        "trace": true,
        "traceResponse": true,
        "engineLogging": true
      },
      // 调试前重新编译(重要)
      // 因为调试(Debug)是启动已经编译好(Build Success)的程序
      // 如果想类似IDE CLion和Xcode 每次调试改动前都重新编译
      // 可以将编译任务放在Launch之前
      "preLaunchTask": {
        "task": "echo",
        "type": ""
      }
    }
  ]
}

结语

在对配置、编译、调试的整个流程熟悉了之后,如果选择 “VSCode + CMake” 进行开发可以总结为以下流程图

+--------------------------------------------------------------------------+
|                                                                          |
|                             Source Code                                  |
|                                                                          |
+--------------------------------------------------------------------------+

+--------------------------------------------------------------------------+
|                                 VSCode                                   |
+--------------------------------------------------------------------------+

+------------+ +--------------------------------------------+ +------------+
|            | |                                            | |            |
| c_cpp_     | |                tasks.json                  | |   launch   |
| properties | |                                            | |   .json    |
| .json      | |                                            | |            |
|            | |                                            | |            |
|------------+ +--------------------------------------------+ +------+-----+
                                                                    |
              +--------------------------------------------+        |
              |                                            |        |
              |                  CMake                     |        |
              |                                            |        |
              | +----------------------------------------+ |        |
              | |                                        | |        |
              | |                 make                   | |        |
              | |                                        | |        |
              | |    +------------------------------+    | |      Debug
              | |    |                              |    | |        |
              | |    |           clang              |    | |        |
              | |    |                              |    | |        |
              | |    +------------------------------+    | |        |
              | +----------------------------------------+ |        |
              |                                            |        |
              +--------------------+-----------------------+        |
                                   |                                |
                                   v  Build                         |
               +-------------------+---------------------+          |
               |                                         |          |
               |             Executable(Target)          |          |
               |                                         | <--------+
               |                                         |
               +-----------------------------------------+

请问老板还招人么(/ω\)

aqiAvyU.jpg!web支付宝

FFbQnye.jpg!web微信


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK