一、Usage: gcc [options] file...
Options:
-E Preprocess only; do not compile, assemble or link
-S Compile only; do not assemble or link
-c Compile and assemble, but do not link
1、编译汇编:$ gcc -c -o hello.o hello.c
2、链接:$ gcc -v -o hello hello.o
gcc会对.c文件默认进行预处理操作,-c再来指明了编译、汇编,从而得到.o文件
再通过gcc -v -o hello hello.o 将.o文件进行链接,-v显示编译过程,得到可执行程序。
链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,最终生成可以再特定平台运行的可执行程序。
gcc -v -nostalib -o hello hello.o 会提示因为没有链接系统标准启动文件和标准库文件,而链接失败
这个-nostalib选项常用于裸机/BootLoader、linux内核等,因为他们不需要启动文件、标准库文件
而一般应用程序才需要系统标准启动文件和标准库文件。
===================================================================
3、编译汇编:$ gcc -c -o hello.o hello.c
4、默认链接动态库:$ gcc -o hello_share hello.o
5、指定链接静态库:$ gcc -static -o hello_static hello.o
6、查看编译的可执行程序链接库类型:$ ldd hello
动态链接使用动态库进行连接,生成的程序在执行时需要加载所需的动态库才能运行。
动态链接生成的程序体积较小,但是必须依赖所需的动态库,否则无法运行。
静态链接使用静态库进行链接,生成的程序包含运行所需的全部库,可以直接运行,
不过静态链接生成的程序体积较大。
二、 其他GCC选项
命令 |
描述 |
-l library |
进行链接时搜索名为library的库。 |
-Idir |
把dir加入到搜索头文件的路径列表中。 |
-Ldir |
把dir加入到搜索库文件的路径列表中。 |
-Dname |
预定义一个名为name的宏,值为1。 |
-Dname=definition |
预定义名为name,值为definition的宏。 |
-ggdb |
为调试器 gdb 生成调试信息。level可以为1,2,3,默认值为2。 |
-g |
生成操作系统本地格式的调试信息。-g 和 -ggdb 并不太相同, -g 会生成 gdb 之外的信息。level取值同上。 |
-s |
去除可执行文件中的符号表和重定位信息。用于减小可执行文件的大小。 |
-M |
告诉预处理器输出一个适合make的规则,用于描述各目标文件的依赖关系。对于每个源文件,预处理器输出 一个make规则,该规则的目标项(target)是源文件对应的目标文件名,依赖项(dependency)是源文件中 `#include引用的所有文件。生成的规则可以是单行,但如果太长,就用`/'-换行符续成多行。规则 显示在标准输出,不产生预处理过的C程序。 |
-C |
告诉预处理器不要丢弃注释。配合`-E'选项使用。 |
-P |
告诉预处理器不要产生`#line'命令。配合`-E'选项使用。 |
-static |
在支持动态链接的系统上,阻止连接共享库。该选项在其它系统上无效。 |
-nostdlib |
不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。 |
Warnings |
|
-Wall |
会打开一些很有用的警告选项,建议编译时加此选项。 |
-W |
打印一些额外的警告信息。 |
-w |
禁止显示所有警告信息。 |
-Wshadow |
当一个局部变量遮盖住了另一个局部变量,或者全局变量时,给出警告。很有用的选项,建议打开。 -Wall 并不会打开此项。 |
-Wpointer-arith |
对函数指针或者void *类型的指针进行算术操作时给出警告。也很有用。 -Wall 并不会打开此项。 |
-Wcast-qual |
当强制转化丢掉了类型修饰符时给出警告。 -Wall 并不会打开此项。 |
-Waggregate-return |
如果定义或调用了返回结构体或联合体的函数,编译器就发出警告。 |
-Winline |
无论是声明为 inline 或者是指定了-finline-functions 选项,如果某函数不能内联,编译器都将发出警告。如果你的代码含有很多 inline 函数的话,这是很有用的选项。 |
-Werror |
把警告当作错误。出现任何警告就放弃编译。 |
-Wunreachable-code |
如果编译器探测到永远不会执行到的代码,就给出警告。也是比较有用的选项。 |
-Wcast-align |
一旦某个指针类型强制转换导致目标所需的地址对齐增加时,编译器就发出警告。 |
-Wundef |
当一个没有定义的符号出现在 #if 中时,给出警告。 |
-Wredundant-decls |
如果在同一个可见域内某定义多次声明,编译器就发出警告,即使这些重复声明有效并且毫无差别。 |
Optimization |
|
-O0 |
禁止编译器进行优化。默认为此项。 |
-O |
尝试优化编译时间和可执行文件大小。 |
-O2 |
更多的优化,会尝试几乎全部的优化功能,但不会进行“空间换时间”的优化方法。 |
-O3 |
在 -O2 的基础上再打开一些优化选项:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 。 |
-Os |
对生成文件大小进行优化。它会打开 -O2 开的全部选项,除了会那些增加文件大小的。 |
-finline-functions |
把所有简单的函数内联进调用者。编译器会探索式地决定哪些函数足够简单,值得做这种内联。 |
-fstrict-aliasing |
施加最强的别名规则(aliasing rules)。 |
Standard |
|
-ansi |
支持符合ANSI标准的C程序。这样就会关闭GNU C中某些不兼容ANSI C的特性。 |
-std=c89 |
指明使用标准 ISO C90 作为标准来编译程序。 |
-std=c99 |
指明使用标准 ISO C99 作为标准来编译程序。 |
-std=c++98 |
指明使用标准 C++98 作为标准来编译程序。 |
-std=gnu9x |
使用 ISO C99 再加上 GNU 的一些扩展。 |
-fno-asm |
不把asm, inline或typeof当作关键字,因此这些词可以用做标识符。用 __asm__, __inline__和__typeof__能够替代它们。 `-ansi' 隐含声明了`-fno-asm'。 |
-fgnu89-inline |
告诉编译器在 C99 模式下看到 inline 函数时使用传统的 GNU 句法。 |
C options |
|
-fsigned-char |
把char定义为有/无符号类型,如同signed char/unsigned char。 |
-traditional |
尝试支持传统C编译器的某些方面。详见GNU C手册。 |
-fno-builtin |
不接受没有 __builtin_ 前缀的函数作为内建函数。 |
-trigraphs |
支持ANSI C的三联符( trigraphs)。`-ansi'选项隐含声明了此选项。 |
-fsigned-bitfields |
如果没有明确声明`signed'或`unsigned'修饰符,这些选项用来定义有符号位域或无符号位域。缺省情况下,位域是有符号的,因为它们继承的基本整数类型,如int,是有符号数。 |
-Wstrict-prototypes |
如果函数的声明或定义没有指出参数类型,编译器就发出警告。很有用的警告。 |
-Wmissing-prototypes |
如果没有预先声明就定义了全局函数,编译器就发出警告。即使函数定义自身提供了函数原形也会产生这个警告。这个选项 的目的是检查没有在头文件中声明的全局函数。 |
-Wnested-externs |
如果某extern声明出现在函数内部,编译器就发出警告。 |
C++ options |
|
-ffor-scope |
从头开始执行程序,也允许进行重定向。 |
-fno-rtti |
关闭对 dynamic_cast 和 typeid 的支持。如果你不需要这些功能,关闭它会节省一些空间。 |
-Wctor-dtor-privacy |
当一个类没有用时给出警告。因为构造函数和析构函数会被当作私有的。 |
-Wnon-virtual-dtor |
当一个类有多态性,而又没有虚析构函数时,发出警告。-Wall会开启这个选项。 |
-Wreorder |
如果代码中的成员变量的初始化顺序和它们实际执行时初始化顺序不一致,给出警告。 |
-Wno-deprecated |
使用过时的特性时不要给出警告。 |
-Woverloaded-virtual |
如果函数的声明隐藏住了基类的虚函数,就给出警告。 |
Machine Dependent Options (Intel) |
|
-mtune=cpu-type |
为指定类型的 CPU 生成代码。cpu-type可以是:i386,i486,i586,pentium,i686,pentium4 等等。 |
-msse |
使用或者不使用MMX,SSE,SSE2指令。 |
-m32 |
生成32位/64位机器上的代码。 |
-mpush-args |
(不)使用 push 指令来进行存储参数。默认是使用。 |
-mregparm=num |
当传递整数参数时,控制所使用寄存器的个数。 |
默认情况下,GCC/G++链接时优先链接动态库,如果没有动态库,则链接相应的静态库。同时,GCC/G++也提供了链接选项 -Wl,-Bstatic 和 -Wl,-Bdynamic 供用户指定链接动态库或者静态库。
-Wl,-Bstatic指示跟在后面的-lxxx选项链接的都是静态库,-Wl,-Bdynamic指示跟在后面的-lxxx选项链接的都是动态库。
如下,
g++ -L. -o main main.cc -Wl,-Bstatic -ltest -Wl,-Bdynamic
前面的 -Wl,-Bstatic指示链接libtest.a静态库,后面的 -Wl,-Bdynamic指示链接系统动态库。
-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
l -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
l -L.:表示要连接的库在当前目录中
l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
l LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
l 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。