gcc 的使用

一、GCC

GCC 编译器是 Linux 下默认的 C/C++ 编译器,大部分 Linux 发行版中都是默认安装的。GCC 编译器通常以 Linux 命令的形式在终端(Shell)中使用,它有很多选项,这是我们要重点学习的。

1.1 gcc的编译过程

  • 预处理(pre-processing)E:插入头文件,替换宏
  • 编译(Compiling)S:编译成汇编
  • 汇编(Assembling) c:编译成目标文件
  • 链接 (Linking):链接到库中,变成可执行文件

生成可执行文件

gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o

#链接,生成可执行文件
gcc hello.s -o hello 

# 运行
/hello 

一次性生成可执行文件

# 也可以一次性完成
# 但一般情况下生成.o文件比较好,可以重定位文件,让别人使用
gcc hello.c -o hello

1.2 gcc常用选项

选项描述
-o生成目标
-c取消链接步骤,编译源码并最后生成目标文件
-E只运行C预编译器(头文件,宏等展开)
-S生成汇编语言文件后停止编译(.s文件)
-Wall打开编译告警(所有)
-g嵌入调试信息,方便gdb调试
-l<lib>指定程序要链接的库(这里是小写 L )
如果gcc编译选项中加入了“-static”表示寻找静态库文件
-L<Dir>指定-l(小写-L)所使用到的库文件所在的目录名,【增加 lib 目录 (静态库和动态库)】
-I<dir>增加 include 目录 (这里是大写 i ) 头文件路径
-D<define>预定义宏
-O优化参数,一般用-O2就是,用来优化程序用的,比如gcc test.c -O2,优化得到的程序比没优化的要小,执行速度可能也有所提
-shared指定命令编译动态库
-fPIC作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code);这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

1.3 多模块编译

一次性编译:

gcc -Wall fun.c main_fun.c -o main_fun

独立编译:

gcc -Wall –c main_fun.c -o main_fun.o
gcc -Wall -c fun.c -o fun.o
gcc -Wall main_fun.o fun.o -o main_fun

多模块编译中如果某一个模块发生了变化,只需要编译更改的模块即可

1.4 静态库(.a)

程序在编译链接时候把库的代码链接到可执行文件中。程序运行时候,不再需要静态库,生成的可执行文件大,每个可执行文件都会加载一份拷贝到内存。

静态库生成(libxxx.a)

# 首先生成.o文件,然后通过.o文件生成.a文件
gcc -c fun.c
ar rcs libfun.a fun.o

静态库使用

gcc -Wall main.c libfun.a -o main
# -L.表示在当前目录搜索 libfun.a
gcc -Wall -L. main.c -o main -lfun

静态库搜索路径

  • 1:编译使用选项 -L 指定的目录(建议)
  • 2:修改环境变量,搜索指定的目录 设置环境变量 LIBRARY_PATH
    export LIBRARY_PATH=“库目录”
  • 3:lib文件放入系统指定目录,例如/usr/lib/等

1.5 共享库(.so或.sa)

程序运行时候才去链接共享库代码,多个程序共享使用,使用时候只需要加载一份到内存

1)共享库生成

gcc -shared -fPIC fun.c -o libFun.so
  • shared:生成共享库格式
  • fPIC: 产生位置无关码,允许在任何地址加载 (否则只能从指定地址加载,无法控制)相对地址

2)共享库使用

gcc –Wall main.o –o main –L. -lFun

只需要-l+文件名即可
配置方式

  • 1:拷贝到so文件到共享库目录 /usr/lib/
  • 2:更改 LD_LIBRARY_PATH,如果已经有了一个这样的目录,要写成export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:“库目录”这样子。如果写在profile配置文件里 export LD_LIBRARY_PA TH="目录:$LD_LIBRARY_PATH"
  • 3:配置 /etc/ld.so.conf; 并使用 ldconfig命令进行更新

二、参数详解

2.1 gcc -l

-l 参数就是用来指定程序要链接的库,-l 参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说他的库名是 m,他的库文件名是libm.so,很容易看出,把库文件名的头 lib 和尾 .so去掉就是库名了。好了现在我们知道怎么得库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把 libtest.so拷贝到/usr/lib里,编译时加上-ltest 数,我们就能用上 libtest.so 库了(当然要用libtest.so 库里的函数,我们还需要与libtest.so 配套的头文件)。

2.2 gcc -L

放在 /lib/usr/lib/usr/local/lib 里的库直接用 -l 参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序 ld 在那3个目录里找不到libxxx.so。这时另外一个参数-L 就派上用场了,比如常用的 X11的库,它在 /usr/X11R6/lib目录下,我们编译时就要用 -L/usr/X11R6/lib -lX11 参数,-L 参数跟着的是库文件所在的目录名。再比如我们把libtest.so 放在 /aaa/bbb/ccc目录下,那链接参数就是 -L/aaa/bbb/ccc -ltest

2.3 gcc -I

-I参数是用来指定头文件目录,/usr/include目录一般是不用指定的,gcc知道去那里找,但是如果头文件不在/usr/include 里我们就要用-I参数指定了,比如头文件放在/myinclude目录里,那编译命令行就要加上 -I/myinclude参数了,如果不加你会得到一个"xxxx.h: No such file or directory"的错误。-I参数可以用相对路径,比如头文件在当前目录,可以用-I. 来指定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书香水墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值