gcc命令学习
转自:https://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html
https://www.cnblogs.com/fengliu-/p/10219850.html
https://blog.csdn.net/m1223853767/article/details/79464729
1.简介
gcc能够编译多种语言,不仅仅是C,使用man gcc查看说明时:
还支持OC等语言。
编译成为可执行文件分为四个阶段:预处理、编译、汇编、链接。
2.基本用法
gcc [options] [filenames]
常用选项:
-c
只编译,不链接成为可执行文件。
编译器只是由输入的 .c 等源代码文件生成 .o 为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename
确定输出文件的名称为output_filename。
同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出默认的可执行文件 filename.out 。
-g
产生符号调试工具(GNU的 gdb)所必要的符号信息。
-Idirname
将 dirname 所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。
3.例子
一步到位:
gcc test.c -o test
3.1 预处理
gcc -E test.c -o test.i 或 gcc -E test.c
-E
预编译后停下来,生成后缀为 .i 的预编译文件。查看test.i文件内容,内容非常长,只截取了一部分:
存放的是.c文件预处理之后的代码。在本例中,是将stdio.h头文件中的内容插入(不是复制?)了进来。
3.2编译(成汇编代码)
gcc -S test.i -o test.s
-S
汇编后停下来,生成后缀为 .s 的汇编源文件。查看.s文件内容,生成了汇编代码:
3.3 汇编(为目标文件)
gcc -c test.s -o test.o
-c
编译后停下来,生成后缀为 .o 的目标文件。cat命令查看.o文件时乱码的,它是一个二进制的文件吧。
3.4 链接(为可执行文件)
gcc test.o -o test
gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。
附加的目标文件包括静态连接库(.a结尾)和动态连接库(.so结尾)。区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。
总结规律:ESC=》文件后缀为ISO,最后-o成为可执行文件
4.连接库文件
函数库实际上就是一些头文件(.h)和库文件(.so 或 .a)的集合。
一般来说,默认将头文件放到 /usr/include/ 目录下,而库文件则放到 /usr/lib/ 目录下。
/usr/include/目录内容,包含很多.h头文件:
/usr/lib/ 目录内容,包含很多库文件:
但gcc仍需自己的方法来查找所需的头文件和库文件:
- -I :可以向 gcc 的头文件搜索路径中添加新的目录。
- -L :如果使用了不在标准位置的库文件,那么可以通过 -L 选项向 gcc 的库文件搜索路径中添加新的目录。
gcc source_file.c -L /XXX/lib -l libXXX.a -I /XXX/include
- -l, 指定所使用到的函数库,链接器将链接名为libxxx.a(后缀.a表示静态库)的函数库。
- -L,指定函数库所在的文件夹,链接器会搜索/XXX/lib(一般可以指定路径)文件夹。
- -I, 指定头文件所在的文件夹,预编译器会搜索/XXX/include文件夹。
4.1 例子
假设test.c在linux上使用c连接mysql,需要去mysql官网下载MySQL Connectors的C库,解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so
编译成目标文件:
gcc –c –I /usr/dev/mysql/include test.c –o test.o
链接成可执行文件:
gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
也可以强制使用静态链接库。
5.为什么编译的时候还要指定cpp源文件?
只包含头文件不就可以?但是如果源文件和对应的头文件不在同一个目录下,就找不到了,而且编译器不会自动根据目录去找源文件,所以必须要指定。
在C++项目中,头文件(.h
或 .hpp
)通常包含了类、函数、变量的声明和接口,而源文件(.cpp
或 .cc
)包含了实现细节和具体的实现代码。在进行编译时,编译器需要访问源文件以获取具体的实现,因此需要包含源文件来生成目标文件(.o
或 .obj
)。但是,头文件本身并不包含具体的实现代码,因此如果只包含头文件而不包含源文件,编译器就无法找到实现,导致链接错误。
当你只包含头文件时,编译器会查找头文件所在的目录,但它不会自动找到并编译对应的源文件。在编译时,你需要确保源文件也被编译,并且生成的目标文件可以在链接阶段使用。这通常需要在构建系统(比如 CMake)中显式地列举源文件。