(十六)CMake 增加一个库

当我们开发一个软件的时候,可以将软件用到的一些函数、功能等放入一个仓库——库。动态库和静态库的区别在于,前者是运行时调用,后者是编译时集成到可执行程序中的。下面是动态库和静态库的对比[1]:

比较项优点缺点
动态库体积小,升级方便,编程语言间可共享可执行运行依赖,兼容性问题
静态库装载较快,可能存在相同代码段运行时无依赖

CMake工具生成动态库相当简单,只需要掌握一条指令add_library

一、add_library

1.1 普通库

利用给定源文件集合向项目增加一个输出库命令。其基本语法如下:

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])
  • <name> 库名为name,库将会从命令的[<source>...]所列的源文件编译;
  • [STATIC | SHARED | MODULE],可以指定库的类型;STATIC静态库,SHARED动态库,MODULE模块。如果这个参数没有指定,默认是STATICSHARED(具体是哪一个取决于BUILD_SHARED_LIB是否处于ON状态),同时POSITION_INDEPENDENT_CODE自动开启,也就是默认创建与位置无关的库。
  • [<source>...] 生成库所用的源文件

默认情况下,动态库将会被创建在CMAKE_BINARY_DIR,如果你想改变输出位置,可以尝试改变以下变量:ARCHIVE_OUT_DIRECTORY LIBARARY_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY,同样你也可以通过OUTPUT_NAME来修改输出的库名。

在linux环境下编程,我们如果想要使用第三方的库,基本上有以下几种方式[1]:

  • 1、将第三方库的源码合并到我们的工程项目代码中,一起编译。
  • 2、将第三方库编译成静态库(xxx.a),我们在使用时,在Makefile中引用该静态库。
  • 3、将第三方库编译成动态库(xxx.so),我们在使用时,隐性调用该动态库,具体表现为需要 在程序中包含动态库的头文件,同时需要在/usr/lib路径下,存放动态库文件,以便程序调用。
  • 4、将第三方库编译成动态库(xxx.so),我们在使用时,显性调用该动态库,在程序中,不需要包含动态库的头文件,使用 dlopen、dlsym等接口函数调用该动态库。

第1和2种,本质上是一样的,使用静态库,编译时,会将静态库的内容合并到工程代码中,唯一区别的是当我们拿不到第三方库的源码时,可以直接使用静态库,相当于使用一个黑盒子,静态库提供接口。
第3和4种方式,我们常用的是第3种方式,也就是隐性调用,但是显性调用一种程序插件的概念,随用随加载,不用不加载。

1.2 对象库(不常见,可以用静态库代替)

将源代码编译生成的.o文件抽象成一个OBJECT对象库。当你使用这个对象库时(如add_library或者add_executable),需要通过与此对象库对应的对象表达式来使用。

add_library(<name> OBJECT [<source>...])

Object库主要用来定义源文件编译生成的目标文件集合,可以作为其他目标的输入来源:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)# 将单个源文件archieve zip.cpp和lzma.cpp处理成名为archive的对象库
add_library(archiveExtras STATIC $<TARGET_OBJECTS:archive> extras.cpp)# 通过$<TARGET_OBJECT:对象库名>$作为目标程序来源
add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp) # 同上

也可以链接到其他目标中去:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)
add_library(archiveExtras STATIC extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive) # archieve目标库加上extras目标对象=archiveExtras
add_executable(test_exe test.cpp)
target_link_libraries(test_exe archive) # 目标文件的一个库链接
1.3 接口库

接口库是一个不编译源文件并且不产生任何实际库文件的库,但是可以有一些特性设置并且能够被安装和输出,一般来说这些属性(INTERFACE_*)如INTERFACE_INCLUDE_DIRECTORIESINTERFACE_COMPILE_DEFINITIONSINTERFACE_COMPILE_OPTIONS, INTERFACE_LINK_LIBRARIESINTERFACE_SOURCESINTERFACE_POSITION_INDEPENDENT_CODE,接口库只能使用以下命令:

set_property()
target_link_libraries(INTERFACE)
target_link_options(INTERFACE)
target_include_directories(INTERFACE)
target_compile_options(INTERFACE)
target_compile_definitions(INTERFACE)
target_sources(INTERFACE)

接口库主要是用在仅有头文件的库:

add_library(Eigen INTERFACE
  src/eigen.h
  src/vector.h
  src/matrix.h
  )
target_include_directories(Eigen INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
  $<INSTALL_INTERFACE:include/Eigen>
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 Eigen)

[1] https://docs.microsoft.com/zh-cn/windows/win32/dlls/advantages-of-dynamic-linking
[2] https://cmake.org/cmake/help/latest/command/add_library.html?highlight=add_library#command:add_library
[3] https://blog.csdn.net/u012351051/article/details/115497369
[4] https://zhuanlan.zhihu.com/p/56167140
[5]https://docs.microsoft.com/zh-cn/cpp/build/linking-an-executable-to-a-dll?view=msvc-170

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值