GCC执行过程
(1)预处理阶段
这个阶段主要是处理源文件中的#ifdef、#include和#define命令
命令:gcc -E xxx.c -o xxx.i
(2)编译阶段
输入的是中间文件*.i,编译后生成汇编语言文件*.s
命令:gcc -S xxx.i -o xxx.s
(3) 汇编阶段
输入的是汇编文件*.s,输出的转换生成的机器语言*.o
命令:gcc -c xxx.s -o xxx.o
(4) 连接阶段
将输入的机器代码文件*.s,汇集成一个可执行的二进制文件
命令:gcc xxx.o -o xxx
编译静态库
(1)创建静态库
例如源码文件为:lib.c,内容如下:
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
要将其编译成为静态库文件——lib.a,则可使用如下的命令:
gcc -c lib.c 生成 lib.o 文件
ar rcs lib.a lib.o // 生成 lib.a 文件
(2)使用静态库
静态库创建成功后,需要链接到应用程序中使用。应用程序可以引用该库中的函数或者全局变量。为了使应用程序可以正确引用该库中的全局符号,需要制作一个包含该静态库中全局符号声明的文件。这个头文件可以包含在应用程序的头文件中,这样就可以引用静态库中的全局符号了。包含静态库文件的头文件:static_lib.h,内容如下:
extern int add(int a, int b);
extern int sub(int a, int b);
应用程序:main.c
#include <stdio.h>
#include "static_lib.h"
int main()
{
int a, b;
printf("Please input a and b\n");
scanf("%d%d",&a, &b);
printf("the add: %d\n", add(a, b));
printf("the sub: %d\n", sub(a, b));
return 0;
}
链接静态库,并生成可执行文件
命令:gcc main.c -static ./static_lib.a -o xxx // xxx 为可执行文件
编译动态库
动态库又称为共享库或者动态链接库,现代程序中大量地使用动态链接库。例如,Windows 环境中的dll文件和Linux环境下的 so文件。动态库是在程序启动时被装载的。当一个程序装载了一个动态库后,其他应用程序仍然可以装载同一个动态库。
例如动态库的.c文件为:share_lib.c
void sort(int *array, int length)
{
int i, j, temp;
for(i = 1; i < length; ++i)
{
temp = array[i];
for(j = i; j > 0; j--)
{
if(array[j - 1] > temp)
{
array[j] = array[j - 1];
}
else
break;
}
array[j] = temp;
}
}
gcc创建一个动态库。由于动态库可以被多个进程共享加载,所以需要生成位置无关的目标文件。这时需要使用gcc编译器的-fPIC选项,该选项用于生成位置无关的代码。需要使用-fPIC选项和-shared 选项,该选项将位置无关的代码制作为动态库。
创建静态库命令:gcc -shared -fPIC -o share_lib.so share_lib.c // 生成库为 share_lib.so
使用动态库
动态库创建完后,应用程序可以引用该库中的函数或全局变量。为了使应用程序可以正确引用该库中的全局符号,需要制作一个包含该动态库中全局符号声明的头文件。头文件:share_lib.h
extern void sort(int *array, int length);
应用程序:main.c
#include <stdio.h>
#include "share_lib.h"
int main()
{
int array[5] = {5, 4, 3, 2, 1};
sort(array, 5);
int i;
printf("the array:");
for(i = 0; i < 5; i++)
printf(" %d ", array[i]);
printf("\n");
return 0;
}
使用静态库命令:gcc main.c ./share_lib.so -o main // 生成可执行文件 main