GCC 最初的意思是GNU C Compiler,而后变成了 GNU Compiler Collection,也就是 GNU 编译器家族(常见的语言都支持)。
内容如下:
1. GCC的组成部分以及使用到的软件
2. 编译和链接
3. gcc选项
4. 库搜索路径
1,GCC的组成部分以及使用到的软件
GCC 是由许多组件组成的。表 1 列出了 GCC 的各个部分,但它们也并不总是出现 的。有些部分是和语言相关的,所以如果没有安装某种特定语言,系统中就不会出现相关的文件。
部分 | 描述 |
---|---|
c++ | gcc 的一个版木,默认语言设置为 C++,而且在连接的时候自动包含标准 C++ 库。这和 g++ 一样 |
ccl | 实际的C编译程序 |
cclplus | 实际的 C++ 编泽程序 |
collect2 | 在不使用 GNU 连接程序的系统上,有必要运行 collect2 来产生特定的全局初始化代码(例如 C++ 的构造函数和析构函数) |
configure | GCC 源代码树根目录中的一个脚木。用于设置配置值和创建GCC 编译程序必需的 make 程序的描述文件 |
crt0.o | 这个初始化和结束代码是为每个系统定制的,而且也被编译进该文件,该文件然后会被连接到每个可执行文件中来执行必要的启动和终止程序 |
cygwin1.dll | Windows 的共享库提供的 API,模拟 UNIX 系统调用 |
f77 | 该驱动程序可用于编译 Fortran |
f771 | 实际的 Fortran 编译程序 |
g++ | gcc 的一个版木,默认语言设置为 C++,而且在连接的时候自动包含标准 C++ 库。这和 c++ 一样 |
gcc | 该驱动程序等同于执行编译程序和连接程序以产生需要的输出 |
gcj | 该驱动程序用于编译 Java |
gnat1 | 实际的 Ada 编译程序 |
gnatbind | 一种工具,用于执行 Ada 语言绑定 |
gnatlink | 一种工具,用于执行 Ada 语言连接 |
jc1 | 实际的 Java 编译程序 |
libgcc | 该库包含的例程被作为编泽程序的一部分,是因为它们可被连接到实际的可执行程序中。 它们是特殊的例程,连接到可执行程序,来执行基木的任务,例如浮点运算。这些库中的例程通常都是平台相关的 |
libgcj | 运行时库包含所有的核心 Java 类 |
libobjc | 对所有 Objective-C 程序都必须的运行时库 |
libstdc++ | 运行时库,包括定义为标准语言一部分的所有的 C++ 类和函数 |
表 2 列出的软件和 GCC 协同工作,目的是实现编译过程。有些是很基本的(例如 as 和 Id),而其他一些则是非常有用但不是严格需耍的。尽管这些工具中的很多都是各种 UNIX 系统的本地共具,但还是能够通过 GNU 包 binutils 得到大多数工具。
工具 | 描述 |
---|---|
addr2line | 给出一个可执行文件的内部地址,addr2line 使用文件中的调试信息将地址翻泽成源代码文 件名和行号。该程序是 binutils 包的一部分 |
ar | 这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。该程序是 binutils 包的一部分 |
as | GNU 汇编器。实际上它是一族汇编器,因为它可以被编泽或能够在各种不同平台上工作。 该程序是 binutils 包的一部分 |
autoconf | 产生的 shell 脚木自动配置源代码包去编泽某个特定版木的 UNIX |
c++filt | 程序接受被 C++ 编泽程序转换过的名字(不是被重载的),而且将该名字翻泽成初始形式。 该程序是 binutils 包的一部分 |
f2c | 是 Fortran 到C的翻译程序。不是 GCC 的一部分 |
gcov | gprof 使用的配置工具,用来确定程序运行的时候哪一部分耗时最大 |
gdb | GNU 调试器,可用于检查程序运行时的值和行为 |
GNATS | GNU 的调试跟踪系统(GNU Bug Tracking System)。一个跟踪 GCC 和其他 GNU 软件问题的在线系统 |
gprof | 该程序会监督编泽程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供 的配置文件来优化程序。该程序是 binutils 包的一部分 |
ld | GNU 连接程序。该程序将目标文件的集合组合成可执行程序。该程序是 binutils 包的一部 |
libtool | 一个基本库,支持 make 程序的描述文件使用的简化共享库用法的脚木 |
make | 一个工具程序,它会读 makefile 脚木来确定程序中的哪个部分需要编泽和连接,然后发布 必要的命令。它读出的脚木(叫做 makefile 或 Makefile)定义了文件关系和依赖关系 |
nlmconv | 将可重定位的目标文件转换成 NetWare 可加载模块(NetWare Loadable Module, NLM)。该 程序是 binutils 的一部分 |
nm | 列出目标文件中定义的符号。该程序是 binutils 包的一部分 |
objcopy | 将目标文件从一种二进制格式复制和翻译到另外一种。该程序是 binutils 包的一部分 |
objdump | 显示一个或多个目标文件中保存的多种不同信息。该程序是 binutils 包的一部分 |
ranlib | 创建和添加到 ar 文档的索引。该索引被 Id 使用来定位库中的模块。该程序是 binutils 包的一部分 |
ratfor | Ratfor 预处理程序可由 GCC 激活,但不是标准 GCC 发布版的一部分 |
readelf | 从 ELF 格式的目标文件显示信息。该程序是 binutils 包的一部分 |
size | 列出目标文件中每个部分的名字和尺寸。该程序是 binutils 包的一部分 |
strings | 浏览所有类型的文件,析取出用于显示的字符串。该程序是 binutils 包的一部分 |
strip | 从目标文件或文档库中去掉符号表,以及其他调试所需的信息。该程序是 binutils 包的一部 |
vcg | Ratfor 浏览器从文木文件中读取信息,并以图表形式显示它们。而 vcg 工具并不是 GCC 发布中的一部分,但 -dv 选项可被用来产生 vcg 可以理解的优化数据的格式 |
windres | Window 资源文件编泽程序。该程序是 binutils 包的一部分 |
2,编译和链接
1)编译和链接一次性操作完成
方法1:gcc main.c #在 gcc 命令后面紧跟源文件名,会在当前目录生成a.out可执行文件
方法2:gcc main.c -o main #可以透过-o指定生成exe文件的名称
2)编译和链接分开操作
step1:编译
方法1: gcc -c main.c #就将 main.c 编译为 main.o
方法2:gcc -c main.c -o a.o #这样生成的目标文件的名字就是 a.o
step2:链接
方法1:gcc main.o #就将 main.o 链接为 a.out
方法2:gcc main.o -o main.out #这样生成的可执行文件的名字就是 main.out
3,GCC 编译器在编译一个C语言程序时需要经过以下 4 步:
将C语言源程序预处理,生成.i文件。
预处理后的.i文件编译成为汇编语言,生成.s文件。
将汇编语言文件经过汇编,生成目标文件.o文件。
将各个模块的.o文件链接起来生成一个可执行程序文件。
GCC 编译流程如下图所示:
.i
文件、.s
文件、.o
文件可以认为是中间文件或临时文件,如果使用 GCC 一次性完成C语言程序的编译,那么只能看到最终的可执行文件,这些中间文件都是看不到的,因为 GCC 已经经它们删除了。
3,gcc选项
-c
编译、汇编指定的源文件,但是不进行链接
-S
将C语言源文件编译为汇编语言,但是并不汇编该程序。使用该选项,我们可以查看C语言代码对应的汇编代码。
-E
将C语言源文件进行预处理,但是并不编译该程序。对于一般的预处理问题,可以使用这个选项进行查看,例如,宏的展开问题、文件的包含问题等。
-I
指定包含的头文件的目录
-g 选项
可生成能被 gdb 调试器所使用的调试信息。
-o
指定输出文件
-o [file1] [file2]
将文件 file2 编译成可执行文件 file1
+++++++++++++++++++++++++++++++++++++++++++++++++++
-o选项使用举例
1) 将源文件作为输入文件,将可执行文件作为输出文件,也即完整地编译整个程序:
$ gcc main.c func.c -o app.out
将 main.c 和 func.c 两个源文件编译成一个可执行文件,其名字为 app.out。如果不使用 -o 选项,那么将生成名字为 a.out 的可执行文件。
2) 将源文件作为输入文件,将目标文件作为输出文件,也即只编译不链接:
$ gcc -c main.c -o a.o
将源文件 main.c 编译为目标文件 a.o。如果不使用 -o 选项,那么将生成名为 main.o 的目标文件。
3) 将源文件作为输入文件,将预处理文件作为输出文件,也即只进行预处理操作:
$ gcc -E main.c -o demo.i
对源文件 main.c 进行预处理操作,并将结果放在 demo.i 文件中。如果不使用 -o 选项,那么将生成名为 main.i 的预处理文件。
4) 将目标文件作为输入文件,将可执行文件作为输出文件:
$ gcc -c func.c main.c
$ gcc func.o main.o -o app.out
第一条命令只编译不链接,将生成 func.o 和 main.o 两个目标文件。第二条命令将生成的两个目标文件生成最终的可执行文件 app.out。如果不使用 -o 选项,那么将生成名字为 a.out 的可执行文件。
+++++++++++++++++++++++++++++++++++++++++++++++++++
-shared
生成动态链接库。输入文件可以是源文件、汇编文件或者目标文件。
-fPIC
作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code)
+++++++++++++++++++++++++++++++++
举例
从源文件生成动态链接库:
$ gcc -fPIC -shared func.c -o libfunc.so
从目标文件生成动态链接库:
$ gcc -fPIC -c func.c -o func.o
$ gcc -shared func.o -o libfunc.so
+++++++++++++++++++++++++++++++++
摘自:http://c.biancheng.net/view/2382.html
-O0 、-O1 、-O2 、-O3
编译器的优化选项的 4 个级别,-O0 表示没有优化, -O1为 缺省值,-O3 优化级别最高。
gcc 命令的常用选项
选项 | 解释 |
---|---|
-ansi | 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色, 例如 asm 或 typeof 关键词。 |
-c | 只编译并生成目标文件。 |
-DMACRO | 以字符串"1"定义 MACRO 宏。 |
-DMACRO=DEFN | 以字符串"DEFN"定义 MACRO 宏。 |
-E | 只运行 C 预编译器。 |
-g | 生成调试信息。GNU 调试器可利用该信息。 |
-IDIRECTORY | 指定额外的头文件搜索路径DIRECTORY。 |
-LDIRECTORY | 指定额外的函数库搜索路径DIRECTORY。 |
-lLIBRARY | 连接时搜索指定的函数库LIBRARY。 |
-m486 | 针对 486 进行代码优化。 |
-o FILE | 生成指定的输出文件。用在生成可执行文件时。 |
-O0 | 不进行优化处理。 |
-O 或 -O1 | 优化生成代码。 |
-O2 | 进一步优化。 |
-O3 | 比 -O2 更进一步优化,包括 inline 函数。 |
-shared | 生成共享目标文件。通常用在建立共享库时。 |
-static | 禁止使用共享连接。 |
-UMACRO | 取消对 MACRO 宏的定义。 |
-w | 不生成任何警告信息。 |
-Wall | 生成所有警告信息。 |
摘自:http://www.runoob.com/w3cnote/gcc-parameter-detail.html
GCC选项 –I,-l,-L
-I:指定第一个寻找头文件的目录
-L:指定第一个寻找库文件的目录
-l:表示在库文件目录中寻找指定的动态库文件
例:
gcc –o hello hello.c –I /home/hello/include –L /home/hello/lib –lworld
/home/hello/include 作为第一个头文件的寻找目录。头文件寻找顺序:/home/hello/include –> /usr/include –> usr/local/include
/home/hello/lib 作为第一个库文件的寻找目录。库文件的寻找顺序:/home/hello/lib –> /lib –> /usr/lib –> /usr/local/lib
-lworld 表示在库文件路径中寻找libworld.so的动态库文件
4,库搜索路径
静态库链接时搜索路径顺序:
1. ld会去找GCC命令中的参数-L
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的
动态链接时、执行时搜索路径顺序:
1. 编译目标代码时指定的动态库搜索路径
2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib
有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径
摘自:http://www.sohu.com/a/165547861_777180
32位版:加上 -m32 参数,生成32位的代码。
64位版:加上 -m64 参数,生成64位的代码。
debug版:加上 -g 参数,生成调试信息。
release版:加上 -static 参数,进行静态链接,使程序不再依赖动态库。加上 -O3 参数,进行最快速度优化。加上-DNDEBUG参数,定义NDEBUG宏,屏蔽断言。
当没有-m32或-m64参数时,一般情况下会生成跟操作系统位数一致的代码,但某些编译器存在例外,例如——
32位Linux下的GCC,默认是编译为32位代码。
64位Linux下的GCC,默认是编译为64位代码。
Window系统下的MinGW,总是编译为32位代码。因为MinGW只支持32位代码。
Window系统下的MinGW-w64(例如安装了TDM-GCC,选择MinGW-w64),默认是编译为64位代码,包括在32位的Windows系统下。