Linux下动态库与静态库学习笔记

动态库与静态库的区别

库有两种:静态库和共享库(动态库)。

win32平台下,静态库通常后缀为.lib,动态库为.dll ;

linux平台下,静态库通常后缀为.a,动态库为.so 。

动态库与静态库均以文件的形式存在,其本质上是一种可执行代码的二进制格式,可以被载入内存中执行。无论是动态链接库还是静态链接库,它们无非是向其调用者提供变量、函数和类。

静态库(.a后缀结尾):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

动态库(s0后缀结尾):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

就实现结果而言,静态库就是将需要的链接库的代码一并拷贝到可执行程序中
动态库则是不进行拷贝库的代码这个过程,只将所需要的链接库的地址附在可执行程序中

例如,当我们使用 puts 函数时:

静态库的做法是将 stdio.h 中包含的 puts 函数的实现代码直接复制到我们的项目中。

动态库的做法则是将 puts 函数在 C 标准库中的地址引用到我们的项目中,而不是复制其实现代码。

静态链接库在程序编译时会被链接到目标代码中,目标程序运行时将不再需要改动态库,移植方便,体积较大,浪费控件和资源,因为所有相关的对象文件与牵涉到库都被链接合成一个可执行文件,这样导致可执行文件的体积较大。

动态库在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入,因为可执行文件体积较小。有了动态库,程序的升级会相对比较简单,比如某个动态库升级了,只需要更换这个动态库的文件,而不需要去更换可执行文件。但要注意的是,可执行程序在运行时需要能找到动态库文件。可执行文件时动态库的调用者。

静态库与动态库的制作与使用


├── CMakeLists.txt
├── include
│   └── head.h
├── main.c
└── src
    ├── add.c
    ├── div.c
    ├── mult.c
    └── sub.c

在这里有add.c,div.c,mult.c,sub.c,main.c,head.h 

生成静态库

制作静态库
add_library(库名称 STATIC 源文件1 [源文件2] ...)
 
在Linux中,静态库名字分为三部分:lib+库名字+.a,此处只需要指定出库的名字就可以了,
另外两部分在生成该文件的时候会自动填充。
 
方法一:
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)
add_library(calc STATIC ${SRC_LIST})
 
方法二:
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(calc STATIC ${SRC_LIST})
 
这样最终就会生成对应的静态库文件libcalc.a

使用 aux_source_directory 时,你只需要指定目录和用于存储源文件列表的变量名。例如:

aux_source_directory(. SRC_LIST)

这条命令会将当前目录下的所有认可的源文件(通常是 .cpp 文件)的路径收集起来,并将它们存储在变量 SRC_LIST 中。然后,你可以在 add_executableadd_library 命令中使用这个变量来指定编译目标的源文件。

需要注意的是,使用 aux_source_directory 时,如果目录中添加了新的源文件,你需要手动重新运行 CMake 来更新构建系统,使其包含新文件。因为 CMake 生成的构建系统本身不知道何时添加了新源文件,除非 CMakeLists.txt 文件被修改。

CMakeLists.txt文件编写:

cmake_minimum_required(VERSION 3.10)
project(MyProject)
 
#包含头文件 注意:PROJECT_SOURCE_DIR 或 CMAKE_CURRENT_SOURCE_DIR
include_directories(${PROJECT_SOURCE_DIR}/include)
# 方式一: 使用aux_source_directory命令
# aux_source_directory(./src SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)
add_executable(app main.c ${SRC_LIST}) # 生成可执行的程序
 
# 制作库文件
# 1.生成静态库 libcalc.a
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library(calc STATIC ${SRC_LIST})
 
#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
 
set(HOME ${PROJECT_SOURCE_DIR}) # 定义一个变量用于存储一个绝对路径
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) # 将拼接好的路径值设置给EXECUTABLE_OUTPUT_PATH宏
cmake_minimum_required(VERSION 3.10)
project(MyProject)
 
#包含头文件 注意:PROJECT_SOURCE_DIR 或 CMAKE_CURRENT_SOURCE_DIR
include_directories(${PROJECT_SOURCE_DIR}/include)


# 方式二: 使用GLOB命令 注意:PROJECT_SOURCE_DIR 或 CMAKE_CURRENT_SOURCE_DIR
# set(SRC ${PROJECT_SOURCE_DIR}/src) 
set(SRC ${CMAKE_CURRENT_LIST_DIR}/src)
file(GLOB SRC_LIST ${SRC}/*.c)
add_executable(app main.c ${SRC_LIST}) # 生成可执行的程序


# 制作库文件
# 1.生成静态库 libcalc.a
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library(calc STATIC ${SRC_LIST})


#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)


set(HOME ${PROJECT_SOURCE_DIR}) # 定义一个变量用于存储一个绝对路径
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) # 将拼接好的路径值设置给EXECUTABLE_OUTPUT_PATH宏 

生成动态库 

制作动态库
add_library(库名称 SHARED 源文件1 [源文件2] ...) 
在Linux中,动态库名字分为三部分:lib+库名字+.so,此处只需要指定出库的名字就可以了,
另外两部分在生成该文件的时候会自动填充
方法一:
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)
add_library(calc SHARED ${SRC_LIST})
 
方法二:
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(calc SHARED ${SRC_LIST})
这样最终就会生成对应的动态库文件libcalc.so
 
指定输出的路径
​由于在Linux下生成的静态库默认不具有可执行权限,所以在指定静态库生成的路径的时候就
不能使用EXECUTABLE_OUTPUT_PATH宏了,而应该使用LIBRARY_OUTPUT_PATH,这个宏对
应静态库文件和动态库文件都适用
 
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
# 设置动态库/静态库生成路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 生成动态库
add_library(calc SHARED ${SRC_LIST})
# 生成静态库
add_library(calc STATIC ${SRC_LIST})

 CMakeLists.txt编写

cmake_minimum_required(VERSION 3.10)
project(MyProject)
 
#包含头文件 注意:PROJECT_SOURCE_DIR 或 CMAKE_CURRENT_SOURCE_DIR
include_directories(${PROJECT_SOURCE_DIR}/include)
# 方式一: 使用aux_source_directory命令
# aux_source_directory(./src SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)
add_executable(app main.c ${SRC_LIST}) # 生成可执行的程序
 
# 制作库文件
# 2.生成动态库 libcalc.so
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library(calc SHARED ${SRC_LIST})
 
#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
 
set(HOME ${PROJECT_SOURCE_DIR}) # 定义一个变量用于存储一个绝对路径
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) # 将拼接好的路径值设置给EXECUTABLE_OUTPUT_PATH宏
cmake_minimum_required(VERSION 3.10)
project(MyProject)
 
#包含头文件 注意:PROJECT_SOURCE_DIR 或 CMAKE_CURRENT_SOURCE_DIR
include_directories(${PROJECT_SOURCE_DIR}/include)
# 方式二: 使用GLOB命令 注意:PROJECT_SOURCE_DIR 或 CMAKE_CURRENT_SOURCE_DIR
# set(SRC ${PROJECT_SOURCE_DIR}/src) 
set(SRC ${CMAKE_CURRENT_LIST_DIR}/src)
file(GLOB SRC_LIST ${SRC}/*.c)
add_executable(app main.c ${SRC_LIST}) # 生成可执行的程序


# 制作库文件
# 2.生成动态库 libcalc.so
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library(calc SHARED ${SRC_LIST})


#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
set(HOME ${PROJECT_SOURCE_DIR}) # 定义一个变量用于存储一个绝对路径
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) # 将拼接好的路径值设置给EXECUTABLE_OUTPUT_PATH宏

链接动态库与静态库


.
├── calc
│   ├── calc_add.cpp
│   ├── CMakeLists.txt
│   ├── calc_div.cpp
│   ├── calc_mult.cpp
│   └── calc_sub.cpp
├── CMakeLists.txt
├── include
│   ├── calc.h
│   └── sort.h
├── sort
│   ├── CMakeLists.txt
│   ├── sort_insert.cpp
│   └── sort_select.cpp
└── test
    ├── CMakeLists.txt
    └── sort.cpp
 
4 directories, 13 files

一、在静态库中链接动态库 

  • 修改sort.cpp,包含calc.h文件,调用add函数
  • sort.cpp 
#include "sort.h"
#include <iostream>
#include "calc.h"
using namespace std;
int  main()
{
    int number1 = CalcAdd(1,23);
    cout<<"调用calc库 中的add函数,那么1 + 23 = "<<number1<<endl;
    int a[10] = {8,1,9,7,2,4,5,6,10,3};
    SortInsert(a,10);
    cout<<"插入排序结果:";
    print(a,10);
    SortSelect(a, 10);
    cout << "选择排序结果: ";
    print1(a, 10);
}
 
  • calc文件夹中的CMakeLists.txt 
cmake_minimum_required(VERSION 3.10)
project(calc)
 
# 搜索源文件
aux_source_directory(./ SRC)
include_directories(${HEADPATH}) # 头文件路径 HEADPATH
 
set(LIBRARY_OUTPUT_PATH ${LIBPATH}) # 库生成的路径 LIBPATH
add_library(${CALCLIB} SHARED ${SRC}) # 生成动态库
  • sort文件夹中的CMakeLists.txt 
cmake_minimum_required(VERSION 3.10)
project(sort)
 
# 搜索源文件
aux_source_directory(./ SRC)
# 头文件路径 HEADPATH
include_directories(${HEADPATH}) 
set(LIBRARY_OUTPUT_PATH ${LIBPATH}) # 库生成的路径 LIBPATH
link_directories(${LIBPATH})
add_library(${SORTLIB} STATIC  ${SRC}) # 生成静态库
# 链接calc动态库
target_link_libraries(${SORTLIB} ${CALCLIB})
  •  test文件夹中的CMakeLists.txt 
cmake_minimum_required(VERSION 3.10)
project(test2)
 
aux_source_directory(./ SRC)
include_directories(${HEADPATH})
 
set(EXECUTABLE_OUTPUT_PATH ${EXECPATH})
 
# 包含静态库路径
link_directories(${LIBPATH})
# 链接静态库, sort为静态库的名字
link_libraries(${SORTLIB})
add_executable(${APPNAME2} ${SRC}) 
  • 项目根目录中的CMakeLists.txt 
cmake_minimum_required(VERSION 3.10)
project(test)
# 定义变量
 
# 库生成的路径
set(LIBPATH ${PROJECT_SOURCE_DIR}/lib)
 
# 可执行程序的存储目录(测试程序生成的路径)
set(EXECPATH ${PROJECT_SOURCE_DIR}/bin)
 
# 头文件路径
set(HEADPATH ${PROJECT_SOURCE_DIR}/include)
 
# 库文件的名字
set(CALCLIB calc)
set(SORTLIB sort)
 
# 可执行程序的名字
set(APPNAME1 app1)
set(APPNAME2 app2)
 
# 给当前节点添加子目录
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值