Linux+VScode搭建项目开发环境以及cmake

2023/11/18​
由于项目需要使用C++完成最后一步的模型转换操作,并且需要模型上板,其中都需要用到cmake相关知识,于是就开始了cmake相关的学习。由于之前运行C++项目使用的都是集成环境,可以说是一键运行,并不了解从.cpp文件到可执行之间还需要经过复杂的预处理、编译、链接等过程,所以到make阶段遇到的问题层出不穷,且解决方案毫无头绪。从csdn查到的解决方法通常也是碎片化的,并不能对症下药,有时甚至会因为解决方法不对导致程序进一步出现更多的错误,因此深感需要系统地学习一下make以及cmake原理。

  • 参考:
    g++参数:​https://zhuanlan.zhihu.com/p/104197249

1. C/C++编译流程

请添加图片描述

预编译

使用预编译器处理.cpp源文件和.h头文件,最终生成一个.i的文件。其作用就是处理源码中以#开头的预编译指令,如#include、#define等。

g++ -E hello.cpp -o hello.i

#include 就是将包含的头文件全部展开到#include的位置,所以一个.c源文件如果包含多个头文件,头文件的顺序是需要注意的地方

编译

编译的过程就是将 预处理 完的文件进行一系列的词法分析、语法分析、语义分析及优化,最后生成 .s 汇编代码文件。编译过程等价如下命令:

g++ -S hello.i -o hello.s

编译过程是整个程序构建的核心部分,也是最复杂的部分之一。

汇编

汇编器是将汇编代码转变成机器可以执行的指令, 每一条汇编代码几乎都对应着一条机器指令。最后生成一个 .o 目标文件。汇编过程等价如下命令:

g++ -c hello.s -o hello.o

汇编器的汇编过程相对简单一些,只需要根据汇编指令和机器指令对照表一一翻译就可以了。

2. 链接

链接的作用就是将编译出来的目标文件和代码所用到的库文件一起打包成一个可执行文件的过程。例如hello.c中的打印函数printf,这个函数不是凭空出现的,在链接的过程中就要连同对应库文件一起打包,最终可执行文件才能正常运行。

静态库vs动态库

静态库和动态库的载入时间不一样。

  • 静态库的代码在编译的过程中已经载入到可执行文件中,所以最后生成的可执行文件相对较大。
  • 动态库的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,所以最后生成的可执行文件相对较小。

两者最大的区别是,静态库链接的时候把库直接加载到程序中,而动态库链接的时候,它只保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度和降低程序的耦合度。

  • 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要改静态库。
  • 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因而在程序运行时还需要动态库存在。

无论静态库还是动态库,都是由.o文件创建的。

实战:生成静态库

项目结构:

.
├── include
│   └── print.h
├── main.cpp
└── src
    └── print.cpp
# 汇编,生成print.o文件
g++ print.cpp -c -I../include

# 生成静态库libprint.a,归档
ar rs libprint.a print.o

# 回到根目录
cd ..

# 链接,生成可执行文件static_main
g++ main.cpp -lprint -Lsrc -Iinclude -o static_main

参数注解:

  • -I:头文件
  • -l:静态库,注意名称是print,掐头去尾
  • -L:库位置。在同济目录时填"."

实战:生成动态库

# 生成动态库
g++ print.cpp -I../include -fPIC -shared -o libprint.so

# 链接
g++ main.cpp -Iinclude -Lsrc -lprint -o shared_main

# 执行,执行时注意要指明使用的库路径
LD_LIBRARY_PATH=src ./shared_main

3. GDB调试器

  • GDB(GNU Debugger)是一个用来调试C/C++的功能强大的调试器。
  • 程序员可以使用GDB来跟踪程序中的错误,从而减少工作量。
  • VSCode是通过调用GDB调试器来实现调试工作的。

4. cmake

  • 终极参考书目:https://www.bookstack.cn/read/CMake-Cookbook/README.md

环境搭建

由于初次在Linux系统使用VsCode,对很多方面非常不熟悉,在环境搭建方面花了非常多的时间,前前后后有一个星期。为了使代码能够不报错,经历了很多问题,最终都一一解决了,也学习到了很多基础知识,例如gcc、g++、clang等的作用和关系,clangd的配置,make和cmake的基础应用,一个完整的C++项目结构等等。

cmake和make在另外一篇文章中记录过了,这里记录一下clang。

clang

起初完全摸不着头脑clang到底是个什么东西,以为是一个类似于clangd的辅助工具。第一次cmake时直接使用的是g++,没有注意过程中有warning。后面总是出现诸如clangd认不得std,或者std::string居然不存在这种基础的问题。完全不知道如何解决这个问题,只能重开一个项目,重新配置环境、编译。

后面在第二次cmake项目时,读到该warning才意识过来:

We recommend that you use clang-14 for developing BusTub. You're using GNU, 
a different version.

原来clang也是一个编译器!随后使用update-alternatives --config c++ 果然在其中找到了clang的身影:
在这里插入图片描述
关于其和gcc的关系:https://zhuanlan.zhihu.com/p/357803433;

将默认编译器切换为clang之后,再cmake,报错:

/usr/bin/ld: can't find -lstdc++

这是一个基础支持,不应该不存在。解决方案为创建软连接:

ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/libstdc++.so

此时cmake编译通过,继续make,报错:

fatal error: 'iostream' file not found

又是基础库读不到的问题。使用clang++ -v命令查看clang++版本:
在这里插入图片描述
发现其选择的是gcc 12的版本。网上查这些都说是版本不匹配,需要删掉之前的版本云云。我这才反应过来,我的系统没有安装gcc/g++12的版本,最高只有11。安装12的版本,make成功,vscode中clangd也可以成功运作了,终于可以愉快地做项目了!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值