MakeFile学习1-原理

1.静态库用于动态库原理和编译流程

编译分为四大过程

  1. 预编译
  2. 编译
  3. 汇编
  4. 链接

预编译

完成宏替换、文件引入,以及去除空行,注释等,为下一步编译做准备。也就是对各种预编译命令做处理,包括头文件的包含,宏定义的拓展、条件编译的选择等。
选项-E让gcc在预处理结束后停止编译,test.i文件为预处理后的输出文件
gcc中可以通过-o 来指定输出文件

#test.c文件内容
#include 
int main(){
    printf("hello world!\n");
    return 0;
}
gcc -E test.c -o test.i

编译

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

选项-S让gcc在编译结束后停止编译过程,test.s文件为编译后生成的汇编代码

gcc -S test.i -o test.s

汇编

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

选项-c让gcc在汇编结束停止编译过程,test.o文件为汇编结束生成的机器码目标文件

gcc -c test.s -o test.o

链接

就是将多个目标文件以及所需的库文件链接称为可执行的目标文件的过程

-o本质上是一个重命名选项,不使用-o时,默认生成a.out文件。这里生成的可执行文件时test

./test执行后输出hello world!

$ gcc test.o -o test

$ ./test

hello world!

小结

test.c代码内容

#include 
int main(){
    printf("hello world!\n");
    return 0;
}

执行的操作

gcc -E test.c -o test.i 
gcc -S test.c -o test.s
gcc -c test.o -o test
gcc test.o -o test
./test

静态库和动态库

都需要使用的代码

这里有是三个文件
main.c tool.c tool.h

tool.h

int find_max(int arr[],int n);

tool.c

#include "tool.h"
int find_max(int arr[],int n){
    int max = arr[0];
    int i;
    for(i=0;imax){
            max=arr[i];
        }
    }
    return max;
}

main.c

#include 
#include "tool.h"

int main(){
    int arr[]={1,3,5,8,2};
    int max=find_max(arr,5);
    printf("max =%d\n",max);
    return 0;
}

静态库

什么是静态库

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

生成静态库

首先生成test.o目标文件
使用ar命令将test.o打包成libtest.o静态库

// 首先生成目标文件
gcc -c test.c -o test.o  
//使用ar命令将目标文件打包静态库
ar rcs libtest.a test.o
//使用 ar t libtest.a 查看静态库内容
ar t libtest.a
test.o

具体操作

gcc -c tool.c
ar rcs libtool.a tool.o
gcc -o main main.c -L. -ltool

./main 执行main文件


ls -lh  查看总共的大小

ldd main 查看依赖情况

动态库

什么是动态库

  1. 动态库在链接阶段没有被复制到程序中去,而是在程序运行时由系统动态加载到内存中供程序调用
  2. 系统只需要加载一次动态库,不同的程序可以得到内存中相同的动态库副本,因此可以节约内存

生成动态库

首先生成test.o目标文件
使用-shared和-fPIC参数生成动态库

// 首先生成目标文件
gcc -c test.c
// 使用-fPIC和-shared生成东莞台库
gcc -shared -fPIC -o libtest.so test.o

具体操作

gcc -shared -fPIC -o libtool.so tool.o
gcc -o main main.c -L. -ltool
./main
会报错

./main :error whild loading shared libraries:libtool.so : cannot open shared object file:such file or directory


ldd main  查看缺失的内容

LD_LIBRARY_PATH =. ./main  设置环境变量

动态库和静态库的区别

载入的时刻不同

静态库在程序编译时会连接到目标代码中,程序运行时不需要静态库,因此体积比较大,而且每次编译都需要载入静态代码,因此内存开销大
动态库在编译是不会被链接到目标代码中,而是在程序运行时才被载入,程序运行时需要动态库存在,因此体积比较小。而且系统只需要载入一次动态库,不同程序可以得到内存中相同的动态库副本,因此内存开销小。

你可能感兴趣的:(linux)