GCC部分编译选项解析
1. -mthumb 和 -mthumb-interwork
"-mthumb”的意义是:使用这个编译选项生成的目标文件是Thumb指令的,目前还没有发现GNU编译器中有哪一个选项可以指定生成的目标文件是thumb-2的。
相对应的,“-marm“的意义是,使用编译选项生成的目标文件是ARM指令的。
注意,不同编译器对该选项是否默认开启是不一样的,实际测试的结果如下:
arm-none-eabi-gcc (20160919) 为Cortex-m4编译,(-mcpu=cortex-m4),不加-mthumb选项,提示“target CPU does not support ARM mode”(Cortex-M处理器只支持Thumb指令,包含16位和32位);
arm-none-eabi-gcc (20191025) 为Cortex-m4编译,(-mcpu=cortex-m4),不加-mthumb选项,可以顺利通过编译。
"-mthumb-interwork ”编译选项生成的目标文件就是thumb的,但是可以被其他的ARM的目标文件交叉调用。
一般如果工程中需要一部分文件目标文件编译为ARM指令,一部分目标文件编译为Thumb指令时, 可以在这两部分的编译选项中都加入"-mthumb-interwork”选项,这样就可以在后面将这两部分链接为一个可执行文件,例如:
arm-elf-gcc -mthumb-interwork -marm -c arm.c -o arm.o arm-elf-gcc -mthumb-interwork -mthumb -c thumb.c -o thumb.o arm-elf-gcc -mthumb-interwork arm.o thumb.o -o a.out
2.-mfloat-abi=softfp 和 -mfloat-abi=hard
该选项指定了浮点运算的实现方式,用软件计算还是硬件计算。实际使用中需要根据硬件特性(是否支持硬件浮点单元)以及链接的Lib库(包括libc,libm等)类型进行选择,如果不匹配链接时会出现"VFP register arguments"错误(VFP=Virtual Float Point,虚拟浮点运算)。
如果不加以指定,默认使用-mfloat-abi=softfp 软件浮点方式。
3. -fno-builtin
-fno-builtin用于解决当用户自定义的函数与C语言的内建函数(C库函数)冲突的问题。当用户自定义的函数与内建函数冲突时,若在gcc的编译选项中加上-fno-builtin时,则表示不使用C语言的内建函数。
对于有些函数不想用内建函数,而其他的某些函数还是希望使用内建函数时的场景,那么可以使用 -fno-builtin-function 选项,其中的function就是冲突的函数名,例如-fno-builtin-printf。
4. --wrap=
这是一个链接器(LD)选项,其作用是将某个函数进行重定向,例如指定--wrap=printf 选项,那么所有调用printf的地方都会被重定向到__wrap_printf函数;注意__wrap_printf函数需要重新实现,否则会出现链接错误。另外__wrap_printf不需要另外声明,只需要有printf函数的声明即可。
5. spec选项
-specs=file
Process file after the compiler reads in the standard specs file, in order to override the defaults which the gcc
driver program uses when determining what switches to pass to cc1, cc1plus, as, ld, etc. More than one -specs=file
can be specified on the command line, and they are processed in order, from left to right.
编译器读入标准规范文件后处理文件,以覆盖gcc使用的默认值,可以传递给cc1、cc1plus、as、ld等程序。多个-specs=文件 可以在命令行上指定,并按从左到右的顺序处理。
具体使用:
aarch64-none-elf-gcc -T sample_threadx.ld -specs=nosys.specs startup.o v8_aarch64.o v8_utils.o vectors.o MP_Mutexes.o GICv3_gicd.o GICv3_gicr.o sp804_timer.o timer_interrupts.o sample_threadx.o tx.a -o sample_threadx.axf -Xlinker -Map=sample_threadx.map
aarch64-none-elf-gcc -T sample_threadx.ld -specs=rdimon.specs startup.o v8_aarch64.o v8_utils.o vectors.o MP_Mutexes.o GICv3_gicd.o GICv3_gicr.o sp804_timer.o timer_interrupts.o sample_threadx.o tx.a -o sample_threadx.axf -Xlinker -Map=sample_threadx.map
以aarch64-none-elf-gcc为例,其读入的后处理文件位于 .....gcc-arm-10.2-2020.11-mingw-w64-i686-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.2.1文件夹中,分别是nosys.specs和rdimon.specs。
以nosys.specs为例:
%rename link_gcc_c_sequence nosys_link_gcc_c_sequence *nosys_libgloss: -lnosys *nosys_libc: %{!specs=nano.specs:-lc} %{specs=nano.specs:-lc_nano} *link_gcc_c_sequence: %(nosys_link_gcc_c_sequence) --start-group %G %(nosys_libc) %(nosys_libgloss) --end-group
其结构很简单,主要是指定了两个库选项变量,分别是%(nosys_libc) 和%(nosys_libgloss);
%(nosys_libgloss)在该文件中固定等于-lnosys, %(nosys_libc)取决于specs文件是否等于nano.specs, 这里显然不成立,那么%(nosys_libc)就等于-lc。
解析完成后-lnosys和-lc选项就传递给了gcc命令。
对于spec文件的语法解析可以详细参阅如下链接:
https://blog.csdn.net/qinglinsan/article/details/11478091