开发一个应用程序不可避免要使用多个第三方库(library).
默认情况下,gcc采用动态连接的方式连接第三方库,比如指定-lpng,连接程序就会去找libpng.so。

gcc提供了一个-static参数,可以改变gcc默认的连接方式,GNU官网上关于gcc连接选项的手册《3.14 Options for Linking》中有说明:如下

这个-static选项是个大杀器,指定了这个选项,gcc在连接时对项目所有的依赖库都尝试去搜索名为lib<name>.a的静态库文件,完成静态连接,如果找不到就报错了。这里指的所有是不仅指我们常用的第三方库比如jpeg,png,opencv,zlib,...,还包括gcc编译器自带的库libgcc,libstdc++,libc,libm...,总之就是linux kernal之外的所有库。而且还要包括所有被间接引用的第三方库,比如png这个库在编译时还用到了zlib,那么静态连接png的时候,就要带上zlib的库:-lpng -lz,

这可麻烦大了,要把这些东西全静态连接,这得有多大?呵呵,这事儿我干过,十几兆字节总是有的,取决你的程序用到多少第三方库。
这种全静态连接有啥用处呢?也有用,就是你的程序自带干粮,只需要一个linux kernal就能跑了。

但是实际应用中,我们绝大多数应用场景不需要这么做,即使在嵌入式系统中也不一定必要,尤其是嵌入式系统的存储容量受限,这么一只大象装都装不下。所以我们大多数情况下需要有选择的进行静态编译,-static并不适合。

如何有选择的进行静态编译呢?
最简单的方式直接在连接参数中以全路径指定连接库就好了: your/path/lib<name>.a
但这种形式对管理结构简单而且自己写Makefile的小型项目还好,当一个项目结构复杂,有时需要静态连接有时需要动态连接,这种频繁的修改编译脚本的方式,可维护性就太差了。

-Bstatic
gnu的连接程序ld提供了一个-Bstatic选项用于对指定的库静态连接,ld的官方手册《2.1 Command Line Options》有说明,如下:

大意就是-Bstatic参数指定对跟在它后面的所有库执行静态连接,如下就指定LDFLAGS对png这个库静态连接,ld会自动去搜索libpng.a

-Bstatic -lpng -lz
1
-l:filename
如果你觉得上面一种静态连接方式不适合你,可以看看ld的官方手册《2.1 Command Line Options》中关于-l参数的说明,如下:

注意上面的说明中红框标注的内容,如果-l:filename格式指定一个文件名,连接程序直接去找这个文件名了,不会再像使用-lname时将name扩展成lib<name>.a格式的文件名.
所以使用 -l:libpng.a这样的形式来指定连接库,就指定了静态连接png库。
当然如果库的位置不在gcc默认搜索路径中,要用-L参数另外指定搜索库的路径,否则连接程序不知道该从哪里找到filename。

-L/your/library/path -l:libmylib.a
1
顺便贴出ld的官方手册《2.1 Command Line Options》中关于-L参数的说明

参考资料
以上内容只是我对最近做项目编译的一些总结和体会,可能会有所遗漏,权威资料还请参见gcc的官方文档
《3.14 Options for Linking》
《2.1 Command Line Options》
---------------------
作者:10km
来源:CSDN
原文:https://blog.csdn.net/10km/article/details/83239949
版权声明:本文为博主原创文章,转载请附上博文链接!

static link:关于gcc连接静态库的几种方式的更多相关文章

  1. GCC同时使用静态库和动态库链接

    一 在应用程序需要连接外部库的情况下,linux默认对库的连接是使用动态库,在找不到动态库的情况下再选择静态库.使用方式为: gcc test.cpp -L. -ltestlib 如果当前目录有两个库 ...

  2. linux连接静态库

    在项目中发现,使用 -l连接某个库时,如果存在同名的静态库(.a)和动态库(.so),默认会连接.so 那么如何指定连接静态库呢?如果有多个库,有些要连接静态库.有些要连接动态库,连接选项该如何指定呢 ...

  3. gcc创建静态库和共享库

    静态库和动态(共享)库静态库:编译程序在编译使用库提供的功能代码的程序时将代码复制到该程序然后编译成可执行程序,这种库成为静态库共享库:共享库比静态库的处理方式更加灵活,因而其产生的可执行文件更小,其 ...

  4. GCC与静态库、动态库

    GCC 常用指令 1 man gcc gcc工作流程例如: gcc hello.c 1234567891011121314 //***第一步***gcc -E hello.c >hello.i ...

  5. 不停止MySQL服务增加从库的两种方式

    不停止MySQL服务增加从库的两种方式 转载自:http://lizhenliang.blog.51cto.com/7876557/1669829 现在生产环境MySQL数据库是一主一从,由于业务量访 ...

  6. 不停止MySQL服务增加从库的两种方式【转载】

    现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...

  7. Spring静态注入的三种方式

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/chen1403876161/article/details/53644024Spring静态注入的三 ...

  8. 不停mysql服务添加从库的两种方式

    现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...

  9. 基于 Webpack 引入公共库的几种方式

    以 jquery 和其插件 jquery-modal 为例,记录下引入公共库的几种方式. 为了方便,首先安装 jquery 和 jquery-modal: cnpm i jquery jquery-m ...

随机推荐

  1. windows 下安装composer

    安装 1.在PHP目录下,打开php.ini文件,开启openssl扩展.去掉extension=php_openssl.dll前面的分号(;) 2.把php目录添加到环境变量(和php.exe同级目 ...

  2. 关于 transparent rgba display:none; opacity visiblity 关于em

    关于 transparent  rgba   display:none; opacity   visiblity   display 之后不会占位. 其余都会占位 opacity 还会继承,子元素也会 ...

  3. A Spy in the Metro(UVA 1025 ACM/ICPC World Finals2003)

    ---恢复内容开始--- 题意:有n(2<=n<=50)个车站,从左到右编号为1~n,有M1辆列车从第1站向右开,还有M2辆列车从第N站向左开.在时刻0,间谍从第1站出发,目的是在时刻T( ...

  4. c++——基本概念

    如何理解c/c++中的指针?每种编程语言都使用指针,但Java.c#等将指针隐藏,而c/c++将指针暴露给了用户(程序员)https://www.cnblogs.com/gxcdream/p/4805 ...

  5. 2017.5.11 Yarn

    Yarn在hadoop中的位置 Yarn的优点 YARN把JobTracker分为ResouceManager和ApplicationMaster,ResouceManager专管整个集群的资源管理和 ...

  6. django HttpResponse的用法

    一.传json字典 def back_json(rquest): #JsonResponse父类是HttpResponse,原码里调用了json.dumps() from django.http im ...

  7. Node学习笔记2:建立HTTP服务器和客户端之间的通信

    http服务器端: var http = require('http'); var server = http.createServer(); server.on('request', functio ...

  8. Xenserver之HA实现-NFS的实现

    环境: 在vm上安装好一台Xenserver服务器,一台centos7虚拟机(用来做NFS存储,因为实现HA需要共享存储),网络连接方式为桥接模式 echo '- - -'>> /sys/ ...

  9. Java数组逆序排列

    //逆序排列原理 /* A: 数组逆序原理* a: 题目分析* 通过观察发现,本题目要实现原数组元素倒序存放操作.即原数组存储元素为{12,69,852,25,89,588},逆序后为原数组存储元素变 ...

  10. scala学习笔记-面向对象编程之Trait

    将trait作为接口使用 1 // Scala中的Triat是一种特殊的概念 2 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 3 // 在triat中可 ...