gcc用法以及静态/动态链接

安装

yum install gcc gcc-c++

选项

-E:只进行预处理,不编译
-S:只编译,不汇编
-c:只编译、汇编,不链接
-g:编译器在编译的时候产生调试信息。
-I:指定include包含文件的搜索目录
-o:输出成指定文件名,如果缺省则输出位a.out
-L:搜索库的路径
-l:指定程序要链接的库
-w:忽略所有警告
-shared:指定生成动态链接库。
-static:指定生成静态链接库。
-fPIC:表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码,概念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。

-l参数和-L参数

  • -l参数就是用来指定程序要链接的库,-l参数紧接着就是库名。那么库名跟真正的库文件名有什么关系呢?
    就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。好了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)。
    放在/lib/usr/lib/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了。

  • -L 比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest。 gcc默认会在程序当前目录、/lib/usr/lib/usr/local/lib下找对应的库

-I参数

  • -include和-I参数

    在你是用#include '***.h'的时候,gcc/g++会先在当前目录查找你所制定的头文件,如果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他回先在你所制定的目录查找,然后再按常规的顺序去找.对于#include,gcc/g++会到-I制定的目录查找,查未找到,然后将到系统的缺省的头文件目录查找。
    #include有两种方式

  • 使用<>包含的头文件一般会先搜索-I选项后的路径(即用gcc编译时的-I选项),之后就是标准的系统头文件路径。

  • 而用""号包含的头文件会首先搜索当前的工作目录,之后的搜索路径才是和<>号包含的头文件所搜索的路径一样的路径。

Linux下的标准头文件路径为/usr/include/usr/local/include

2.png
1.png

.a 和.so

静态函数库

静态函数库,这类库的名字一般是libxxx.a
利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中。
优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为缺点如果静态函数库改变了,那么你的程序必须重新编译。

共享函数库

这类库的名字一般是libxxx.so
相对于静态函数库,共享函数库在编译的时候 并没有被编译进目标代码中。当程序执行到相关函数时才调用共享函数库里相应的函数,因此共享函数库所产生的可执行文件比较小。
由于共享函数库没有被整合进你的程序,而是在程序运行时动态地申请并调用,所以程序的运行环境中必须提供相应的库.
共享函数库的改变并不影响你的程序,所以共享函数库的升级比较方便.

示例

先上头文件hello.h

#ifndef HELLO_H
#define  HELLO_H
void show();
#endif

分别做两个实现,hello_static.cpp和hello_dynamic.cpp。代码很简单就是打印一句话做一个区分,方便我们后面测试链接的哪个库。
hello_static.cpp

#include "hello.h"
#include <iostream>
using namespace std;
void show(){
  cout<<"hello static"<<endl;
}

hello_dynamic.cpp

#include "hello.h"
#include <iostream>
using namespace std;
void show(){
  cout<<"hello dynamic"<<endl;
}

测试主程序main.cpp

#include "hello.h"
int main(){
  show();
  return 0;
}

下面我们写Makefile然后进行编译:

all : hello_static.o libhello.a libhello.so  main_s main_d

hello_static.o : hello_static.cpp
    g++ -c hello_static.cpp
    
libhello.a : hello_static.o
    ar crs libhello.a hello_static.o

libhello.so : hello_dynamic.cpp
    g++ -o $@ $+  -fPIC -shared

main_s : main.cpp
    g++  -static -o $@ $+ -I. -lhello -L.

main_d : main.cpp
    g++ -o $@ $+ -I. -lhello -L.

.PHONY : clean
clean :
    -rm hello_static.o libhello.a libhello.so main_s main_d

在链接hello时,会以共享库文件优先. 如果同时存在静态库和共享库,可以使用-static强制使用静态库。当然也可以直接指定libhello.a。如:

g++ -o $@ $+ -I.  -L.  libhello.a

完成Makefile后,就可以进行编译,执行make命令,生成hello_static.olibhello.alibhello.somain_smain_d等文件。而main_s是我们静态链接生成的,main_d是动态链接。我们分别运行后:

[root@localhost gcc]# ./main_d 
hello dynamic
[root@localhost gcc]# ./main_s
hello static

与我们预期一致。

问题

静态链接使用-static出现错误:
/usr/bin/ld: cannot find -lm
collect2: ld 返回 1
make: *** [main_s] 错误 1

安装glibc-devel即可

找不到动态库
./main_d: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

这里是需要设置环境变量,可参考Linux环境变量介绍和区别。也就是我们需要将so文件设置到环境变量中。直接编辑.bashrc文件

vim ~/.bashrc

添加:

export LD_LIBRARY_PATH=/code/gcc

保存退出后,使其生效。

source ~/.bashrc
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容