makefile 学习(2):C语言的编译及库文件的生成与链接

1. 介绍

编译C语言的相关后缀

在这里插入图片描述

  • .a 文件是一个静态库文件
  • .c文件是c语言的源文件
  • .h c语言的头文件
  • .i 是预处理文件
  • .o 目标文件
  • .s汇编语言的文件
  • .so 动态库或者共享库或者称为运行时库

.c文件在github中可以看到另一种后缀,比如.cc 或者是其他的后缀,但是常用的还是.c后缀。在makefile 学习(1):C/C++ 编译过程, 我们讲到编译过程包括4个步骤: (1)预处理,(2)转换为汇编语言,(3) 生成目标文件(4) 链接为可执行文件。

2. C语言编译

2.1 预处理

main.c文件:

#include <stdio.h>

int main(int argc, char** argv)
{
    
    
	printf("Hello World\n");
	return 0;
}
  • 执行命令:
# 不会生成.i文件
gcc -E main.c

虽然进行了预处理编译,但是没有输出.i文件,需要-o指定下输出

gcc -E main.c -o main.i

可以看到了生成了预处理main.i,打开可以看到.i文件对应的是脚本
【图】

2.2 生成汇编语言

执行命令:

gcc -S main.c

可以看到生成汇编语言main.s,内容如下:

熟悉汇编语言的童学对生成的内容应该很熟悉

如果想指定输出的文件名,可以利用-o选项:

gcc -S main.c -o test.s

在这里插入图片描述

2.3 编译目标文件

  • 执行命令:
gcc -c main.c   # 没有指定输出名,默认为main.o
gcc -c main.c -o xxx.o #生成 xxx.o
  • 编译多个.c文件
gcc -c main.c add.c minus.c # 生成main.o add.o minus.o

2.4 编译为可执行文件

gcc main.c -o exec #exec 可执行文件名

【图】

生成了可执行文件exec, 然后运行可执行文件./exec就能输出对应结果

3. .a静态库的编译与链接

在实际的项目中,我们会写很多带有功能性源文件(比如特定的运算,放在不同的.c文件中),供其他脚本调用。如果不希望.c文件源码被外部看到或者不想拷贝一堆.c,而是直接输出库文件,供外部的可执行文件链接,此时就需要编译静态库或者动态库

案例

  • add.c中实现两个数相加,在minus.c文件中实现两个数相减。 在main.c中调用add.cminus.c中的函数,进行加减运算
  • 实现将add.cminus生成库文件
    [图]

add.c的代码

int add(int a, int b)
{
    
    
    return a+b;
}

minus.c的代码

int minus(int a, int b)
{
    
    
    return a-b;
}

main.c

#include <stdio.h>
int add(int a,int b);
int minus(int a,int b);

int main(int argc, char ** argv[])
{
    
    
    int a = 10;
    int b = 5;
    int c;
    c = add(a,b);
    printf("a+b = %d\n",c);
    c = minus(a,b);
    printf("a-b = %d\n",c);
    return 0;
}

(1)编译目标文件

  • 首先编译目标文件 add.ominus.o
gcc -c add.c minus.c

(2)编译静态库
生成静态库语法:

ar -r [lib自定义库名.a] [.o] [.o] ...
  • add.ominus.o编译为 静态库
ar -r liboperation.a add.o minus.o

在这里插入图片描述

可以看到生成了 liboperation.a静态库文件

(3)连接静态库

  • 方法1:
    生成静态库后,就可以将静态库连接到源文件main.c
gcc main.c liboperation.a -o  exec # 生成可执行文件exec
./exec # 执行可执行文件

【图】

  • 方法2
    main.c也编译为目标文件,然后利用gcc 把3个目标文件链接起来
  • 生成 main.o
gcc -c main.c
  • 3个目标文件链接,生成可执行文件
gcc main.o add.o minus.o -o exec
./exec

4 .so 动态库的编译与链接

动态库的编译与静态库的编译,其实是一样的。

  • (1)编译二进制.o文件 (需要加上 -fpic)
    语法
gcc -c -fpic [.c/.cpp] [.c/.cpp] ...

编译 add.o, minus.o目标文件

gcc -c -fpic add.c minus.c
  • (2)编译动态库 (需要加上 -share)
    语法
gcc -shared [.o][.o] ... -o [lib自定义库名.so]

生成动态库liboperation.so

gcc -shared add.o  minus.o -o liboperation.so

[图]

  • (3)链接动态库到可执行文件
    语法
gcc [.c/.cpp] -o [自定义可执行文件名] -l(库名) -L(库路径) -Wl,-rpath =[库路径]

链接可执行文件

gcc main.c -loperation -o exec -L/home/yuanwushui/project/tensorrt-integrate/1.C/src

在这里插入图片描述

编译成功了可执行文件,这里还有一些小细节并没有说,比如-Wl,-rpath等,这些都将在后续makefile章节进行讲解

猜你喜欢

转载自blog.csdn.net/weixin_38346042/article/details/130731565