1.基本选项
-o 指定输出文件名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
# cc -o XX XX.c
-c
编译、汇编到目标代码,不进行链接
-v
打印较多信息,显示编译器调用的程序。
-E
仅作预处理,不进行编译、汇编和链接。
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面. 例子用法: gcc -E hello.c > pianoapan.txt gcc -E hello.c | more 慢慢看吧,一个hello word 也要与处理成800行的代码
-E选项,表示让gcc只进行“预处理”就行了。 所谓的预处理,就是把程序中的宏展开, 把头文件的内容展开包含进来等等一些编译前的预处理操作。预处理结果会显示到屏幕上,如果需要保存,则得需要重定向
-m32
-m64
生成32位/64位机器上的代码。
2.gcc选项--调试
-g,生成调试信息。
# cc -g -o XX XX.c
-ggdb
-ggdblevel
为调试器 gdb 生成调试信息。level 可以为1,2,3,默认值为2。
-g
-glevel
生成操作系统本地格式的调试信息。-g 和 -ggdb 并不太相同, -g 会生成 gdb 之外的信息。level 取值同上。
3.gcc选项--汇编
-S 仅编译到汇编语言,不进行汇编和链接。
# cc -S XX.c
4.gcc优化
-O0
禁止编译器进行优化。默认为此项。
-O
-O1
尝试优化编译时间和可执行文件大小。
-O2
更多的优化,会尝试几乎全部的优化功能,但不会进行“空间换时间”的优化方法。
-O3
在 -O2 的基础上再打开一些优化选项:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 。
-Os
对生成文件大小进行优化。它会打开 -O2 开的全部选项,除了会那些增加文件大小的。
-finline-functions
把所有简单的函数内联进调用者。编译器会探索式地决定哪些函数足够简单,值得做这种内联。
-fstrict-aliasing
施加最强的别名规则(aliasing rules)。
5.gcc选项-Wall
-W是打开警告选项
-all打开所有
# cc -g -Wall -o XX XX.c
-Wall
会打开一些很有用的警告选项,建议编译时加此选项。
-W
-Wextra
打印一些额外的警告信息。
-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
如果在同一个可见域内某定义多次声明,编译器就发出警告,即使这些重复声明有效并且毫无差别。
6.多个程序文件的编译
通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有一个由test1.c和 test2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序test,可以使用下面这条命令:
# cc test1.c test2.c -o test
如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:
# cc -c test1.c -o test1.o
# cc -c test2.c -o test2.o
# cc test1.o test2.o -o test
7.gcc链接外部库--I和L选项
-l library (仅对标准库)
进行链接时搜索名为library的库, -lm相当于libm.a。
例子: $ gcc test.c -lm -o test
-Idir
把dir 加入到搜索头文件的路径列表中。
例子: $ gcc test.c -I../inc -o test
-Ldir
把dir 加入到搜索库文件的路径列表中。
例子: $ gcc -I/home/foo -L/home/foo -ltest test.c -o test
8.线程库
由于pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-lpthread参数:
# gcc thread1.c -o thread1 -lpthread9.gcc选项--fpic
-fpic:产生位置无关码
解释一下,位置无关码就是可以在进程的任意内存位置执行的目标码,动态链接库必须使用。
如果使用Makefile构建,一般要给CFLAGS中指定CFLAGS=-fPIC
10.gcc选项--共享
-shared
生成共享目标文件。通常用在建立共享库时。
-static
禁止使用共享连接。
11.使用Makefile构建
一般要给CFLAGS中指定-g
CFLAGS= -Wall -o2 -g
如果用configure脚本生成Makefile
#./configure CFLAGS= "-Wall -02 -g"
调试
#./configure CFLAGS= "-0 -g"
12.查看gcc版本
查看glibc版本
# rpm -qa | grep glibc
glibc-2.12-1.80.el6_3.6.x86_64
glibc-headers-2.12-1.80.el6_3.6.x86_64
glibc-devel-2.12-1.80.el6_3.6.x86_64
glibc-common-2.12-1.80.el6_3.6.x86_64
或者# ldd --version
ldd (GNU libc) 2.12
查看gcc版本
# rpm -qa | grep gcc
gcc-gfortran-4.4.6-4.el6.x86_64
gcc-4.4.6-4.el6.x86_64
gcc-c++-4.4.6-4.el6.x86_64
libgcc-4.4.6-4.el6.x86_64
gcc-java-4.4.6-4.el6.x86_64
或者# gcc -v
使用内建 specs。
目标:x86_64-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
线程模型:posix
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
# man gcc
GCC编译器的调用参数大约有100多个,其中多数参数我们可能根本就用不到
GCC设定include和库路径
一、头文件
gcc 在编译时寻找所需要的头文件 :
※搜寻会从-I开始
※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH (这些变量在windows下对应的是include环境变量)
※再找内定目录
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include
库文件但是如果装gcc的时候,是有给定的prefix的话,那么就是
/usr/include
prefix/include
prefix/xxx-xxx-xxx-gnulibc/include
prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include
二、库文件
编译的时候:
※gcc会去找-L
※再找gcc的环境变量LIBRARY_PATH
※再找内定目录 /lib:/usr/lib: /usr/local/lib:这是当初compile gcc时写在程序内的
三、运行时动态库的搜索路径
1、在配置文件/etc/ld.so.conf中指定动态库搜索路径
2、通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)(HP- UX对应的是SHLIB_PATH环境变量,AIX对应的是LIBPATH环境变量,windows对应的是lib环境变量)
3、在编译目标代码时指定该程序的动态库搜索路径(还可以在编译目标代码时指定程序的动态库搜索路径。
这是通过gcc 的参数"-Wl,-rpath,"指定。当指定多个动态库搜索路径时,路径之间用冒号":"分隔
4、默认的动态库搜索路径/lib /usr/lib
可以通过执行可执行文件pos得到的结果不同获知其搜索到了哪个动态库,从而获得第1个动态库搜索顺序,然后删除该动态库,
再执行程序pos,获得第2个动态库搜索路径,再删除第2个被搜索到的动态库,
如此往复,将可得到Linux搜索动态库的先后顺序。
程序pos执行的输出结果和搜索到的动态库的对应关系如表1所示
程序pos输出结果 使用的动态库 对应的动态库搜索路径指定方式
./ ./libpos.so 编译目标代码时指定的动态库搜索路径
/root/test/env/lib /root/test/env/lib/libpos.so 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的动态库搜索路径
/lib /lib/libpos.so 默认的动态库搜索路径/lib
/usr/lib /usr/lib/libpos.so 默认的动态库搜索路径/usr/lib
动态库的搜索路径搜索的先后顺序是:
1.编译目标代码时指定的动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.默认的动态库搜索路径/lib /usr/lib。
// using –Wl,--rpath
#gcc main.c -ldl -Wl,—rpath=/home/username/usr/lib