[置顶] gcc使用总结

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)。


# cc -o XX XX.c


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

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

你可能感兴趣的:([置顶] gcc使用总结)