VS Code 为 Clang for MSVC 配置 cmake & cmake tools

介绍

  在windows平台上,由于平台API差异过大,一般为linux设计的项目(POSIX兼容)无法通过MSVC的编译,而是会报非常多的头文件错误。如果要修改,工程量将巨大。Windows平台上,主要有两个类POSIX兼容平台,可以在Windows系统上编译运行为Linux编写的程序(功能支持不完整)。

  1. MinGW Minimalist GNU for Windows: 是将GCC编译器和GNU工具链套件移植到Windows平台下的产物。
  2. LLVM/Clang for Windows: Clang编译器对Windows Target的适配。由于LLVM框架的结构,只需要开发Windows平台对应的后端,而不需要进行迁移。LLVM在Windows平台的后端主要采用Visual Studio的MSVC编译器。

  cmake是一个跨平台项目编译工具,通过CMakeLists.txt文件,可以方便地管理项目文件,并灵活地组织编译。根据工具链的不同,编译结果可以应用于各个平台上。例如,Linux系统中,cmake可以编译出Makefile,并交给linux平台的make程序进行编译。

  一个项目需要在Windows平台上编译,但是是面向linux编写的(Makefile),这时候就需要使用Windows平台上的工具链进行编译。但是,多文件项目管理复杂,一个一个文件进行编译较为繁琐,这时候,就可以使用cmake工具辅助进行编译

  笔者是VS Code重度依赖用户,所以在VS Code上利用cmake tools进行配置。当然也可以使用命令行或是cmake-gui进行配置,只不过cmake tools更加集成和方便。

安装Clang-CL & CMake

Clang-CL for MSVC可以在Visual Studio的组件中找到

VS Code 为 Clang for MSVC 配置 cmake & cmake tools_第1张图片

CMake可以在官网下载,安装后注意检查PATH,是否添加cmake

CMake & Toolkits

我们应当明确几个编译概念:

  • Build System 编译系统:又称为Generator 生成器,是编译工具根据规则编译、链接文件的系统,按照是否集成交互,可分为;
    • IDE Build Tool Generators 用于IDE的Build System,生成的项目可以直接被IDE打开、编辑,例如Visual Studio Generators
    • Command-Line Build Tool Generators,使用命令行进行编译构建,有编译工具链即可工作,不需要IDE支持,例如,Make构建系统(即Linux中使用Makefile进行构建的系统),以及Ninja(一套更轻量的命令行构建系统,是CMake Tools 的默认构建系统)
  • Build Toolkits 编译工具链:是直接参与编译、生成可执行文件的一系列工具,包括Compiler 编译器, Linker 链接器等。主流的工具链如下:
    • GNU/GCC: GNU项目组的编译工具链,主要运用于Linux系统,其在Windows上的迁移版本称为MingGW
    • LLVM/Clang:LLVM编译基础设施,采用模块化设计,前后端分离工作,能够很好地适配多种前端语言和后端平台,是越来越流行的编译工具链
    • Visual C++:微软开发的C/C++编译工具链,集成在Visual Studio上,主要用于Windows平台下的程序开发,即MSVC

编译系统使用编译工具链,按照开发者指定的编译规则进行程序的编译链接。那么,CMake属于哪里?CMake 属于更上一层的编译工具,使用CMake,可以生成任何一种适配的Build System所需要的规则,然后再调用这些Build System进行程序编译。

配置 cmake toolkits

在VS Code中,安装插件CMake Tools,并在项目目录中创建CMakeLists.txt文件,插件被激活后,状态栏会显示CMake Toolkits, Build Variant, Build Target等信息。如果是第一次在项目中使用插件,Toolkits工具链会显示No Kit Selected,单击该按钮,出现选择框。

VS Code 为 Clang for MSVC 配置 cmake & cmake tools_第2张图片
初次配置,点击Scan for kits,工具会自动扫描电脑上安装的工具链。

Clang for MSVC 对应有四条(名称已经被我修改,正常情况下还有版本信息),Build Target有x86和x64,命令行接口有GNU CLI和MSVC CLI。

接下来,检查工具链配置参数,Ctrl+Shift+P,打开Command Palette,输入cmake kits -> 编辑用户本地CMake 工具包,这会打开一个json文件。
VS Code 为 Clang for MSVC 配置 cmake & cmake tools_第3张图片

部分配置如下:

  {
    "name": "Clang 14.0.5 (GNU CLI) for MSVC (VS Community 2022 Release - x86)",
    "visualStudio": "8b689476",
    "visualStudioArchitecture": "x86",
    "compilers": {
      "C": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\Llvm\\bin\\clang.exe",
      "CXX": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\Llvm\\bin\\clang.exe"
    }
  },
  {
    "name": "Clang 14.0.5 (MSVC CLI) for MSVC (VS Community 2022 Release - x64)",
    "visualStudio": "8b689476",
    "visualStudioArchitecture": "x64",
    "preferredGenerator": {
      "name": "Visual Studio 17 2022",
      "platform": "x64",
      "toolset": "ClangCL"
    },
    "compilers": {
      "C": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\Llvm\\x64\\bin\\clang-cl.exe",
      "CXX": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\Llvm\\x64\\bin\\clang-cl.exe"
    }
  },
  • 对于MSVC CLI,Scan kit默认配置为MSVC Generator,注意检查toolset,必须修改为ClangCL,若为host=xxx,则仍将通过传统MSVC工具链编译,仍会遇到API不适配问题
  • 对于GNU CLI,默认配置为Ninja Generator,是一套轻量级、高效率的命令行构建系统,也可以根据需要修改preferredGenerator为MSVC工具链

编译与常用选项

状态栏选项

在这里插入图片描述

  • Build Variant (构建变体,编译选项……XD, anyway):选择工具链的编译输出模式,常见的有Debug调试模式(包含调试信息)、Release发布模式(去除调试信息,增加优化)
  • ToolKits 工具链:为项目选择编译工具链(跨平台项目使用交叉编译工具链)
  • Build 编译:点击编译(Not install)
  • Build Target:编译目标,选择编译哪个项目,默认为[all]全部编译,但是速度很慢,注意更换
  • Debug\Run:调试、运行,不多介绍

Command Palette 命令选项卡

使用命令选项卡可以进行更加完整的配置,常用的有两个:

  • CMake Clean:清除编译文件
  • CMake Install:进行编译安装,将按照CMakeLists.txt指定的安装配置进行生成工具的安装

常见问题与解决方案

Include error - file not found

IDE中显示这个错误,通常有两种来源:

  1. Compiler 编译器错误 (似乎通常显示gcc):此类问题通常不会通过build,是编译阶段报错导致,需要找到include失败原因(没有配置引用等),解决后有时需要删cmake cache重新检测,如果能通过编译,一般此问题会消除。另一种可能是没有执行cmake configure,在command palette 进行cmake: Configure即可修复。
  2. 仅显示 file not found而没有其他提示,这是C/C++ Clang adapter 的报错,这个插件功能完全冗余,而且配置未知,直接卸载即可。

示例

在一个目录下,创建如下文件

G:.
│  CMakeLists.txt
├─include
│      hello_lib.h
├─lib
│  │  CMakeLists.txt
│  ├─include
│  │      hello_lib.h
│  └─src
│          hello_lib.c
└─src
        hello.c
// hello.c
#include 
#include 
#include "hello_lib.h"

int main() {
	printf("Hello World!\n");
	DbgPrint("%s\n", "Hello World");	// defined in hello_lib
	return 0;
}
// hello_lib.h
#include 
#include 
#include 
#include 

void DbgPrint(char* FormatStr, ...);
// hello_lib.c
#include "hello_lib.h"

void DbgPrint(char* FormatStr, ...)
{
	char dbgout[1000];
	va_list vaList;

	va_start(vaList, FormatStr);
	sprintf(dbgout, FormatStr, vaList);
	OutputDebugStringA(dbgout);
	va_end(vaList);
}

然后配置CMakeLists:

root

cmake_minimum_required(VERSION 3.0)

project(HELLO)

add_subdirectory(lib)

aux_source_directory(src src_dir)
add_executable(hello ${src_dir})

target_include_directories(hello PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(hello PUBLIC hello_lib)
  • add_subdirectory 增加子项目
  • target_link_libraries 链接库,hello_lib在子项目中定义

lib

cmake_minimum_required(VERSION 3.0)

project(HELLO_LIB)

aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src src_dir)
add_library(hello_lib STATIC ${src_dir})

target_include_directories(hello_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
  • add_library(STATIC)添加静态库

最后,build,输出结果:

[build]   hello_lib.vcxproj -> G:\C\Cmake Test\build\lib\Debug\hello_lib.lib
[build]   hello.c
[build]   hello.vcxproj -> G:\C\Cmake Test\build\Debug\hello.exe
[build] Build finished with exit code 0

你可能感兴趣的:(C,windows,cmake,vscode)