嵌入式学习笔记 : GCC选项

来源:互联网 发布:深圳天猫美工招聘 编辑:程序博客网 时间:2024/06/09 16:18

输出控制选项

Options Controlling the Kind of Output

  • -c
    Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
    对源文件进行预处理、编译、汇编,但不进行连接,所以最后会为每个源文件生成一个.o的目标文件,如为source.c生成source.o。

  • -S
    Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified.
    编译后既停止,不进行汇编,生成汇编代码的文件,默认为将”.c”、”.i”后缀替换为”.s”。

  • -E
    Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.
    预处理之后停止,生成内容送到标准输出。

  • -o file
    Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code.
    指定输出文件名为file,生成预处理、编译、汇编、连接的结果时都可以使用该选项。

连接器选项

Options for Linking

  • -shared
    Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option. For predictable results, you must also specify the same set of options that were used to generate code (-fpic, -fPIC, or model suboptions) when you specify this option.
    生成共享目标文件,可与其他目标文件一起链接生成可执行文件。

例01:

/* 以如下的三个C代码文件为基础进行实验,后面仍会用到 *//* mylib.h */void a();void b();/* mylib.c */void a() {}void b() {}/* main.c */int main() { a(); }

生成库文件:

$ lsmain.c mylib.c mylib.h$ gcc -c mylib.c -o mylib.o$ gcc -shared -o libmylib.a mylib.o

使用库文件进行连接:

$ lslibmylib.a main.c mylib.c mylib.h$ gcc -o test main.c ./libmylib.a

这样,如果想把实现的a()、b()函数提供给用户使用,而不想暴露源代码,可以只对用户发布库文件libmylib.a和头文件mylib.h。

  • -llibrary
    Search the library named library when linking.
    连接时搜索名为library的库。
    It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, `foo.o -lz bar.o’ searches library `z’ after file foo.o but before bar.o. If bar.o refers to functions in `z’, those functions may not be loaded.
    使用库的时候,要注意目标文件与库文件的顺序,如果目标文件使用了库文件中定义的函数,那么,目标文件要放在库文件之前,否则可能会引发函数未定义的错误。因为,gcc在处理符号时,不可能将库文件中所有目标文件的所有符号都记录到可执行文件的符号表中,只会使用我们所写的代码中未定义的符号去库中查找,而处理符号的过程是从左到右一次性的。如果真的需要,同一个库文件可以在一条命令里出现两次。
    The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
    对应的库文件名为liblibrary.a,即库名前面加lib前缀,后面加.a后缀。
    The directories searched include several standard system directories plus any that you specify with -L.
    搜索库文件的路径包括-L指定的路径。
    Normally the files found this way are library files—archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with `lib’ and `.a’ and searches several directories.
    一般,此方式寻找的库文件是由目标文件组成的归档文件。链接器会扫描该归档文件中的每一个目标文件,去查看是否有被引用但是未定义的符号位于其中。

例02
使用例01中的三个C文件开始

$ lsmain.c mylib.c mylib.h$ gcc -c mylib.c -o mylib.o$ gcc -shared -o libmylib.a mylib.o$ gcc -o test main.o -L. -lmylib

-L. 表示将当前目录(即.)添加到库搜索路径列表中
-lmylib 会去查找libmylib.a的库文件


  • -nostartfiles
    Do not use the standard system startup files when linking. The standard system libraries are used normally, unless -nostdlib or -nodefaultlibs is used.
    连接时不使用标准系统启动文件,标准库文件仍然正常使用。该文件中的函数会为main函数的调用准备系统环境,如初始化栈,在栈中放入环境变量和函数参数,即argc和argv,还会调用一些别的初始化函数,析构函数,等等。可能有人说怎么感觉在说C++啊,没错,C++的对象的初始化与析构的机制与此类似。

  • nostdlib
    Do not use the standard system startup files or libraries when linking. No startup files and only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored.
    不连接标准系统启动文件和标准库文件。

  • -Xlinker option
    Pass option as an option to the linker. You can use this to supply system-specific linker options which GCC does not know how to recognize.
    将选项作为链接器的选项传给链接器。链接器识别的选项,gcc未必识别。
    If you want to pass an option that takes a separate argument, you must use -Xlinker twice, once for the option and once for the argument. For example, to pass -assert definitions, you must write `-Xlinker -assert -Xlinker definitions’. It does not work to write -Xlinker “-assert definitions”, because this passes the entire string as a single argument, which is not what the linker expects.
    如果传递的选项携带参数,那么需要使用两次-Xlinker。
    如传递”-assert definitions”写成”-Xlinker -assert -Xlinker definitions”。
    When using the GNU linker, it is usually more convenient to pass arguments to linker options using the option=value syntax than as separate arguments. For example, you can specify `-Xlinker -Map=output.map’ rather than `-Xlinker -Map -Xlinker output.map’. Other linkers may not support this syntax for command-line options.
    使用GNU编译器时,可以简化上面的过程,写为”-Xlinker -assert=definitions”。
  • -Wl, option
    Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example,
    `-Wl,-Map,output.map’ passes `-Map output.map’ to the linker. When using the GNU linker, you can also get the same effect with `-Wl,-Map=output.map’.
    将选项传递给链接器。如果选项中有逗号,那么在逗号处分割成多个选项。
    `-Wl,-Map,output.map’ -> `-Map output.map’
  • -u symbol
    Pretend the symbol symbol is undefined, to force linking of library modules to define it. You can use -u multiple times with different symbols to force loading of additional library modules.
    使该符号为未定义的状态,这样,在连接的时候会强制将包含该符号定义的模块连接进来。

控制C方言(dialect)选项

Options Controlling C Dialect

  • -fno-builtin / -fno-builtin-function
    Don’t recognize built-in functions that do not begin with `__builtin_’ as prefix.
    不再识别和使用以__builtin_开头的内建函数。
    GCC normally generates special code to handle certain built-in functions more efficiently; for instance, calls to alloca may become single instructions that adjust the stack directly, and calls to memcpy may become inline copy loops. The resulting code is often both smaller and faster, but since the function calls no longer appear as such, you cannot set a breakpoint on those calls, nor can you change the behavior of the functions by linking with a different library. In addition, when a function is recognized as a built-in function, GCC may use information about that function to warn about problems with calls to that function, or to generate more efficient code, even if the resulting code still contains calls to that function.
    当你的C代码调用C库中的一些常用函数时,GCC可能不会去调用标准C库中的那些函数,而是使用内建函数进行取巧的处理,从而使代码又小又快,但是这样有时会给我们造成困扰。比如,自己写的C库函数abs,想要测试一下,abs就跟main函数在同一个文件,但是却尴尬的发现根本没调用,更别提调试了,此时可以使用该选项禁用内建函数。

例03

/* main.c */#include<stdio.h>int abs(int n) { return n+1; }int main() { printf("%d\n", abs(-3)); return 0; }

这样的代码,理论上应该输出 -2

$ gcc main.c$ ./a.out3

结果却为3,就是因为main调用的abs时,使用的是内建函数,不是我们写的abs,也不是系统C库中提供的abs函数。

$ gcc -fno-builtin main.c$ ./a.out-2

加入-fno-builtin选项,或者-fno-builtin-abs选项,可以抑制内建函数的使用,结果为-2,正是我们期望的。


GCC工具链有太多的选项,如果不是遇到相关的问题,真的不想一个一个的学习。所以,本文后期再根据兴趣逐渐补充完善。

阅读全文
0 0
原创粉丝点击