9.5 KiB
简介
gcc一般会进行预处理,编译,汇编,连接四步。
gcc选项
通用选项
-c # 不运行连接器,这样就只生成汇编器生成的目标文件。
-S|-E #
-specs=<file> # 编译器读取标准specs文件后再处理<file>,用来覆盖传给cc1,cc1plus,as,ld等的默认开关。
C语言选项
-fno-buitin # 不使用C语言的内建函数
-std=<standard> #
C++语言选项
-ffreestanding # 指示编译目标为独立环境。这意味着-fno-builtin。
Objective-C和Objective-C++语言选项
诊断信息格式选项
请求或禁止Warning选项
-w # 不生成警告信息
-Wall # 生成所有警告信息
-Werror # 让所有的警告都变成错误
-Wunused-function #
-Wunused-label # 当一个标签只声明而不使用时进行警告
-Wunused-parameter # 当函数参数未使用时进行警告
-wunused-variable # 变量只定义而未使用时进行警告
-Wunused-value # 当一个语句的计算结果未使用时进行警告
-Wunused # 所有-Wunused-*选项加到一块
C和Objective-C专用Warning选项
调试选项
-g # 生成调试信息,其格式为操作的本地格式(stabs, COFF, XCOFF, DWARF)。
-ggdb # 尽可能生成gdb调试信息
优化选项
-fomit-frame-pointer # 在不需要frame指针的函数中忽略frame指针。
-fno-omit-frame-pointer # 看起来与-fomit-frame-pointer相反。
-foptimize-sibling-calls # 优化同级和尾部递归调用。
-fno-optimize-sibling-calls # 看起来与-foptimize-sibling-calls相反。
-fno-stack-protector # 禁用堆栈保护
-O0 # 不进行优化
-O1或-O # 缺省优化
-O2 # 比-O1高一级的优化
-Os # 使用所有-O2优化,但不缩减代码尺寸
-O3 # 最高级别优化
程序工具选项
-pg #
预处理器选项
-Dmacro[=value] # 预定义宏macro,其值默认为1
-M # 输出依赖关系的规则,而不是预处理的结果
-MM # 类似于-M,但不提示系统目录里的头文件
-MF file # 与-M或-MM一块使用时,将依赖写入文件file
-MD # 相当于-M -MF file,只是-E不是隐含的。file的确定依赖于-o选项。
-MMD # 和-MD一样,但只提示用户头文件,不提示系统头文件。
汇编器选项
链接器选项
-pie # 产生一个动态链接的位置无关可执行文件。为获得一个可预测的结果,还需要指定编译时对应的选项(-fpic, -fPIE, 或模型子选项)。
-no-pie # 不要产生动态链接的位置无关可执行文件。
-l # 指定要链接的库。默认为系统的库的路径。可查看/etc/ld.so.conf文件获取系统库路径的详情。
-static # 覆盖-pie选项,且不链接到共享库。
-T # 指定链接脚本。在没有操作系统的裸板上,可能需要-T选项来避免对未定义符号的引用。可以在搜索“lds链接脚本”关键字得到更详细信息。
-Wl,option # 把option作为选项传递给链接器。如果option里包含逗号,传递给链接器的时候逗号会被替换为空格,这个语法的好处是:可以传递多个选项过去,或者给选项指定一个参数。
文件夹选项
-Idir # 在dir目录内寻找头文件
-Ldir # 指定库所在的目录。如果库不在系统库的目录下,需要使用此参数。
-nostdinc # 不使用系统缺省头文件目录
-nostdlib # 链接时不使用标准的系统启动文件或库。
代码生成选项
开发者选项
机器相关选项
# X86
-m32 # 生成32位代码
控制输出类型的选项
RISC-V选项
# for GCC7.3.0
-mbranch-cost=n
# 将branch的cost设置为大约n条指令。
-mplt, -mno-plt
# 当生成PIC代码时,是否允许使用PLTs。默认允许。
-mabi=ABI-string
# 指定整数和浮点调用规约。ABI-string由两部分组成:整数类型的大小和浮点型的寄存器。如-march=rv64ifd -mabi=lp64d指long和指针是64位(隐式定义了int类型是32位),F寄存器里使用的浮点值是64位;-mabi=lp64f指long和指针是64位,使用f扩展的寄存器(32位);作为对比,march=rv64ifd -mabi=lp64f指的是编译器仍然可以在生成的代码里使用F和D扩展,但寄存器里传递的浮点值只能是32位。而对march=rv64ifd -mabi=lp64来说,则不使用浮点寄存器。
# 这个参数的默认值是系统决定的,用户如果想使用特定的调用约定就要明确指定出来。有效的调用约定有:ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d。要注意一些调用约定在某些ISAs上是不可能实现的:例如,-march=rv32if -mabi=ilp32d是无效的,因为ABI需要在F寄存器中传递64位值,但是F寄存器只有32位宽。
-mfdiv, -mno-fdiv
# 是否使用浮点除法或开方指令。这要求F或D扩展。默认如果硬件支持那些指令就使用它们。
-mdiv, -mno-div
# 是否使用整数除法的指令。这要求M扩展。默认如果硬件支持那些指令就使用它们。
-march=ISA-string
# 为给定RISC-V ISA生成代码。ISA-string要求小写。如rv64i,rv32g, rv32imaf等。
-mtune=processor-string
# 优化通过微架构名定义的给定处理器的输出
-msmall-data-limit=n
# 将小于n字节的全局和静态数据放到一个特定的section。
-msave-restore, -mno-save-restore
# 是否使用更小但更慢的开始和结束代码,这些代码使用的是库函数调用。默认是使用快速的内联函数来实现开始和结束代码。
-mstrict-align, -mno-strict-align
# 是否生成未对齐的内存访问。默认设置取决于我们正在优化的处理器是否支持快速的未对齐访问。
-mcmodel=medlow
# 为medium-low代码模型创建代码。要求程序必须在2G地址范围内,且是-2G到2G之间。这是默认的代码模型。它寻址使用的是lui/ld指令。
-mcmodel=medany
# 为medium-any代码模型创建代码。要求程序必须在2G地址范围内。它寻址使用的是auipc/ld指令。
-mexplicit-relocs, -mno-exlicit-relocs
# 在处理符号地址时是否使用汇编程序迁移操作符
gcc配置文件
# gcc调用不同的程序完成编译、汇编和链接。这些行为都是通过SPEC字符串来控制的。可以通过-specs参数指定一个SPEC文件来覆盖默认SPEC字符串。SPEC文件由一些指令组成,这些指令通过空行来分割。可能的指令如下:
%include <file> # 将<file>的内容插入到当前位置
%include_noerr <file> # 等同于%include,但没找到<file>也不产生错误信息
%rename <old_name> <new_name> # 将SPEC字符串<old_name>改名为<new_name>
*[spec_name]: # 删除、创建或覆盖SPEC字符串。内容为空表示删除,spec_name不存在表示创建,spec_name存在表示覆盖,内容以+开头表示追加。
[suffix]: # 以suffix为后缀的文件的处理方法。
# gcc内置的SPEC字符串:
asm
asm_final
cpp
cc1 # 传递给c编译器的选项
cc1plus
endfile # 链接的最后需要包含的目标文件
link # 传递给链接器的选项
lib
libgcc
linker
predefines
singed_char
startfile # 一开始就需要传递给链接器的目标文件
# 变量以%开头,如下是一些预定义变量:
%s # 当前参数是某个库或可执行文件的名字。搜索标准的目录列表来查找这个文件,如果找到了就用命名来进行替换。
%:function(args) # 调用函数function,args为要传递的参数,内建支持的函数有:
getenv
if-exists # 判断参数里定义的文件是否存在,如存在则返回该文件名称
if-exists-else
%{!S:X} # 如果没有使用-S选项,则替换成X。
gcc使用过程错误解决
错误提示:error while loading shared libraries: libncursesw.so.5
原因分析:原因一,新系统使用旧系统编译出来的文件,但两个系统支持的库版本不一致,所以引发的这个问题。原因二,网上有人说是系统升级不完全,需要换源。
解决方法:对于原因一,要把需要的二进制文件重新编译一遍。对于原因二,要换源再升级系统,看看所缺的库是否回来了。
错误提示:fatal error: asm/socket.h: 没有那个文件或目录
原因分析:ubuntu将asm文件夹改名为了asm-generic,所以找不到asm文件夹了
解决方法:创建一个链接asm指向文件夹asm-generic
错误提示:Instruction csrw requires absolute expression
原因分析:这是由于编译器版本不正确引起的,由于riscv指令集尙处于发展阶段,所以不同版本的指令集可能是不一样的
解决方法:重新编译工链,要使用指令集对应的编译器版本号
错误提示:undefined reference to `__alltraps'
原因分析:没把包含__alltraps
的源文件加入编译系统,导致链接器找不到对__alltraps
的引用
解决方法:修改Makefile,把相应源文件加入编译系统
错误提示:a label can only be part of a statement and a declaration is not a statement
原因分析:一个标签的后面只能跟语句而不能跟声明,我的问题在于switch语句里声明了一个变量
解决方法:把变量声明放到switch语句的外面
错误提示:multiple definition of XXX
原因分析:我碰到的问题是在头文件里实现了函数,当多个二进制文件链接到一块的时候会产生冲突
解决方法:在头文件里声明函数,在其它c文件里实现这个函数。变量定义应该也会产生这个问题,所以不要在头文件里定义变量,而只声明变量。