Linux系统下的GCC编译过程、使用命令详解(多文件编译、动态库、静态库)

GCC编译过程包括预处理、编译、汇编和链接四个步骤。预处理处理宏定义和头文件,编译阶段生成汇编代码,汇编转换为机器码,链接阶段将所有对象文件整合成可执行文件。文章还介绍了多文件编译、静态库和动态库的创建与使用,以及-I选项指定头文件路径的功能。
摘要由CSDN通过智能技术生成

GCC 编译命令

GCC编译通常分为4步骤处理
在这里插入图片描述在这里插入图片描述
创建文件hello.c

vim hello.c
#include <stdio.h>

/* 执行命令: ./hello dengzj 
 * argc = 2
 * argv[0] = ./hello
 * argv[1] = dengzj
 */
#define xxx 10

/*argc:argument count  argv: argument value*/
int main(int argc, char **argv)
{
        if (argc >= 2)
                printf("Hello, %s,%d!\n", argv[1],xxx);
        else
                printf("Hello, world! %d\n",xxx);
        return 0;
}

gcc基本用法:gcc [option] [filenames]
编译hello.c文件 不加参数(option) ;gcc filenames则 默认输出为a.out

gcc hello.c

在这里插入图片描述
通常编译hello.c 使用-o参数可命名文件,将hello.c编译后命名为hello,即gcc命令后的-o参数的位置不固定,带-o参数后面一定接编译后的文件名这也是后续编译.c文件使用最多的命令。结果如下图所示

gcc hello.c -o hello
//或者
gcc -o hello hello.c

在这里插入图片描述
-o file 指定输出文件名为file 。无论是预处理、编译、汇编还是链接,这个选项都可
以使用。如果没有使用 o’ 选项,默认的输出结果是:可执行文件为a.out

以上是学习中大多数时候使用的gcc编译指令,上面代码是一步到位的得到链接后的文件,其本质是要经过预处理 编译 汇编 链接这四步。等同于下面的4行指令依次完成。

gcc -E -o hello.i hello.c 
gcc -S -o hello.s hello.i 
gcc -c -o hello.o hello.s 
gcc -o hello hello.o

1、预处理 gcc -E

最开始编写的hello.c文件变为hello.i文件, 展开宏、头文件,替换条件编译,删除注释、空行、空白。

gcc -E -o hello.i hello.c

在这里插入图片描述
打开文件里面就是一些头文件路径即展开宏。打开hello.i文件,在vim的命令模式下输入/main后会看见源代码的xxx宏已经展开后得到数值为10。
在这里插入图片描述

2、编译 gcc -S

.i文件编译得到汇编形式的hello.s,检测语法规范,消耗时间、系统资源最多。同样用vim 打开文件可查看到汇编形式的代码。

gcc -S -o hello.s hello.i 

在这里插入图片描述
同理,灵活使用,可将上面融合为一步。gcc -S -o hello.s hello.c,可直接将hello.c文件编译为汇编形式,并命名为hello.s

3、汇编 gcc -c

(1) 得到hello.o文件,将汇编指令翻译成机器指令,进入则看到的是一堆机器码。

 gcc -c -o hello.o hello.s 

在这里插入图片描述
(2) .c文件直接-c,预处理、编译和汇编源文件,但是不作链接,编译器根据源文件生成OBJ 文件。多用于多文件编译

gcc -o hello.o -c hello.s

4、链接 无参数

数据段合并 将生成的.obj文件与库文件.lib等文件链接,生成可执行文件ELF格式,地址回填。
将hell.o和库文件、系统文件的一系列.o文件进行链接。

gcc -o hello hello.o

最终输出的文件结果
在这里插入图片描述
ELF格式查看

file hello

在这里插入图片描述

*选看

查看gcc完整编译过程,带-v参数,输出结果复制到Notepad++打开

gcc -o hello hello.o -v

在这里插入图片描述
仅供自学参考,谢谢!

进阶用法

多文件编译组成一个应用程序

在这里插入图片描述

vim main.c
#include <stdio.h>
#include "sub.h"

int main(int argc, char *argv[])
{
       int i;
       printf("Main fun!\n");
       sub_fun();
       return 0;
}

vim sub.c
void sub_fun(void)
{
	printf("Sub fun!\n");
}
vim sub.h
void sub_fun(void);

一条命令,处理多个源文件。以此类推,10个文件编写,在后面加10个文件名即可。实际工程中,文件一多起来就不行了(需要makefile,但手搓makefile已过时,现在是cmake的天下,自动生成makefile,makefile是时代的悲哀),因此gcc的缺点是对所有文件都需要再一次处理

gcc -o test main.c sub.c

在这里插入图片描述
当多文件(比如100个文件)进行编译,其中一个文件需要修改时,因为只是某些修改文件的内容,而后其余文件却要被重新处理一次,使用上面这条命令就显得很浪费时间。因此可以使用-c命令只进行前三个步骤(预处理、编译、汇编),最后再统一链接。
即:

gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -o test main.o sub.o

这样在只修改某些文件时,只需要执行对应的-c命令即可。

-I的作用

main.c的头文件中,<>代表在系统目录或工具链的默认的指定路径目录下查找,编译时加上-v选项可查看, " "代表在当前目录下查找文件。
在这里插入图片描述
利用-I来指定目录,修改mian.c 该为<sub.h>

#include <stdio.h>
#include <sub.h>

int main(int argc, char *argv[])
{
       int i;
       printf("Main fun!\n");
       sub_fun();
       return 0;
}

在这里插入图片描述
-I ./ 在当前路径查看头文件,编译成功。

gcc -c -o main.o main.c -I ./

静态库

静态库:程序的链接阶段被复制到程序中
每个需要使用静态库的程序都要将整个静态库编译到可执行程序中,若静态库50M,10个程序要500M。
库函数本地化,优点调用速度快,缺点是系统资源消耗大,多用于对时间要求较高的核心程序。
未链接sub.c文件,文件编译时可以将其他文件生成.o文件制作成库来使用
ar rcs lib库名.a 一系列.o文件
在这里插入图片描述
解决办法:当然可以在代码后加入sub.c文件进行链接生成test文件
或者制作静态库,先生成sub.o文件。

gcc -c -o sub.o sub.c

制作静态库,在编译生成库文件时,对于静态库要使用ar命令对.o文件链接。

ar crs libsub.a sub.o

使用静态库

gcc -o test main.o libsub.a

在这里插入图片描述

动态库

动态库:在程序运行时由系统动态加载到内存中供程序调用。可以实现进程间资源共享(共享库)多个程序使用同个动态库,内存中只会出现一个动态库,所以程序共享。
机制:多个可执行程序共享一份库文件(共享代码、不共享数据)。
使用 gcc -shared 制作动态库,-shared表示要生成的是一个动态库文件
gcc -shared -o lib库名.so 一系列.o文件 (如:add.o sub.o div.o)
制作动态库

gcc -shared -o libsub.so sub.o

使用动态库1

gcc -o test2 main.o libsub.so

在这里插入图片描述
链接可执行程序时,指定所使用的动态库, -l:指定动态库名 -L:指定动态库路径。
补充:-i(大写)包含要引入的头文件路径

使用动态库2

gcc -o test2 main.o -L./ -lsub

运行时,需要添加动态指定路径,:./添加当前路径

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
./test2

总结:
1、动态库是否加载到内存,取决于程序是否运行
2、动态库每次加载的位置不固定
3、动、静态库共存时,编译器默认使用动态库

头文件依赖

查看c.c文件的依赖

gcc -M c.c

在这里插入图片描述

利用-MF指令生成名为c.e的依赖文件

gcc -M -MF c.e c.c

在这里插入图片描述
即生成依赖文件 且编译

gcc -c -o c.o c.c -MD -MF c.e
  • 46
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值