C++进阶 Linux相关的静态库,动态库,第三方库
1、多个源程序联合编译g a.cpp b.cpp ... -o ***一次性编译所有.cpp源码自动完成编译 链接直接生成可执行文件 app。1.1 执行流程分别把 a.cpp、b.cpp 编译汇编成临时 .o自动调用链接器 ld合并所有目标文件、系统库生成可执行程序 app适用场景小型项目、单个命令就能跑完不需要复用目标文件。在上述案例中主程序要是有的源程序代码在add.cpp中如果项目结束后到了交付阶段由于主程序的生成需要其他程序联合编译那么就要将源程序打包一起发给老板这样该程序的开发者自身的价值就不大了该项目的知识产权就很容易被窃取。为了保护我们的知识产权我们引入了库的概念2、什么是库2.1 概念库在linux中是一个二进制文件它是由 .cpp文件不包含main函数编译而来其他程序如果想要使用该源文件中的函数时只需在编译生成可执行程序时链接上该源文件生成的库文件即可。库中存储的是二进制文件不容易被窃取知识产权做到了保护作用。2.2 库在linux系统中分为静态库和动态库1windows***.lib静态库***.dll: 动态库2linux***.a静态库***.so: 动态库3、静态库及其制作(lib开头.a结尾)3.1 概念将一个***.cpp的文件编译生成一个 lib***.a的二进制文件当你需要使用该源文件中的函数时只需要链接该库即可后期可以直接调用静态体现在在使用g编译程序时会将你的文件和库最终生成一个可执行程序把静态库也放入到可执行程序中每个可执行程序单独拥有一个静态库体积较大但是执行效率较高编译到使用静态库的步骤源文件生成.o--打包静态库--使用静态库3.2 编译生成静态库g -c ***.cpp -o ***.o//只编译不链接生成二进制文件main 主函数的 cpp可以不建议单独执行第一步生成.oar -crs lib***.a ***.o//编译生成静态库库名是lib后.a之前的部分如果有多个.o文件共同编译生成静态库可以使用 ar -crs lib***.a ***.o xxx.o ...ar:用于生成静态库的指令c:用于创建静态库r:将文件插入或者替换静态库中同名文件s:重置金泰克索引3.3 使用静态库g main.cpp -L 库的路径 -l库名 -I 头文件的名字 -o 文件名-o后面可以不写注意头文件的时大写的i库名是小写的L其他同理.表示当前路径库名后面没有空格..表示上级目录分文件夹多路径编译头文件源文件静态文件都各自管理在一个文件夹里4.4 批量生成.o怎么做每个.cpp单独执行 -c 编译互不干扰g -c 支持一次性传入多个 cpp自动按文件名生成同名.o不用手动写 -o# 写法1指定全部cpp文件g -c func1.cpp func2.cpp calc.cpp# 写法2通配符匹配当前目录所有cpp最省事g -c *.cpp自动生成func1.o、func2.o、calc.o不需要加 -o 参数。注意这种批量写法无法自定义.o输出名只能和 cpp 同名。4.5 批量生成.a怎么做把全部.o打包进静态库ar -crs libmylib.a *.o4、动态库及其制作4.1 概念将一个***.cpp的文件编译生成一个 lib***.so的二进制文件当你需要使用该源文件中的函数时只需要链接该库即可后期可以直接调用动态体现在在使用g编译程序时会将你的文件和库中的相关函数的索引表一起生成一个可执行程序每个可执行程序只拥有函数的索引表当程序执行到对应函数时会根据索引表动态寻找相关库所在位置进行调用体积较小执行效率较低但是可以多个程序共享同一个动态库所以动态库也叫共享库4.2 编译生成动态库g -fPIC -c ***.cpp -o ***.o//编译生成二进制文件g -shared ***.o -o lib***.so//依赖于二进制文件生成一个动态库上述两个指令可以合成一个指令g -fPIC -shared ***.cpp -o lib***.so4.3 使用动态库gcc main.cpp -L 库的路径 -l库名 -I 头文件的名字 -o 文件名-o后面可以不写此时还是报错4.4 解决包含优缺点适合场景方式1更改路径的宏export LD_LIBRARY_PATH库的路径(1) 优点不用重新编译现成的可执行文件临时救急(2) 缺点只在当前终端窗口生效关窗口 / 新开终端就失效每次运行都要重复输两行命令。(3) 适配环境临时测试、快速验证库是否正常不适合长期使用。方法2将自己的动态库放入到系统的库函数目录中 (/lib64 /usr/lib64)mv lib***.so /lib(1) 优点系统全局永久生效所有程序都能自动找到这个 so(2) 缺点需要 root 权限污染系统动态链接缓存项目挪走后残留无效库路径多项目时容易出现库版本冲突。(3) 适配环境自己写的公共工具库、长期安装在服务器的软件不适合你当前课堂分目录练习。方式3编译加 -Wl,-rpath工程开发 / 学习练习最建议g main.cpp -L 库目录 -l库名 -I 头文件目录 -Wl,-rpath库目录 -o 文件名注意头文件的时大写的i库名是小写的L-W后面的是小写的L其他同理(1) 优点一次编译到处运行可执行文件内部自带库路径新开终端、重启系统都不用额外输命令直接 ./run相对路径 ../lib 跟随项目文件夹整个项目文件夹复制到别的机器也能正常跑不修改系统全局配置无权限污染普通用户、root 都能用。(2) 缺点仅当前编译出的程序生效别的程序不受影响。(3) 适合.课堂练习、个人项目、小型交付程序5. 动/静态库编译生成可执行程序的大小比较只有不几个文件就差了24字节的大小项目不用交再交源程序直接交编译生成的动态库/静态库发给上级即可运行指令的具体含义gcc main.cpp -L 库的路径 -l库名 -I 头文件的名字的具体含义单纯说链接库指 -L xxx -lxxx 这一段剩下的是编译整条完整命令编译源代码 链接外部库 是完整的编译链接命令。6 如何使用第三方库使用数学库#includemath.hl后面是库名线程支持类库#includepthread.h如果man手册不能支持线程库sudo yum install manpages-posix manpages-posix-dev怎么知道咱们要用的头文件他对应的要链接 的名字查找这个头文件底下的的某个函数名man 函数名你可以看到SYNOPSIS里面的东西比如线程库函数能看到Compole with -pthread相当于-lpthread