NDK之静态库与动态库原理及编译流程

文章目录

    • 一、编译
        • 1、预处理(Preprocessing)
        • 2 、编译(compilation)
        • 3 、汇编(Assemble)
        • 4 、链接(Linking)
    • 二、Linux中编译的具体流程
    • 三、静态库
    • 四、动态库
    • 五、在Linux平台如何编译及使用静态库和动态库
        • 1. 如何编译使用静态库
        • 2. 如何编译使用动态库
    • 六、静态库与动态库的区别

静态库与动态库原理,编译流程详解。编译原理和语法详解。

一、编译

编译,就是将高级语言编写的程序转化为二进制代码可执行性目标程序。四个步骤:预处理,编译,汇编,链接

1、预处理(Preprocessing)

预处理解释

  • 完成宏替换、文件引入,以及去除空行、注释等,为下一步的编译做准备。
  • 也就是对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选项等。
    代码说明:

操作命令
通过命令 gcc -E test.c -o test.itest.c文件进行预处理,输出一个预处理后的文件test.i

  • -E表示:让gcc在预处理结束后停止后续的 编译、汇编以及链接等操作。
  • -o表示:重命名选项,这里表示预编译后输出的文件
    可以看出,预处理之后文件变大了很多,并且为txt文件。

具体代码及步骤
vim test.c 创建文件并输入

#include 
int main(){
   printf("hello,城南一霸贾十七~\n ");
   return 0;
}

执行命令 gcc -E test.c -o test.i进行预处理,通过命令du -sh * | sort -n统计当前文件夹下的文件。可以尝试打开test.i文件看看长啥样。
NDK之静态库与动态库原理及编译流程_第1张图片

2 、编译(compilation)

概念解释

  • 将预处理后的代码编译成汇编代码。在这个阶段中,首先要检出代码的规范性、是否有语法错误等,以确定代码实际要做的工作,再检查无误后,再把代码翻译成汇编语言。
  • 编译程序执行时,先分析,后综合。分析,就是指词法分析、语法分析、语义分析和中间代码生成。综合,就是指代码优化和代码生成。
  • 大多数的编译程序直接产生机器语言的目标代码,形成可执行文的目标文件,也有的是先产生汇编语言一级的符号代码文件,在调用汇编程序进行翻译和加工处理,最后产生可执行的机器语言目标文件。

操作命令

  • 通过命令gcc -S test.i -o test.s对预编译之后的test.i文件进行编译。输出一个编译后的汇编文件test.s,此为汇编代码。
    -S表示:gcc在编译结束后停止后续的汇编、链接等操作
    NDK之静态库与动态库原理及编译流程_第2张图片

3 、汇编(Assemble)

概念解释

  • 汇编就是把编译阶段生成的.s文件转成二进制目标代码,也就是机器码(01序列)

操作命令

  • 通过命令gcc -c test.s -o test.o将编译后的test.s文件转成test.o二进制文件.
    NDK之静态库与动态库原理及编译流程_第3张图片

4 、链接(Linking)

概念解释

  • 链接就是将多个目标文件及所需要的库文件链接生成可执行目标文件的过程。

操作命令

  • 通过命令 gcc test.o -o test生成可执行文件test
  • 通过命令./test执行程序

-o本质是一个重命名选项,不使用 -o选项 ,默认生成一个 a.out文件,这里使用-o 指定生成为test可执行文件,生成之后可以使用./test来执行。
NDK之静态库与动态库原理及编译流程_第4张图片

二、Linux中编译的具体流程

以上是具体的编译流程。
简化流程,通常使用 gcc命令 将 test.c文件直接转换为test文件。使用以下命令:gcc -o test test.c
NDK之静态库与动态库原理及编译流程_第5张图片

三、静态库

概念解释

  • 静态库实际就是一些目标文件(一般以.o结尾)的集合,静态库一般以.a结尾,只用于生成可执行文件阶段。
  • 在链接步骤中,链接器将从库文件取得所需代码,复制到生成的可执行文件中。这种库称为静态库。其特点是可执行文件中包含了库代码的一份完整拷贝,在编译过程中被载入程序中。其缺点就是多次使用就会有多份冗余拷贝,并且对程序的更新、部署和发布会带来麻烦,如果静态库有更新,name所有是用他的程序都需要重新编译、发布。

生成静态库
操作命令

  • 通过命令ar rcs libtest2.a test2.o将目标文件打包成静态库。
  • 通过命令ar t libtest2.a查看静态库libtest2.a中的内容。
    NDK之静态库与动态库原理及编译流程_第6张图片

命令ar rcs libtest2.a test2.orcs的含义:

  • r表示:更新或增加新文件到静态库中。
  • c表示:创建一个库,不管存在与否。
  • s表示:创建文档索引,在创建较大的库时候,能够加快编译时间。

四、动态库

概念解释

  • 动态库在链接阶段没有被复制到程序中,而是在程序运行时由系统动态加载到内存在供程序调用。
  • 系统只需载入一次动态库,不同的程序可以得到内存中相同动态库的副本,因此节省了很多内存。

生成动态库

NDK之静态库与动态库原理及编译流程_第7张图片
gcc -shared -fPIC -o libtest.so test.o
-fPIC :postion independent code:表示创建与地址无关的代码。

五、在Linux平台如何编译及使用静态库和动态库

1. 如何编译使用静态库

NDK之静态库与动态库原理及编译流程_第8张图片
tool.c编译成静态库

  1. tool.c编译成目标文件,使用命令gcc -c tool.c生成tool.o目标文件,命令中省略了-o tool.o 因为默认生成相同文件名的.o文件
  2. tool.o文件生成静态库文件,ar rcs libtool.a tool.o,将tool.o目标文件打包成静态库文件libtool.a
  3. 编译可执行文件并链接静态库,以生成可执行文件。命令:gcc -o main main.c -L. -ltool。命令ls可以看到生成了 main的可执行文件
    1. -l 用来指定要链接的库,后面紧接着就是库的名字,如:-ltool
    2. -L表示:编译程序按照指定的路径去寻找库文件,这里是.表示当前目录去找。
  4. ./main执行main
    NDK之静态库与动态库原理及编译流程_第9张图片
    查看可执行文件main依赖了哪些库文件
    • linux -vdso .so .1 指Linux 内核提供的虚拟so
    • libc .so .6 指 libc 核心库,如上main函数printf的实现就在核心库中
    • /lib64/ld-liunx -x86 -64.so.2 指 Linux下的动态库链接器

2. 如何编译使用动态库

  1. 第一步 ,生成tool.o目标文件,与静态库第一步一致
  2. tool.o文件生成动态库文件,命令gcc -shared -fPIC -o libtool.so tool.o,根据tool.o的目标文件生成动态库文件libtool.so
  3. 编译可执行文件并链接动态库,命令gcc -o main main.c -L. -ltool。此时当前目录同时有libtool.a静态库和libtool.so动态库。档静态库和动态库同名,gcc会优先加载动态库文件
  4. 执行可执行文件

注:第4步中,如果采用静态库.\main命令来执行,会报错:
**加粗样式**
查看当前可执行文件依赖了哪些库。
所以,在执行之前使用命令LD_LIBRARY_PATH=. ./main设置环境变量,该环境变量主要用来指定查找共享库,也就是动态链接库时除了默认路径以外的其他路径,这也就是报这个错的原因,在系统的默认路径下找不到libtool.so这个库,而libtool.so在当前的目录下,我们并没有给当前目录设置到环境变量里面去,
NDK之静态库与动态库原理及编译流程_第10张图片

六、静态库与动态库的区别

NDK之静态库与动态库原理及编译流程_第11张图片

你可能感兴趣的:(DNK)