个人博客首页(点解查看详情)-- https://blog.51cto.com/11495268
    

1、简介

    程序编译一般需要经预处理、编译、汇编和链接,在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为 "库" 文件,本文 主要 描述 Linux 平台下 库文件的 创建 和 链接 相关操作(既然都看 这么底层的内容了,相信 也有一定的基础,所以本文 对相关命令 也不会进行详细解释)
Linux g++ 链接库 编译、链接 以及 Makefile编写
    

备注:
    linux平台下,静态链接库是以 .a 的后缀文件,动态链接库是以 .so 的后缀文件
    widows平台下,静态链接库是以 .lib 的后缀文件,动态库文件是以 .dll 的后缀文件
    

2、库文件

    库是写好的 现有的、成熟的 一种可执行、可以复用代码的二进制形式(注,其本身不可执行),可以被操作系统载入内存执行;分为 静态链接库 和 动态链接库
    

2.1 静态库

2.1.1 简介

    静态链接库可以简单看成一组目标文件.o 的集合,即很多目标文件经过压缩打包后形成的一个文件
    

2.1.2 原理

    链接器将从 静态(链接)库 取得所需的代码,复制到生成的可执行文件
Linux g++ 链接库 编译、链接 以及 Makefile编写
    

2.1.3 特点

    静态库对函数库的链接是放在程序编译时期完成
    程序在运行时对函数库再无瓜葛(因为所有相关的目标文件和牵涉到的函数库被链接合成一个可执行文件)
    浪费空间和资源(因为所有相关的目标文件和牵涉到的函数库被链接合成一个可执行文件)
    

2.1.4 创建流程

Linux g++ 链接库 编译、链接 以及 Makefile编写
    

备注:
    linux下使用ar工具(windows下用lib.exe)将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和索引
    

2.1.5 命令规则

    静态链接库的名称 和 库文件名称不同但有联系;例如,库名称为"static_library",那么起库文件名为"libstatic_library.a"
    

2.2 动态库

2.2.1 简介

    程序在开始运行后调用 动态(链接)库(Dynamic Link Library)中的函数 才被载入
    

2.2.2 原理

    程序编译是并不会被连接到目标代码中,而是在程序运行时才被载入
Linux g++ 链接库 编译、链接 以及 Makefile编写
    

2.2.3 特点

    动态库把对一些库函数的链接载入推迟到程序运行时期
    进程之间的相同动态库实现共享
    

2.2.4 创建

    创建动态库与创建静态库不同,不需要打包工具,直接使用编译器创建动态库

# g++ -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp

    

2.2.5 命名规则

    动态链接库的名称 和 库文件名称不同但有联系;例如,库名称为"dynamic_library",那么起库文件名为"libdynamic_library.a"
    

3、库文件 编译、链接(实战操作)

3.1 静态库 编译、链接

3.1.1 静态库 源码

# cat g++_lib_header.h
#ifndef __GXX_LIB_HEADER_H_ 
#define __GXX_LIB_HEADER_H_

#include <iostream>

using namespace std;
void gxx_lib_one();
void gxx_lib_two();
void gxx_lib_three();

#endif

    

# cat g++_lib_first.cpp  
/* 
    filename : g++_lib_first.cpp 
*/
#include "g++_lib_header.h"

void gxx_lib_one(){
    cout << "call gxx_lib_one() function" << endl;
}

    

# cat g++_lib_sec.cpp
/* 
    filename : g++_lib_sec.cpp 
*/
#include "g++_lib_header.h"

void gxx_lib_two(){
    cout << "call gxx_lib_two() function" << endl;
}

    

# cat g++_lib_third.cpp
/* 
    filename : g++_lib_third.cpp 
*/
#include "g++_lib_header.h"

void gxx_lib_three(){
    cout << "call gxx_lib_three() function" << endl;
}

    

# cat g++_lib_main.cpp 
/* 
    filename : g++_lib_main.cpp 
*/
#include "g++_lib_header.h"

int main(int argc, char *argv[])
{
    gxx_lib_one();
    gxx_lib_two();
    gxx_lib_three();

    return 0;
}

    

3.1.2 静态库 编译

# g++ -c g++_lib_first.cpp
# g++ -c g++_lib_sec.cpp
# g++ -c g++_lib_third.cpp

# ar  cqs  libstatic_gxx.a  g++_lib_first.o g++_lib_sec.o g++_lib_third.o

    

3.1.3 静态库 链接

## -L ./ 等同于 -L.
# g++ -o g++_lib_main_static g++_lib_main.cpp -L. -static -l static_gxx

# ./g++_lib_main_static 
call gxx_lib_one() function
call gxx_lib_two() function
call gxx_lib_three() function

    

3.2 动态库 编译、链接

3.1.1 动态库 源码

    为了便于测试比较,使用 与 静态库编译相同的源码

3.1.2 动态库 编译

# g++ -fPIC -shared -o libdynamic_gxx.so  g++_lib_first.cpp g++_lib_sec.cpp g++_lib_third.cpp

    

3.1.3 动态库 链接

# g++ -o g++_lib_main_dynamic g++_lib_main.cpp -L ./ -l dynamic_gxx

    

3.1.4 共享路径设置(不详细解释)

## 共享路径设置 :
##     1@:LD_LIBRARY_PATH 修改 这个全局变量
##     2@:修改 /etc/ld.so.conf 配置
## 本文 就 详细描述了,直接把 生成的共享库 cp 至 系统默认路径下
# cp libdynamic_gxx.so /usr/local/lib/

    

备注:
    如果 不设置 共享路径 或者 共享路径下 找不到 指定的 库文件,系统 就会 提示相关的错误信息:"./g++_lib_main_dynamic: error while loading shared libraries: libdynamic_gxx.so: cannot open shared object file: Error 40"
    

3.1.5 执行

## 查看 依赖库,没有问题 就执行
# ldd g++_lib_main_dynamic 
    linux-vdso.so.1 =>  (0x00007ffcf73c1000)
    libdynamic_gxx.so => /usr/local/lib/libdynamic_gxx.so (0x00007effbb5d0000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007effbb24e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007effbae84000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007effbab7a000)
    /lib64/ld-linux-x86-64.so.2 (0x000056545a3cb000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007effba964000)

    

# ./g++_lib_main_dynamic 
call gxx_lib_one() function
call gxx_lib_two() function
call gxx_lib_three() function

    

4、自定义工具(Makefile)

4.1 安装 make

# apt-get install make

    

4.2 编写 Makefile

# cat Makef
default_target : help

help :
    @echo "usage : make [opt]"
    @echo "\topt arguement is one of \"static_gxx、dynamic_gxx\""

g++_lib_first.o : g++_lib_first.cpp g++_lib_header.h
    g++ -c g++_lib_first.cpp 

g++_lib_sec.o : g++_lib_sec.cpp g++_lib_header.h
    g++ -c g++_lib_sec.cpp 

g++_lib_third.o : g++_lib_third.cpp g++_lib_header.h
    g++ -c g++_lib_third.cpp 

static_gxx : g++_lib_first.o g++_lib_sec.o g++_lib_third.o
    ar  cqs  /tmp/libstatic_gxx.a  g++_lib_first.o g++_lib_sec.o g++_lib_third.o
    g++ -o g++_lib_main g++_lib_main.cpp -L /tmp -static -l static_gxx

dynamic_gxx :
    g++ -fPIC -shared -o /tmp/libdynamic_gxx.so  g++_lib_first.cpp g++_lib_sec.cpp g++_lib_third.cpp
    g++ -o g++_lib_main_dynamic g++_lib_main.cpp -L /tmp -l dynamic_gxx
    cp /tmp/libdynamic_gxx.so /usr/local/lib/
    ldconfig 

    

4.3 执行

## 创建 静态库 链接的 可执行文件
# make static_gxx
ar  cqs  /tmp/libstatic_gxx.a  g++_lib_first.o g++_lib_sec.o g++_lib_third.o
g++ -o g++_lib_main g++_lib_main.cpp -L /tmp -static -l static_gxx

## 创建 动态库 链接的 可执行文件
# make dynamic_gxx
g++ -fPIC -shared -o /tmp/libdynamic_gxx.so  g++_lib_first.cpp g++_lib_sec.cpp g++_lib_third.cpp
g++ -o g++_lib_main_dynamic g++_lib_main.cpp -L /tmp -l dynamic_gxx
cp /tmp/libdynamic_gxx.so /usr/local/lib/