一. 库的分类

  1.1. 静态库(.a)

    1.1.1. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。

  1.2. 动态库(.so)

    1.2.1. 动态库又名共享库。

    1.2.2. 动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。所以,即使程序编译完,库仍须保留在系统上,以供程序运行时调用

  1.3. 两种区别

    1.3.1. 静态库和动态库的最大区别,静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。

    1.3.2. 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库

    1.3.3. 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在

二. GCC编译选项

  2.1. GCC编译流程

    a. 预处理 Pre-Processing
    b. 编译 Compiling
    c. 汇编 Assembling
    d. 链接 Linking

2.2. gcc总体选项列表

    2.2.1. -E :只进行预编译/预处理,不做其他处理。

    2.2.2. -S :只编译,不汇编,生成汇编代码“.S”。

    2.2.3. -c :只编译,不链接,生成目标文件“.o”。

    2.2.4. -o file:把输出文件输出到file里。

    2.2.5. -g :在可执行程序中包含标准调试信息。

    2.2.6. -v :打印出编译器内部编译各过程的命令行信息和编译器的版本。

    2.2.7. -I dir :在头文件的搜索路径列表中添加dir目录

    2.2.8. -L dir :在库文件的搜索路径列表中添加dir目录

    2.2.9. -static :连接静态库(静态库也可以用动态库链接方式链接)

    2.2.10.  -llibrary :连接名为library的库文件(显示指定需要链接的动态库文件)

  2.3. gcc告警和出错选项    

    1) -ansi :支持符合ANSI标准的C程序
    2) -pedantic :允许发出ANSI C标准所列出的全部警告信息
    3) -pedantic-error :允许发出ANSI C标准所列出的全部错误信息
    4) -w :关闭所有警告
    5) -Wall :允许发出gcc提供的所有有用的报警信息
    6) -werror :把所有的告警信息转化为错误信息,并在告警发生时终止编译过程  

  2.4. gcc优化选项    

    gcc可以对代码进行优化,它通过编译选项“-On”来控制优化代码的生成,其中n是一个代表优化级别的整数。对于不同版本的gcc,n的取值范围不一致,比较典型的范围为0变化到2或者3。虽然优化选项可以加速代码的运行速度,但对于调试而言将是一个很大的挑战。因为代码在经过优化之后,原先在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句也可能因为循环展开而变得到处都有。

三、GCC生成动态库和静态库

  3.1. 生成动态库

    3.1.1. 单个源文件/目标直接生成动态库    

a.
gcc -fPIC -shared xxx.c -o libxxx.so
b.
gcc -fPIC -shared xxx.o -o libxxx.so

    3.1.2. 多个源文件/目标生成动态库

a.
gcc -fPIC -shared xxx1.c xxx2.c xxx3.c -o libxxx.so
b.
gcc -fPIC -shared xxx1.o xxx2.o xxx3.o -o libxxx.so

  3.2. 生成静态库

    3.2.1. 单个源文件/目标直接生成静态库

a.
ar -rc libxxx.a xxx.o(正确方法)
b. ar -rc libxxx.a xxx.c (静态库可以生成;当运行连接了该静态库的可执行程序会报错:could not read symbols:Archive has no index;run ranlib
to add one)

    3.2.2. 多个源文件/目标生成静态库

a.
ar -rc libxxx.a xxx1.o xxx2.o xxx3.o (正确方法)
b.
ar -rc libxxx.a xxx1.c xxx2.c xxx3.c (静态库可以生成;当运行连接了该静态库的可执行程序会报错:could not read symbols:Archive has no index;run ranlib to add one)

四. 实例

  4.1. 动态链接库

    a. 创建hello.so动态库

#include <stdio.h>
void hello(){
printf("hello world\n");
}
编译:gcc -fPIC -shared hello.c -o libhello.so

    b. hello.h头文件

void hello();  

    c. 链接动态库

      PS:这里-L的选项是指定编译器在搜索动态库时搜索的路径,告诉编译器hello库的位置。"."意思是当前路径.

#include <stdio.h>
#include "hello.h" int main(){
printf("call hello()");
hello();
}
编译:gcc main.c -L. -lhello -o main

    d. 测试

      编译成够后执行./main,会提示:

In function `main':  

main.c:(.text+0x1d): undefined reference to `hello'
collect2: ld returned exit status

      这是因为在链接hello动态库时,编译器没有找到。

      解决方法:

        方法一:

sudo cp libhello.so /usr/lib/  

        方法二:一般来讲这只是一种临时的解决方案, 在没有权限或临时需要的时候使用,换个终端环境变量就不在了

export LD_LIBRARY_PATH=.:$export LD_LIBRARY_PATH
./main

        方法三:

LD_LIBRARY_PATH=. ./main

  4.2. 静态库实例

    4.2.1. 文件有:main.c、hello.c、hello.h

    4.2.2. 编译静态库hello.o:

gcc hello.c -o hello.o  #这里没有使用-shared  

    4.2.3. 生成目标文件

      PS:程序ar配合参数-r创建一个新库libhello.a,并将命令行中列出的文件打包入其中。这种方法,如果libhello.a已经存在,将会覆盖现在文件,否则将新创建。

ar -r libhello.a hello.o

    4.2.4. 链接静态库

gcc main.c -lhello -L. -static -o main  

      这里的-static选项是告诉编译器,hello是静态库。
    或者:

gcc main.c libhello.a -L. -o main  

  4.3. makefile实例

    4.3.1. 生成静态库 

# 、准备工作,编译方式、目标文件名、依赖库路径的定义。
CC = g++
CFLAGS := -Wall -O3 -std=c++0x # opencv 头文件和lib路径
OPENCV_INC_ROOT = /usr/local/include/opencv
OPENCV_LIB_ROOT = /usr/local/lib OBJS = GenDll.o #.o文件与.cpp文件同名
LIB = libgendll.a # 目标文件名 OPENCV_INC= -I $(OPENCV_INC_ROOT) INCLUDE_PATH = $(OPENCV_INC) LIB_PATH = -L $(OPENCV_LIB_ROOT) # 依赖的lib名称
OPENCV_LIB = -lopencv_objdetect -lopencv_core -lopencv_highgui -lopencv_imgproc all : $(LIB) # . 生成.o文件
%.o : %.cpp
$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH) $(LIB_PATH) $(OPENCV_LIB) # . 生成静态库文件
$(LIB) : $(OBJS)
rm -f $@
ar cr $@ $(OBJS)
rm -f $(OBJS) tags :
ctags -R * # . 删除中间过程生成的文件
clean:
rm -f $(OBJS) $(TARGET) $(LIB)

    4.3.2. 生成动态库

      PS:第1、4步准备和收尾工作与静态库的保持一致,第2步和第3步所使用的命令稍有不同。

# 、准备工作,编译方式、目标文件名、依赖库路径的定义。
CC = g++
CFLAGS := -Wall -O3 -std=c++0x # opencv 头文件和lib路径
OPENCV_INC_ROOT = /usr/local/include/opencv
OPENCV_LIB_ROOT = /usr/local/lib OBJS = GenDll.o #.o文件与.cpp文件同名
LIB = libgendll.so # 目标文件名 OPENCV_INC= -I $(OPENCV_INC_ROOT) INCLUDE_PATH = $(OPENCV_INC) LIB_PATH = -L $(OPENCV_LIB_ROOT) # 依赖的lib名称
OPENCV_LIB = -lopencv_objdetect -lopencv_core -lopencv_highgui -lopencv_imgproc all : $(LIB) # . 生成.o文件
%.o : %.cpp
$(CC) $(CFLAGS) -fpic -c $< -o $@ $(INCLUDE_PATH) $(LIB_PATH) $(OPENCV_LIB) # . 生成动态库文件
$(LIB) : $(OBJS)
rm -f $@
g++ -shared -o $@ $(OBJS)
rm -f $(OBJS) tags :
ctags -R * # . 删除中间过程生成的文件
clean:
rm -f $(OBJS) $(TARGET) $(LIB)

    4.3.3. 动态/静态库调用

CC = g++
CFLAGS := -Wall -O3 -std=c++0x OPENCV_INC_ROOT = /usr/local/include/opencv
OPENCV_LIB_ROOT = /usr/local/lib
MY_ROOT = ../ OPENCV_INC= -I $(OPENCV_INC_ROOT)
MY_INC = -I $(MY_ROOT) EXT_INC = $(OPENCV_INC) $(MY_INC) OPENCV_LIB_PATH = -L $(OPENCV_LIB_ROOT)
MY_LIB_PATH = -L $(MY_ROOT) EXT_LIB = $(OPENCV_LIB_PATH) $(MY_LIB_PATH) OPENCV_LIB_NAME = -lopencv_objdetect -lopencv_highgui -lopencv_imgproc -lopencv_core
MY_LIB_NAME = -lgendll all:test test:main.cpp
$(CC) $(CFLAGS) main.cpp $(EXT_INC) $(EXT_LIB) $(MY_LIB_NAME) $(OPENCV_LIB_NAME) -o test

    PS:在测试过程中,经常会报错:找不到.so文件。一种简单的解决方法如下: 
在linux终端输入如下命令:

export LD_LIBRARY_PATH=/home/shaoxiaohu/lib:LD_LIBRARY_PATH:

参考文献:http://www.cnblogs.com/fnlingnzb-learner/p/8059251.html

参考文献:https://cloud.tencent.com/developer/article/1344879

gcc编译工具生成动态库和静态库的更多相关文章

  1. gcc编译工具生成动态库和静态库之一----介绍

     1.库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. ...

  2. GCC 指令详解及动态库、静态库的使用

    GCC 指令详解及动态库.静态库的使用 一.GCC 1.1 GCC 介绍 GCC 是 Linux 下的编译工具集,是「GNU Compiler Collection」的缩写,包含 gcc.g++ 等编 ...

  3. 如何使用GCC生成动态库和静态库

    根据链接时期的不同,库又有静态库和动态库之分.静态库是在链接阶段被链接的,所以生成的可执行文件就不受库的影响,即使库被删除,程序依然可以成功运行.而动态库是在程序执行的时候被链接的.程序执行完,库仍需 ...

  4. gcc 编译动态库和静态库

    Linux C 编程入门之一:gcc 编译动态库和静态库 cheungmine 2012 参考: C程序编译过程浅析 http://blog.csdn.net/koudaidai/article/de ...

  5. 【C++】如何使用GCC生成动态库和静态库

    一.静态库和动态库的定义及区别 程序编译的四个过程: 1.预处理  展开头文件/宏替换/去掉注释/条件编译(.i后缀) 2.编译    检查语法,生成汇编(.s后缀) 3.汇编    汇编代码转换成机 ...

  6. 动态库与静态库的学习 博主写的很好 静态库 编译的时候 需要加上 static 动态库编译ok运行不成功就按照文章中的方法修改

    来源连接   http://www.cnblogs.com/skynet/p/3372855.html C++静态库与动态库 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库 ...

  7. Linux下动态库和静态库的生成和使用

    1.准备头文件和源文件 hello.h #ifndef HELLO_H #define HELLO_H void hello(const char *name): #endif hello.c #in ...

  8. Linux环境编译动态库和静态库总结

    对Linux环境动态库和静态库的一些基础知识做一些总结, 首先总结静态库的编译步骤. 1 先基于.cpp或者.c文件生成对应的.o文件 2将几个.o文件 使用ar -cr命令 生成libname.a文 ...

  9. 自己在linux上编译、链接、动态库和静态库的学习笔记

    在平常的项目中,我们都是使用公司要求的makefile.makedebug一类的文件,因此,在编译.链接.生成和链接动态库与静态库的时候,我们只是简单的使用一些已经设置的变量,只是简单的修改.添加一些 ...

随机推荐

  1. Codeforces Gym 101505C : Cable Connection (计算几何)

    题目链接 题意:给出第一象限的N个点,存在一直线x/a+y/b=1(a>0,y>0)使得所有点都在这条直线下面,求 min{sqrt(a^2+b^2)} 显然,这样的直线必然经过这N个点中 ...

  2. Golang入门及开发环境配置

    Go语言诞生背景 计算机硬件更新频繁,主流编程语言无法发挥多核多CPU的性能 软件系统复杂度不断变高,缺乏简洁高效的编程语言 C/C++运行速度快,但编译速度慢 Go语言特点 静态类型开发语言 静态: ...

  3. logstash之Filter插件

    Logstash之所以强悍的主要原因是filter插件:通过过滤器的各种组合可以得到我们想要的结构化数据 1:grok正则表达式 grok**正则表达式是logstash非常重要的一个环节**:可以通 ...

  4. sqli-labs(18)

    开始挑战第十八关(Header Injection - Uagent field - Error based) 常见的HTTP注入点产生位置为[Referer].[X-Forwarded-For].[ ...

  5. 如何用CSS3画出懂你的3D魔方?

    作者:首席填坑官∙苏南公众号:honeyBadger8,群:912594095,本文原创,著作权归作者所有,转载请注明原链接及出处. 前言 最近在写<每周动画点点系列>文章,上一期分享了& ...

  6. VASP学习笔记--输入输出文件

    一.VASP 全称Vienna Ab-initio Simulation Package,是维也纳大学Hafner小组开发的进行电子结构计算和量子力学-分子动力学模拟软件包. 它是目前材料模拟和计算物 ...

  7. WPF DevExpress Chart控件多Y轴,指定数据参考的Y轴

    当Chart中有两个及以上的Y轴时,我们就要指明图表中的柱子或折线对应的是哪个Y轴了,这时候需要指明柱子或者折线的dxc:XYDiagram2D.SeriesAxisY属性,来设置对应的Y轴(dxc: ...

  8. Delphi XE2 之 FireMonkey 入门(40) - 控件基础: TMemo

    Delphi XE2 之 FireMonkey 入门(40) - 控件基础: TMemo 值得注意的变化: 1.其父类 TScrollBox 的许多特性也很有用处, 如:   Memo1.UseSma ...

  9. MYSQL启用数据库错误:ERROR 2002 (HY000)

    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) MYSQL服务 ...

  10. CSS样式div

    页面中,有很多样式标签:div标签,对标签定位的地方有: 1.<head>标签里加<style>标签,在<style>标签中添加样式.如: <style> ...