文章目录
1.Linux 如何安装 C++ 编译环境
(1)安装 gcc
下载:sudo apt install gcc g++
安装:gcc/g++ -v/--version
其中 gcc 用于编译 C ,g++ 用于编译 C++
版本要 >4.8.5 这样才能使用 C++11 的特性
(2) 使用 g++ 编译代码
首先现在对应目录下编写一个 c++ 程序,如:test.cpp,然后执行下面的命令进行编译
g++ test.cpp -o test.out
其中 -o 代表:生成可执行目标文件
test.out 是用户自定义的可执行文件名称,在 linux 下是 .out 在 windows 中是 .exe
(3)运行可执行文件
不能直接敲指令 test.out ,要在前面加 ./test.out
2.编程语言的发展
2.1 编程语言的发展
![image-20211029105526970](https://i-blog.csdnimg.cn/blog_migrate/3a0c9d31cb24b516c89309bcba07107d.png)
机器语言:计算机识别的语言
汇编语言:使用简单的符号代替机器语言
2.2 GCC 工作流程
![image-20211029110101814](/Users/xuguagua/Documents/typora_image/image-20211029110101814.png)
预处理:将头文件导入,宏替换,去掉一些注释
编译:对预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码
汇编:对汇编代码进行处理,生成处理器能识别的指令
目标代码:计算机可以识别的代码
链接:将这个文件中使用的相关库进行链接,形成可执行程序
2.3 gcc 编译选项代码演示
![image-20211029111249299](/Users/xuguagua/Documents/typora_image/image-20211029111249299.png)
![image-20211029110233749](/Users/xuguagua/Documents/typora_image/image-20211029110233749.png)
![image-20211030103225473](https://i-blog.csdnimg.cn/blog_migrate/c810462703a37de98f4069ef6b227ec9.png)
分别执行上面的代码:
1.-E
预处理源文件
g++ test.cpp -E -o test.i
![image-20211029111708675](https://i-blog.csdnimg.cn/blog_migrate/d26b91dc7d9f9b1172350faa1bf2ae41.png)
这是一个长长的文件,直接定位到 Hello World 部分,可以看到所有的注释,宏定义,头文件全部被替换
2.-S
生成汇编代码
g++ test.i -S -o test.s
![image-20211029111913031](https://i-blog.csdnimg.cn/blog_migrate/ada2f4f2d21d55162c63bbd66bca1d80.png)
**3.-s **
生成可执行文件
g++ test.s -s -o test.o
![image-20211029112057911](https://i-blog.csdnimg.cn/blog_migrate/ea2e2cbe3a3b853d37b5f35753a206e6.png)
上图是一对乱七八糟的东西,其实这个文件不能被打开。但是可以直接执行
![image-20211029112207044](https://i-blog.csdnimg.cn/blog_migrate/9ec3598a6465ec58aadf0c83886ddde9.png)
4.一步式操作
g++ test.cpp
![image-20211029112518629](https://i-blog.csdnimg.cn/blog_migrate/8b45e40b52edbf765dea6abc53b39296.png)
可以看到上图直接生成了一个 ,out 文件,同理如果直接跳过 -E 还有 -S 直接执行 -s 也是可以的
2.库的制作
库文件是计算机上的一类文件,可以将库文件看做是一种代码仓库。它提供给使用者一些可以直接拿来用的变量,函数或类。库是一种特殊的程序,但是库是不能单独运行的。
库文件有两种:静态库和动态库
静态库: GCC进行链接时,会把静态库中代码打包到可执行程序中
动态库: GCC进行链接时,动态库的代码不会被打包到可执行程序中,程序启动之后,动态库会被动态加载到内存中,通过动态库地址访问动态库,但是对于自己刚刚写的库系统是不知道库的内存地址的,所以就要自己手动为动态库添加环境变量地址,通过ldd (list dynamic dependencies)命令检查动态库依赖关系
库的好处:1.代码保密(C++ 的反编译还原度非常低) 2.方便部署和分发
应用场景:比如Office软件的各个组成部分有相似的外观和功能,那么就可以调用同一个库文件中的函数生成那些组件
2.1 如何生成静态库
2.1.1 书写相关函数
1.文件如何保存
这里实现了一个算术运算的库,主要进行相关加减乘除操作,并根据命名规则将他们放在对应的目录下
![image-20211030111747506](https://i-blog.csdnimg.cn/blog_migrate/c9938824b10857caa539320490026a5e.png)
2.文件内容
(1)head.h
对函数进行声明
![image-20211030112241751](https://i-blog.csdnimg.cn/blog_migrate/05b6dea7c231d8bd3d19c4eec6bf4764.png)
(2)方法体的实现
add.c
![image-20211030112339704](https://i-blog.csdnimg.cn/blog_migrate/2db0f189a55d4a641549640414b4887a.png)
(3) main 执行方法实现
![image-20211030112442437](https://i-blog.csdnimg.cn/blog_migrate/9583b49ea29255721e68146f608b242f.png)
2.1.1 静态库的命名规则
![image-20211030105426907](https://i-blog.csdnimg.cn/blog_migrate/1a3fc1fcf4eb1d0b575a2cd3b933d1f8.png)
![image-20211030105510007](https://i-blog.csdnimg.cn/blog_migrate/0b08aa3f96b94540d575c4d2454069f5.png)
2.1.2 静态库的制作
(1)gcc -c 对库文件编译
gcc -c add.c mult.c sub.c div.c
报错,头文件找不到,使用 -I 将头文件导入
![image-20211030112709156](https://i-blog.csdnimg.cn/blog_migrate/14126678f4322a4411145a902610f3f5.png)
gcc -c add.c mult.c sub.c div.c -I ../include
上面代码注意,不需要添加 head.h ,直接将文件 dictionary 添加进来即可。于是就生成了一堆 .o 文件
![image-20211030113140520](https://i-blog.csdnimg.cn/blog_migrate/20874ba035d232968927bdea24899015.png)
(2)对 .o文件进行打包 ,成 .a 库文件
ar rcs libmath.a add.o div.o mult.o sub.o
(3)执行 main.c 方法
执行 main.c 方法,调用的库都是从 head 文件中查找的,所以还会报一个找不到 head.h 文件的情况。这时候将 head.h 再次导入
gcc main.c -I include/ // 编译
![image-20211030114005640](https://i-blog.csdnimg.cn/blog_migrate/fd5a00f9e186027e5535eecc104936c9.png)
如上图所示,提示未引用库的 error ,这里需要使用 -L 参数将打包的库进行引用
gcc main.c -o app -I ./include/ -L ./lib/ -l math
注意:
-l 参数后的内容是和 -L 后面的文件对应的 .a 文件相关,调用的时候直接添加 lib 的名称即可
2.2 动态库的制作
这里是将上面的文件定义成动态库的方式
2.2.1 文件命名规则
![image-20211030121941820](https://i-blog.csdnimg.cn/blog_migrate/aeddf8cd7431c68582b1a2cfa77141ad.png)
2.2.2 动态库的制作
1.gcc 得到 .o 文件,得到和位置无关的代码
gcc -c -fpic add.c div.c mult.c sub.c -I ../include/
参数:fpic 生成与位置无关的代码,原因是动态库与静态库不同,静态库是将静态库代码嵌套在可执行文件中。但是动态库的代码是放在内存的,是不确定位置的,所以就需要有这个参数
2.gcc 得到动态库
gcc -shared *.o -o libmath.so
*.o 就是将所有的 .o 文件聚合,注意这里别忘了加 .o 参数
shared 作用是生成一个共享库
![image-20211030122540111](https://i-blog.csdnimg.cn/blog_migrate/a0a9a5c668ccad84026491531088db91.png)
如上图所示就生成了一个 .so 的可执行文件
3.根据动态库生成可执行文件
gcc main.c -o main -I include/ -L lib/ -l math
但是如果执行这个可执行文件就发现报错,主要是找不到共享库的地址
![image-20211030123155301](https://i-blog.csdnimg.cn/blog_migrate/d391dea0283312c9d9baa6967733ab5c.png)
2.2.3 如何让程序找到共享库
![image-20211030123245912](https://i-blog.csdnimg.cn/blog_migrate/e9d3c0b19a609d1f50c862c174dc5d00.png)
ldd main // 查看所用动态库
![image-20211030123531107](https://i-blog.csdnimg.cn/blog_migrate/5ef675e9e90805251cd5486d69b74669.png)
查看电脑环境变量:
那么这样的话只需要将动态库的地址配置到环境变量中既可
env
其中 path 就是配置的环境信息
![image-20211031223057671](https://i-blog.csdnimg.cn/blog_migrate/255d9de388f8ac4fe739ebdf1a6ca07f.png)
2.2.4 在环境变量中声明动态库
为环境变量添加动态库(用户级别的配置)
用户级别配置是在 .bashrc 文件下配置的
编辑 .branch 文件,在最后添加动态库地址,最后再将这个文件编译一下
![image-20211031224750386](https://i-blog.csdnimg.cn/blog_migrate/e5c3d8d4493355cdd84b5cb5e204ed73.png)
source .bashrc or . .bashrc // 编译文件
source 的含义是读取并执行 source 后面文件;. 是 source 这个 operation 的简写。最后在执行 ldd main 就找到了这个库的地址,并且 main 这个文件也可以执行
![image-20211031225123798](https://i-blog.csdnimg.cn/blog_migrate/8e3fc7aa73bdaf37e95ad3ce5ee27aca.png)
知识延伸:如何查看某个变量的值
上面使用 $+变量名获取变量值,用同样的方法再结合shell 指令就可以使用 ¥ 将这个值输出,看到这个变量中拼接的值
echo $LD_LIBRARY_PATH
![image-20211031230234741](https://i-blog.csdnimg.cn/blog_migrate/4b425de83dc6f6a60d8e91b8cf5fca0f.png)
为环境变量添加动态库(系统级别的配置)
系统界别的配置主要是在 /etc/profile 文件中,所以就在这个文件下对这个变量添加动态库目录
sudo vim /etc/pro
使用和上面相同的添加动态库的指令,并在最后一行添加动态库地址,并且使用 source 进行编译
![image-20211031230654338](https://i-blog.csdnimg.cn/blog_migrate/40330361a512ed6d8d50931ad1ba15b6.png)
最后在执行 main 方法就发现可以运行了
2.2.5 在文件列表中添加 PATH
通过 2.2.3 动态库的保存路径中获知可以直接修改 /etc/ld.so.cache
文件对动态库 path 进行调用。但是这个文件如果使用 vim 打开都是乱码,其实这个文件可以通过使用 conf 文件进行映射
sudo vim /etc/ld.so.conf
直接将地址粘贴到这个文件中即可
![image-20211031232137699](https://i-blog.csdnimg.cn/blog_migrate/972179cac82b8495899611999d441794.png)
然后使用 ldconfig 指令将动态库进行共享
sudo ldconfig
最后就可以直接对 main 文件执行
视频作者不太建议使用直接更改 lib 的方式更改库文件,因为 lib 中的文件太多,容易混乱
2.3 动态库和静态库的区别
2.3.1 制作流程上的差别
1.静态库的制作
![image-20211101103923631](https://i-blog.csdnimg.cn/blog_migrate/ea703af781e8b14eadde97cab0fb223e.png)
2.动态库的制作
![image-20211101104000087](https://i-blog.csdnimg.cn/blog_migrate/459181c31d6b547ba2486eea4436acce.png)
2.3.2 静态库的优缺点
1.静态库
优点 | 缺点 |
---|---|
静态库被打包到应用程序中加载速度快 | 消耗系统资源,浪费内存 |
发布程序无序提供静态库,直接调用静态库 | 当静态库中代码更新后,所以引用它的文件全部要进行相关喜欢,更新,部署,发布麻烦 |
2.动态库
优点 | 缺点 |
---|---|
可以实现进程间资源共享 | 加载速度比静态库慢 |
相比于静态库,动态库更新部署发布简单 | 发布程序是时需要提供依赖的库文件 |
可以控制何时加载动态库 |