CMake-target_link_library

Posted by 周思进 on May 29, 2022

本文是阅读《Professional-CMake-A-Practical-Guide》第四章做的一点笔记。

1、add_library

在 CMakeLists.txt 文件可以通过如下命令创建库文件

add_library(targetName [STATIC | SHARED | MODULE]
    [EXCLUDE_FROM_ALL]
    source1 [source2 ...]
)

STATIC 和 SHARED 都好理解,就是 C 语言里的静态库和动态库的意思,文章是建议不要在 add_library 中直接指定是要何种类型库,而是在编译的时候通过宏来开关指定,如下:

cmake .. -DBUILD_SHARED_LIBS=YES

也可以在 add_library 语句之前进行如下配置

set(BUILD_SHARED_LIBS YES)


如果 A 库需要链接库 B,可以通过如下命令进行链接

target_link_libraries(targetName
    <PRIVATE|PUBLIC|INTERFACE> item1 [item2 ...]
    [<PRIVATE|PUBLIC|INTERFACE> item3 [item4 ...]]
...
)

上面三个关键词需要理解下:

PRIVATE:B 只是给 A 自己用,对于链接 A 库的对象,不需要用到 B;即只是 A 的源码实现中会包含 B 的头文件;对于链接 A 的执行程序是无法调用 B 中的接口实现

PUBLIC:链接 A 库的对象一定需要 B 的对我接口才能使用 A,如 A 接口的入参是在 B 中声明的;即 A 的头文件中也要包含 B 的头文件,且源码实现中会用到;对于链接 A 的执行程序是可以调用 B 中的接口实现

INTERFACE:A 自己不用,给链接 A 的对象使用;对于链接 A 的执行程序可以调用 B 中的接口实现

具体效果可以按下面的部分示例代码操作下:

hello_test $ tree
.
├── build
├── CMakeLists.txt
├── hello_world
│   ├── CMakeLists.txt
│   ├── hello
│   │   ├── CMakeLists.txt
│   │   ├── hello.c
│   │   └── hello.h
│   ├── hello_world.c
│   └── hello_world.h
└── main.c

//main.c
#include "hello_world.h"
#include "hello.h"

int main(int argc, char const *argv[])
{
    hello_word();
    hello();
    return 0;
}
// hello_test/CMakeLists.txt
...
add_executable(test 
    main.c
)

include_directories(hello_world)
target_link_libraries(test PRIVATE hello_world)

add_subdirectory(hello_world)
// hello_world/CMakeLists.txt

add_library(hello_world SHARED hello_world.c)

# 如果main.c 要使用hello接口,则这里使用 PUBLIC
target_link_libraries(hello_world PUBLIC hello)
target_include_directories(hello_world PUBLIC hello)

# 如果main.c 不需要使用hello接口,则这里使用 PRIVATE
# target_link_libraries(hello_world PRIVATE hello)
# target_include_directories(hello_world PRIVATE hello)

# 如果main.c 需要使用到,hello_world.c不需要使用,可以使用 INTERFACE
#target_link_libraries(hello_world INTERFACE hello)
#target_include_directories(hello_world INTERFACE hello)

add_subdirectory(hello)
// hello_world.c
#include "hello.h"

void hello_word(void)
{
    printf("[FILE:%s] [FUNC:%s] [Line:%d]  hello_world  \n", __FILE__, __func__, __LINE__ );
    hello();
}
// hello/CMakeLists.txt
add_library(hello SHARED hello.c)
// hello.c
void hello(void)
{
    printf("[FILE:%s] [FUNC:%s] [Line:%d]  hello  \n", __FILE__, __func__, __LINE__ );
}