【gcc编译优化系列】gcc编译链接时候–specs=kernel.specs链接属性究竟是个啥?


1 问题来源

近来关注rt-thread的论坛稍微少了一些,今天突然在论坛里面看到这么一个问题
在这里插入图片描述
为何会对这个问题感兴趣呢?
主要有以下两个原因:

  • 最近都在研究一些gcc编译链接相关的知识,做了一些笔记,方便自己加深理解和记忆;
  • 这个specs选项,隐约记得在哪里见过,但是又记不清楚来龙去脉,看来还是记忆不够深刻。

于是乎,我决定趁着这个机会,好好扒一扒这个specs选项。

2 初步分析

2.1 内事不决问百度,外事不决问谷歌

二话不说,先baidu之,如下:
在这里插入图片描述
没找到合适的,那google一下?无奈,没有梯子,那就bing一下吧:
在这里插入图片描述
问题答案没找到,倒是把问题自己给找到了。

2.2 开发不懂问‘男人’

都说男人靠得住,母猪都上树,但是作为一个长期混迹在Linux开发环境下的程序猿,我可以很负责任地告诉,男人是最不会骗人的,不信你man一下:

recan@ubuntu:~$ man gcc | grep "specs"
           -specs=file  -wrapper @file  -ffile-prefix-map=old=new -fplugin=file  -fplugin-arg-name=arg -fdump-ada-spec[-slim]
           -fconstexpr-loop-limit=n -fconstexpr-ops-limit=n -fno-elide-constructors -fno-enforce-eh-specs -fno-gnu-keywords
           -dletters  -dumpspecs  -dumpmachine  -dumpversion -dumpfullversion  -fchecking  -fchecking=n  -fdbg-cnt-list
           -mshort-calls -nodevicelib  -nodevicespecs -Waddr-space-convert  -Wmisspelled-isr
           declaration).  Such files are also called specs.
       -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
           For C and C++ source and include files, generate corresponding Ada specs.
           In conjunction with -fdump-ada-spec[-slim] above, generate Ada specs as child units of parent unit.
       -fno-enforce-eh-specs
           used in filesystem paths and specs. Depending on how the compiler has been configured it can be just a single number
       -dumpspecs
           Print the compiler's built-in specs---and don't do anything else.  (This is used when GCC itself is being built.)
troff: <standard input>:17361: warning [p 110, 20.7i]: can't break line
       -nodevicespecs
           Don't add -specs=device-specs/specs-<mcu> to the compiler driver's command line.  The user takes responsibility for
           (/usr/lpp/ppe.poe/), or the specs file must be overridden with the -specs= option to specify the appropriate

这句命令行的意思就是在man gcc的结果里面搜索specs关键字,注意仔细看,我们发现了有-specs=file这个关键信息,不用猜,就是它了。
为了更好地说明,我把这段描述完整地拎出来:

-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.

需要点英文理解能力,但是语意并不难,实在不行,用翻译软件也可以搞定:

-specs=文件
编译器读入标准规范文件后处理文件,以覆盖gcc使用的默认值
驱动程序用于确定要传递给cc1、cc1plus、as、ld等的开关。多个-specs=文件
可以在命令行上指定,并按从左到右的顺序处理。

OK,意思已经很明确了,就是用于覆盖gcc默认的传递参数,这些新的参数是在一个新的文件里面里面指定,比如问题中的就是kernel.specs

2.3 gcc默认的specs参数

如果你好好读man gcc的返回,你会发现有这么一个-dumpspec选项,它就是记录了gcc默认的specs参数,为了说明下specs文件长啥样,我把它导出来看看:(说明下,我这个是x64环境下的gcc,如果是交叉编译的gcc,替换对应的gcc即可,方法都是一样的。)

recan@ubuntu:~$ gcc -dumpspecs > default.specs
recan@ubuntu:~$ 
recan@ubuntu:~$ cat default.specs 
*asm:
%{m16|m32:--32}  %{m16|m32|mx32:;:--64}  %{mx32:--x32}  %{msse2avx:%{!mavx:-msse2avx}}

*asm_debug:
%{%:debug-level-gt(0):%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}} %{fdebug-prefix-map=*:--debug-prefix-map %*}

*asm_final:
%{gsplit-dwarf: 
       objcopy --extract-dwo     %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O}      %{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo} 
       objcopy --strip-dwo       %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O}     }

*asm_options:
%{-target-help:%:print-asm-header()} %{v} %{w:-W} %{I*}  %{gz|gz=zlib:--compress-debug-sections=zlib} %{gz=none:--compress-debug-sections=none} %{gz=zlib-gnu:--compress-debug-sections=zlib-gnu} %a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}

*invoke_as:
%{!fwpa*:   %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}   %{!S:-o %|.s |
 as %(asm_options) %m.s %A }  }

*cpp:
%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}

*cpp_options:
%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w} %{f*} %{g*:%{%:debug-level-gt(0):%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*} %{undef} %{save-temps*:-fpch-preprocess} %(distro_defaults)

*cpp_debug_options:
%{d*}

*cpp_unique_options:
%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %@{I*&F*} %{P} %I %{MD:-MD %{!o:%b.d}%{o*:%.d%*}} %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}} %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}} %{remap} %{g3|ggdb3|gstabs3|gxcoff3|gvms3:-dD} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %{H} %C %{D*&U*&A*} %{i*} %Z %i %{E|M|MM:%W{o*}}

*trad_capable_cpp:
cc1 -E %{traditional|traditional-cpp:-traditional-cpp}

*cc1:
%{!mandroid|tno-android-cc:%(cc1_cpu) %{profile:-p};:%(cc1_cpu) %{profile:-p} %{!mglibc:%{!muclibc:%{!mbionic: -mbionic}}} %{!fno-pic:%{!fno-PIC:%{!fpic:%{!fPIC: -fPIC}}}}}

*cc1_options:
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)}  %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}}  %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{Qy:} %{-help:--help} %{-target-help:--target-help} %{-version:--version} %{-help=*:--help=%*} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{coverage:-fprofile-arcs -ftest-coverage} %{fprofile-arcs|fprofile-generate*|coverage:   %{!fprofile-update=single:     %{pthread:-fprofile-update=prefer-atomic}}}

*cc1plus:


*link_gcc_c_sequence:
%{static|static-pie:--start-group} %G %{!nolibc:%L}    %{static|static-pie:--end-group}%{!static:%{!static-pie:%G}}

*distro_defaults:
%{!fno-asynchronous-unwind-tables:-fasynchronous-unwind-tables} %{!fno-stack-protector:%{!fstack-protector-all:%{!ffreestanding:%{!nostdlib:%{!fstack-protector:-fstack-protector-strong}}}}} %{!Wformat:%{!Wformat=2:%{!Wformat=0:%{!Wall:-Wformat} %{!Wno-format-security:-Wformat-security}}}} %{!fno-stack-clash-protection:-fstack-clash-protection} %{!fcf-protection*:%{!fno-cf-protection:-fcf-protection}}

*link_ssp:
%{fstack-protector|fstack-protector-all|fstack-protector-strong|fstack-protector-explicit:}

*endfile:
%{!mandroid|tno-android-ld:%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}    %{mpc32:crtprec32.o%s}    %{mpc64:crtprec64.o%s}    %{mpc80:crtprec80.o%s} %{fvtable-verify=none:%s;      fvtable-verify=preinit:vtv_end_preinit.o%s;      fvtable-verify=std:vtv_end.o%s}    %{static:crtend.o%s;      shared|static-pie|!no-pie:crtendS.o%s;      :crtend.o%s} crtn.o%s %{fopenacc|fopenmp:crtoffloadend%O%s};:%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}    %{mpc32:crtprec32.o%s}    %{mpc64:crtprec64.o%s}    %{mpc80:crtprec80.o%s} %{shared: crtend_so%O%s;: crtend_android%O%s}}

*link:
%{!r:--build-id} %{!static|static-pie:--eh-frame-hdr} %{!mandroid|tno-android-ld:%{m16|m32|mx32:;:-m elf_x86_64}                    %{m16|m32:-m elf_i386}                    %{mx32:-m elf32_x86_64}   --hash-style=gnu   --as-needed   %{shared:-shared}   %{!shared:     %{!static:       %{!static-pie:     %{rdynamic:-export-dynamic}     %{m16|m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:%{mmusl:/lib/ld-musl-i386.so.1;:/lib/ld-linux.so.2}}}}       %{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:%{mmusl:/lib/ld-musl-x86_64.so.1;:/lib64/ld-linux-x86-64.so.2}}}}         %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:%{mmusl:/lib/ld-musl-x32.so.1;:/libx32/ld-linux-x32.so.2}}}}}}     %{static:-static} %{static-pie:-static -pie --no-dynamic-linker -z text}};:%{m16|m32|mx32:;:-m elf_x86_64}                    %{m16|m32:-m elf_i386}                    %{mx32:-m elf32_x86_64}   --hash-style=gnu   --as-needed   %{shared:-shared}   %{!shared:     %{!static:       %{!static-pie:      %{rdynamic:-export-dynamic}     %{m16|m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:%{mmusl:/lib/ld-musl-i386.so.1;:/lib/ld-linux.so.2}}}}       %{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:%{mmusl:/lib/ld-musl-x86_64.so.1;:/lib64/ld-linux-x86-64.so.2}}}}     %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:%{mmusl:/lib/ld-musl-x32.so.1;:/libx32/ld-linux-x32.so.2}}}}}}     %{static:-static} %{static-pie:-static -pie --no-dynamic-linker -z text}} %{shared: -Bsymbolic}}

*lib:
%{!mandroid|tno-android-ld:%{pthread:-lpthread} %{shared:-lc}    %{!shared:%{profile:-lc_p}%{!profile:-lc}};:%{shared:-lc}    %{!shared:%{profile:-lc_p}%{!profile:-lc}} %{!static: -ldl}}

*link_gomp:


*libgcc:
%{static|static-libgcc|static-pie:-lgcc -lgcc_eh}%{!static:%{!static-libgcc:%{!static-pie:%{!shared-libgcc:-lgcc --push-state --as-needed -lgcc_s --pop-state}%{shared-libgcc:-lgcc_s%{!shared: -lgcc}}}}}

*startfile:
%{!mandroid|tno-android-ld:%{shared:;      pg|p|profile:%{static-pie:grcrt1.o%s;:gcrt1.o%s};      static:crt1.o%s;      static-pie:rcrt1.o%s;      !no-pie:Scrt1.o%s;      :crt1.o%s} crti.o%s    %{static:crtbeginT.o%s;      shared|static-pie|!no-pie:crtbeginS.o%s;      :crtbegin.o%s}    %{fvtable-verify=none:%s;      fvtable-verify=preinit:vtv_start_preinit.o%s;      fvtable-verify=std:vtv_start.o%s} %{fopenacc|fopenmp:crtoffloadbegin%O%s};:%{shared: crtbegin_so%O%s;:  %{static: crtbegin_static%O%s;: crtbegin_dynamic%O%s}}}

*cross_compile:
0

*version:
9.3.0

*multilib:
. !m32 !m64 !mx32;32:../lib32:i386-linux-gnu m32 !m64 !mx32;64:../lib:x86_64-linux-gnu !m32 m64 !mx32;x32:../libx32:x86_64-linux-gnux32 !m32 !m64 mx32;

*multilib_defaults:
m64

*multilib_extra:


*multilib_matches:
m32 m32;m64 m64;mx32 mx32;

*multilib_exclusions:


*multilib_options:
m32/m64/mx32

*multilib_reuse:


*linker:
collect2

*linker_plugin_file:


*lto_wrapper:


*lto_gcc:


*post_link:


*link_libgcc:
%D

*md_exec_prefix:


*md_startfile_prefix:


*md_startfile_prefix_1:


*startfile_prefix_spec:


*sysroot_spec:
--sysroot=%R

*sysroot_suffix_spec:


*sysroot_hdrs_suffix_spec:


*self_spec:


*cc1_cpu:
%{march=native:%>march=native %:local_cpu_detect(arch)   %{!mtune=*:%>mtune=native %:local_cpu_detect(tune)}} %{mtune=native:%>mtune=native %:local_cpu_detect(tune)}

*link_command:
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:    %(linker) %{!fno-use-linker-plugin:%{!fno-lto:     -plugin %(linker_plugin_file)     -plugin-opt=%(lto_wrapper)     -plugin-opt=-fresolution=%u.res     %{flinker-output=*:-plugin-opt=-linker-output-known}     %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}}     }}%{flto|flto=*:%<fcompare-debug*}     %{flto} %{fno-lto} %{flto=*} %l %{static|shared|r:;!no-pie:-pie -z now} %{fuse-ld=*:-fuse-ld=%*}  %{gz|gz=zlib:--compress-debug-sections=zlib} %{gz=none:--compress-debug-sections=none} %{gz=zlib-gnu:--compress-debug-sections=zlib-gnu}  -z relro %X %{o*} %{e*} %{N} %{n} %{r}    %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!r:%{!nostartfiles:%S}}}     %{static|no-pie|static-pie:} %@{L*} %(mfwrap) %(link_libgcc) %{fvtable-verify=none:} %{fvtable-verify=std:   %e-fvtable-verify=std is not supported in this configuration} %{fvtable-verify=preinit:   %e-fvtable-verify=preinit is not supported in this configuration} %{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):%{!shared:libasan_preinit%O%s} %{static-libasan:%{!shared:-Bstatic --whole-archive -lasan --no-whole-archive -Bdynamic}}%{!static-libasan:%{!fuse-ld=gold:--push-state} --no-as-needed -lasan %{fuse-ld=gold:--as-needed;:--pop-state}}}     %{%:sanitize(thread):%{!shared:libtsan_preinit%O%s} %{static-libtsan:%{!shared:-Bstatic --whole-archive -ltsan --no-whole-archive -Bdynamic}}%{!static-libtsan:%{!fuse-ld=gold:--push-state} --no-as-needed -ltsan %{fuse-ld=gold:--as-needed;:--pop-state}}}     %{%:sanitize(leak):%{!shared:liblsan_preinit%O%s} %{static-liblsan:%{!shared:-Bstatic --whole-archive -llsan --no-whole-archive -Bdynamic}}%{!static-liblsan:%{!fuse-ld=gold:--push-state} --no-as-needed -llsan %{fuse-ld=gold:--as-needed;:--pop-state}}}}}} %o      %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):      %:include(libgomp.spec)%(link_gomp)}    %{fgnu-tm:%:include(libitm.spec)%(link_itm)}    %(mflib)  %{fsplit-stack: --wrap=pthread_create}    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} %{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address): %{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}    %{static:%ecannot specify -static with -fsanitize=address}}    %{%:sanitize(thread): %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}    %{static:%ecannot specify -static with -fsanitize=thread}}    %{%:sanitize(undefined):%{static-libubsan:-Bstatic} %{!static-libubsan:--push-state --no-as-needed} -lubsan  %{static-libubsan:-Bdynamic} %{!static-libubsan:--pop-state} %{static-libubsan|static:%:include(libsanitizer.spec)%(link_libubsan)}}    %{%:sanitize(leak): %{static-liblsan|static:%:include(libsanitizer.spec)%(link_liblsan)}}}}}     %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}    %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*}  
%(post_link) }}}}}}

由于specs文件这块知识在我这,确实是个盲区,我还得记住巨人的肩膀,我找到了一篇参考价值比较大的文章
具体我不再细说里面的内容了,大家可以对照着来学习,简单捋一遍就会印象更深刻。

2.4 specs文件都放在哪里?

起初,当我们知道-specs=kernel.specs中的kernel.specs是一个文件的时候,我第一感觉就是:“嗯,应该在源码的bsp目录里面”,结果我拉去rt-smart的源码搜了一遍也没搜到:

takeout@newnew MINGW64 /c/llc/git_repos/rt-thread-share/rt-thread (rt-smart)
$ find . -name "kernel.specs"

takeout@newnew MINGW64 /c/llc/git_repos/rt-thread-share/rt-thread (rt-smart)
$ find . -name "*.specs"

这类名称的specs文件一个没搜到,倒是搜关键字的时候,有的bsp提到了nano.specs:
在这里插入图片描述
既然有些bsp的链接选项,明目张胆地引入nano.specs文件,而且编译不会报错,自然肯定有地方能找到它。
既然不在源码目录,那么还有一个可能就是在交叉编译工具链的目录里面,我们来找一找。
以我手上的gcc-arm-none-eabi-5_4-2016q3为例子:
`
在这里插入图片描述

这么一说,我想起了为何之前对specs有些印象,就是这两个nano.specsnosys.specs;baidu之,这下资料就很多了,这里给几个有效的参考链接:

在这里插入图片描述
在这里插入图片描述
看了第二个nosys.specs,再次勾起回忆,之前RRT论坛就有一个问题跟这个有关的,需要通过加入nosys.specs来解决的,当然我还看到它的解决思路,还真的是有点印象,仅此而已。
找到当时我回答的那个问题,大家也可以顺带看看当时我的思路。
在这里插入图片描述

另外,相关的问题我给出链接,大家有空都可以去看看,说不定能解决你的一些疑问。

2.5 愉快地结束

看到这里,楼主的疑问已经解答了,我自己对这个知识点也加深了理解,看来还是要多记笔记,真正进入到自己脑海里的东西才是自己的,否则永远只存在于搜索引擎中。

3 更多分享

欢饮大家关注我的github仓库01workstation,欢迎指正问题。

同时也非常欢迎关注我的CSDN主页和专栏:

【http://yyds.recan-li.cn】

【C/C++语言编程专栏】

【GCC专栏】

【信息安全专栏】

有问题的话,可以跟我讨论,知无不答,谢谢大家。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>