前言
最近在做CMU15445,其实最痛苦的就是配环境,众所周知,VSCode的C/C++插件功能虽然全但是速度不怎么理想,写一点东西反应半天,非常之不友好。我们希望换到更加快速,提示更加智能的clangd上。
之前在网上看到了一大堆关于怎么配置LLVM家族的C/C++环境的教程,其中往往充斥着各种神鬼莫名的配置参数,对新手的劝退作用立竿见影。我理想的所谓新手教程应该是这样的:
- 可控性高:偏好GUI > 命令行 > config
- 上下文完整:一步解决一个特定问题,不引入额外的负担
- 可复现性强:每个步骤应该立刻有可供检查的结果,易于排查错误
好吧说来说去其实说的就是那些上来咣咣贴个config.json走人的。总之这是一个基本不使用配置文件的、绝对新手友好的入门教程。
环境要求
本教程基于WSL Ubuntu 22.04,理论上在其它Linux发行版以及MacOS中也是通用的。至于Windows?WSL2就行,目前重度使用4年,所有的问题基本上都能解决,嫌弃兼容不好什么的都是借口,虚拟机不比这麻烦多了?
依赖的软件包,基本上就是LLVM全家桶+cmake
:
clang
:我们使用的编译器,拥有更加人性化的报错clangd
:一个C/C++的Language Sever后端,薄纱C/C++ Toolslldb
:调试工具,一家人就要整整齐齐cmake
:构造工具,因为clangd
需要读取compile_commands.json
才能提供服务
Ubuntu使用下面的指令进行安装 (别先急着着敲命令看下面)
sudo apt install clang clangd lldb cmake (先看下面那段话别急着敲)
来自后期的提示:如果只是针对cmu15445的话那么需要下载clang-14,如果你希望日常开发也用这套的话,推荐安装最新的19和稳定版的17这两个版本,也就是最多可选装3个版本,看个人的选择。当然怎么安装的话后面会提到。
LLVM 17 & 19(DLC)
首先声明一点,越新的clangd肯定要配合越新的gcc使用(比如clang-19对gcc-13.2),如果你和我一样是ubuntu 22.04LTS的话,那么你APT源里面的gcc只支持到12,也就是说一键式安装最多到sudo apt gcc-12 g++-12
,想体验最新的gcc13需要自己去编译,这里就不多说了,主要讲怎么快捷安装LLVM-17和LLVM-19。
首先我们先进入清华大学镜像站的LLVM APT软件仓库。如果你需要19那么直接使用默认的就行,需要17则在脚本后面输入17即可(也可以像我我全都要,到时候选下工具链就行了),注意一定要用镜像,非镜像源就算开了VPN同样会下载失败。
vscode
然后是VSCode中需要的插件:
只需要这四个就可以了。其中CodeLLDB
需要下载一个文件,几乎是一定会下载失败的。
超时之后点击弹出来的消息,手动下载,然后再手动进行安装。
在弹出菜单里选择你下载的那个(后缀为.vsix
)即可。注意在WSL环境下你可以从/mnt
文件夹下访问Windows文件,假如你直接下载在系统自带的下载文件夹里,那就是在/mnt/c/Users/<Username>/Downloads/
里。装好了之后会弹出重载VSCode的窗口。
到这里前期准备就结束啦。
开始
如果还没安装gcc和g++建议先安装,安装最新的即可,即sudo apt install gcc-13 g++-13开始试,找不到就gcc-12,g++-12直到安装上。
随便找一个空文件夹打开,然后Ctrl+Shift+P
或者你自定义的快捷键打开下拉菜单,搜索cmake
,选择Quick Start
:
给你的项目起个名字,类型选择Executable
,第一次打开cmake
可能还会问你一些编译套件的选择问题,选择clang
即可,记得看清楚后缀免得用错。
打开自动生成的main.cpp
,发现clangd
已经在运行了,就是这么简单。
打开clangd
输出,看看clangd
是否真的如此智能。
并没有,clangd
抱怨说找不到编译数据库!那么这个所谓的编译数据库在哪里呢?其实就在cmake
生成的build
文件夹里:
我们要让clangd
识别项目的编译数据库,于是终于到了我们第一次和配置文件的交锋。打开设置,搜索clangd
,在Arguments
配置项中输入参数--compile-commands-dir=${workspaceFolder}/build
,然后点确定。
这个参数相当直观,就是告知clangd
我们的编译数据库在工作区根目录的build
文件夹下。
重启VSCode,再次查看clangd
输出,发现成功读入了参数,并且没有报错信息,同时能够使用cmake
输入的编译指令即为配置成功。
额外补充
值得一提的是,在很多教程里面没有提到如果你下载了CMake language support这个软件,那么会需要一个.net运行环境依赖,这个依赖如果你只靠vscode同样是不能下载下来的,需要apt install dotnet
的运行环境(或者连sdk一起下载),除此之外,如果你在vscode输出这栏打开CMake/Build这插件的输出,大概率会看见说build失败,缺乏ninja(然而实际上是构建成功的,只不过是原生cmake构建),当然也可以不用管,但是我非常推荐安装ninja,它类似于CMake但速度比CMake快了一个数量级,并且安装并不麻烦。
sudo apt-get install ninja-build
ninja --version
同时还推荐下载github copilot
,感受人工智能帮你补充代码和注释(前提已经弄好了github pro),接下来就可以正式开始了。
运行与调试
按一下底部菜单中的build
键,看看我们生成的可执行文件在哪里(一般就在build
下面):
按F5
键,VSCode会报错,同时在根目录下生成一个.vscode
文件夹以及launch.json
。打开这个json文件,将其中唯一一个需要我们配置的(也是本文第二次跟配置文件打交道)program
项改为cmake
生成的可执行文件的位置(按照惯例,根目录的名字和项目的名字应该是同一个,否则就需要手动指定)。
再按一次F5
,终端返回了一句亲切的Hello World
。
上个断点试试:
完美,到这里就算搞定了,同理在win10下也一样。
再附上一些常用的的CMakeLists:
多源文件配置头文件的搜索路径
注意,本章本质上是验证工具链是否配置成功。
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_SOURCE_DIR}/include/server)
include_directories(${PROJECT_SOURSE_DIR}/thirdparty)
同样需要告诉编辑器怎么去寻找执行文件,对于.vscode来说则是:
"program": "${workspaceFolder}/build/${fileBasenameNoExtension}",
对于该种工程结构:
├── build
├── CMakeLists.txt
├── include
│ └── sayHello.h
├── main.cpp
└── src
│ └── sayHello.cpp
对应的cmake添加:
include_directories(include)
add_executable(main main.cpp src/atmp.cpp)
对应的头文件如atmp.h和atmp.cpp分别在include和src里面,则只需要下面即可:
#ifndef _ATMP_H
#define _ATMP_H
#include<iostream>
void sayHello();
#endif
atmp.cpp
#include"atmp.h"
void sayHello()
{
std::cout << "Hello" << std::endl;
}
main.cpp
#include "atmp.h"
int main() {
sayHello();
return 0;
}
即可成功编译运行。
额外补充
如果你没有用教的那个方法在vscode上面build程序而是自己去cmake的话,请记得指定所选的工具链(课程使用的是clang-14),如下:
#!/bin/sh
rm build -r
mkdir build
cd build || exit
cmake -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Debug ..
make -j "$(nproc)"
这样就不用每次都手工敲cmake和make了,运行脚本即可,记得做实验的时候vscode的工具链选择clang-14。如果对多工具链有问题的话可以看看我这篇文章:Linux下多Clang工具链的踩坑,关于传参的话可以看这篇文章:VScode CMake Tools 传递命令行参数
VPN的使用
知乎有对应的脚本来开启vpn,但有些细节没有说清楚。
#!/bin/bash
host_ip=$(cat /etc/resolv.conf |grep "nameserver" |cut -f 2 -d " ")
export ALL_PROXY="http://$host_ip:7890"
当你做完这些,一定要在对应的.zsh文件里面最后对端口配置文件进行source,不然无法生效。