1.制作静态库
- 语法:
add_library(库名称 STATIC 源文件1 [源文件2] ...)
- 在Linux中,静态库名字分为三部分:
lib
+库名字
+.a
,此处只需要指定出库的名字就可以了,另外两部分在生成该文件的时候会自动填充- 在Windows中虽然库名和Linux格式不同,但也只需指定出名字即可
- 示例:
cmake_minimum_required(VERSION 3.0) project(CALC) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) add_library(calc STATIC ${SRC})
2.制作动态库
- 语法:
add_library(库名称 SHARED 源文件1 [源文件2] ...)
- 在Linux中,动态库名字分为三部分:
lib
+库名字
+.so
,此处只需要指定出库的名字就可以了,另外两部分在生成该文件的时候会自动填充- 在Windows中虽然库名和Linux格式不同,但也只需指定出名字即可
- 示例:
cmake_minimum_required(VERSION 3.0) project(CALC) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) add_library(calc SHARED ${SRC})
3.指定输出的路径
- 对于生成的库文件来说和可执行程序一样都可以指定输出路径
1.动态库
- 方法:
LIBRARY_OUTPUT_DIRECTORY
,这个宏对应动态库文件 - 示例:
cmake_minimum_required(VERSION 3.0) project(CALC) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) # 设置动态库生成路径 set(LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) add_library(calc SHARED ${SRC})
2.静态库
- 方法:
ARCHIVE_OUTPUT_DIRECTORY
,这个宏对应静态库文件 - 示例:
cmake_minimum_required(VERSION 3.15) project(CALC) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) # 设置静态库生成路径 set(ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) add_library(calc STATIC ${SRC})
4.包含库文件
- 在编写程序的过程中,可能会用到一些系统提供的动态库或者自己制作出的动态库或者静态库文件,CMake中也提供了相关的加载动态库的命
1.链接静态库
- 语法:
link_libraries(<static lib> [<static lib>...])
- 参数:
<static lib>
:要链接的静态库的名字- 可以是全名:
libxxx.a
- 也可以掐头(
lib
)去尾(.a
):xxx
- 可以是全名:
[<static lib>]
:要链接的其他静态库的名字
- 如果该静态库不是系统提供的(自己制作或者使用第三方提供的静态库)可能出现静态库找不到的情况,此时可以将静态库的路径也指定出来
link_directories(<lib path>)
- 示例:
cmake_minimum_required(VERSION 3.15) project(CALC) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) # 指定库搜索路径 link_directories(${PROJECT_SOURCE_DIR}/lib) # 链接静态库 link_libraries(calc1) add_executable(app_static ${SRC})
2.链接动态库
- 语法:
target_link_libraries( <target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
- 参数:
target
:指定要加载动态库的文件的名字- 该文件可能是一个源文件
- 该文件可能是一个动态库文件
- 该文件可能是一个可执行文件
PRIVATE|PUBLIC|INTERFACE
:动态库的访问权限,默认是PUBLIC
- 如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的
PUBLIC
即可 - 动态库的链接具有传递性,如果动态库A链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法
target_link_libraries(A B C) target_link_libraries(D A)
PUBLIC
:在PUBLIC
后面的库会被Link
到前面的target
中,并且里面的符号也会被导出,提供给第三方使用PRIVATE
:在PRIVATE
后面的库仅被Link
到前面的target
中,并且终结掉,第三方不能感知你调了啥库INTERFACE
:在INTERFACE
后面引入的库不会被链接到前面的target
中,只会导出符号
- 如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的
- 动态库的链接和静态库是完全不同的:
- 静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就被加载到内存中了
- 动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存
- 因此,在CMake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后
- 链接系统动态库:无需指出库路径
cmake_minimum_required(VERSION 3.0) project(TEST) file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) # 添加并指定最终生成的可执行程序名 add_executable(app ${SRC_LIST}) # 指定可执行程序要链接的动态库名字 target_link_libraries(app pthread)
- 链接第三方动态库:需指出库所在路径
cmake_minimum_required(VERSION 3.15) project(CALC) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) # 指定库搜索路径 link_directories(${PROJECT_SOURCE_DIR}/lib) add_executable(app_shared ${SRC}) # 链接动态库 target_link_libraries(app_shared calc2)
3.两个命令区别
- 实际上
target_link_libraries
和link_libraries
对于动态库和静态库的链接并没有区别,它们都可以用于链接动态库和静态库到目标 target_link_libraries
- 作用范围:是一个命令,用于将库链接到特定的目标(target)
- 比如可执行文件、静态库或共享库
- 用法:通常用于将库链接到单个目标,可以指定一个或多个库,并且可以针对不同的目标分别调用这个命令
- 作用范围:是一个命令,用于将库链接到特定的目标(target)
link_libraries
- 作用范围:是一个全局命令,用于设置在链接过程中所有目标(target)都要链接的库
- 用法:通常在项目的顶层
CMakeLists.txt
文件中使用,用于指定整个项目的链接库,影响所有的目标
- 主要区别:
- 作用范围:
target_link_libraries
用于特定目标link_libraries
用于全局设置,影响整个项目
- 用法:
target_link_libraries
可以被用于每个单独的目标link_libraries
只需要被调用一次,影响整个项目
- 作用范围: