使用一个已经存在的动态库,需要用到CMake中两个命令,分别是:

  • link_directories
  • target_link_libraries

下面先介绍以下两个命令的格式及其含义,最后是一个使用已存在动态库的例子。

一、link_directories 链接库目录

为一个对象或者依赖项指定一个存放库的目录或标志,其基本格式是:

link_directories([AFTER|BEFORE] directory1 [directory2 ...])

与之前include_directories一样,可以向已经存在的库目录列表向前或者向后追加。目录可以是多个,空格隔开,同样支持绝对路径和相对路径(相对路径的前缀是变量CMAKE_CURRENT_SOURCE_DIR,也就是当前CMakeLists.txt所在)

Tips:如果有其他选择,应该尽量避免link_directories,实在无法避免使用绝对路径增加工程的可移植性。绝对路径可以配合find_library()+target_link_libraries()

二、target_link_libraries

该命令用于链接目标或者其依赖项时的库或者标志。语法定义如下:

target_link_libraries(<target> ... <item>... ...)
  • <target> 变量必须由add_excutable()或者add_library()创建,不能是别名目标
  • <item> 形式有多种,见下面解释

对于每一个item可以是以下几种形式:

  • 一个目标库名字。CMake编译系统将会获得这个库的完整路径,一旦库的内容发生改变,cmake将会捕捉到这一信息,将变化更新到程序中。目标库的来源只能是两个:1. add_library命令创建的库对应变量名 2.IMPORTED的由外部编译的库

IMPORTED是用来表示对象是否为已经存在依赖。一个已经存在的对象,意味着它是由其他别的什么项目生成的,我们只需要使用它,而不需要负责去编译它。一旦一个对象被声明为“被导入”的,那么可以通过控制一系列的命令继续向这个已经存在的库传递信息,如:包含目录、目标编译选项和连接库。如果这个IMPORTED对象被指定了IMPORTED_NO_SONAME选项,那么cmake将会去搜索它,而不是用绝对路径去找它(如:/usr/lib/libfoo.so变成lfoo

  • 一个完整的带路径的库文件。和使用目标库一样,编译系统将会获得完整路径,一旦库发生变化,功能将会重新链接一份最新的库。有些时候,就算是给定一个完整路径,也会去搜索库(也就是/usr/lib/libfoo.so 变成了-lfoo
  • 一个普通的库名。编译器将会直接去搜索这个库,注意:我们不需要额外的引号或者其他转移符号。如:库名为foo,编译器将会去找动态库或者静态库。
  • 一个链接标记。这个项将会以-开头,但非-l或者-framework,将会被当成链接标志。
  • 一个表达式生成器。一个表达式生成器$<...>

三、例子

project(Demo)
cmake_minimum_required(VERSION 3.15)
include_directories(../libCreate)
link_directories("../libCreate")

add_executable(Demo main.cpp)
target_link_libraries(Demo Fun)