动态库与静态库的区别
库有两种:静态库和共享库(动态库)。
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_executable
或 add_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)