0%

cmake 迷你系列(四)同步构建库

引言

【创建你自己的库】 这篇文章中,我们遇到一个问题,就是必须先创建库,然后才能编译我们的源程序,那么有没有办法让我们的源程序与库同时编译呢?答案是肯定的。

构造同步编译

其实思路很简单,就是在根 CMakeLists.txt 文件中,把创建库的指令写好,然后目标文件引入即可。我们来看一下具体内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
cmake_minimum_required(VERSION 3.21)
project(test VERSION 0.0.1 LANGUAGES C)

set(CMAKE_C_STANDARD 11)

set(LIB_INSTALL_DIR ${PROJECT_SOURCE_DIR}/libs/lib)
set(LIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/libs/include)


option(EMBED_SOURCE "using embed source to build" ON)

if (EMBED_SOURCE)
message(STATUS "start build...")
include_directories(${PROJECT_SOURCE_DIR}/utils)

set(UTILS_SOURCE
${PROJECT_SOURCE_DIR}/utils/utils.c
)

file(STRINGS ${PROJECT_SOURCE_DIR}/utils/VERSION version)

add_library(utils STATIC ${UTILS_SOURCE})
add_library(utils-share SHARED ${UTILS_SOURCE})
set_target_properties(utils-share PROPERTIES
OUTPUT_NAME utils
VERSION ${version}
PUBLIC_HEADER utils/utils.h
)

install(TARGETS utils utils-share
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION ${LIB_INCLUDE_DIR}
PUBLIC_HEADER DESTINATION ${LIB_INCLUDE_DIR}
)

endif ()

add_subdirectory(src)

有了前几篇文章的基础,这段代码就不难理解了。

  1. 10 行,我们添加一个开关,是否采用内嵌代码编译。
  2. 12 ~ 37 行进行编译库。
  3. 13 行,我们打印构建日志,这里只是单纯的标记构建开始。
  4. 14 行,引入头文件。
  5. 16 行,指定源码路径。
  6. 20 行,指定动态库的版本号。
  7. 22 ~ 23 行,添加库。
  8. 24 行,设置库属性。
  9. 30 行,将库安装到指定路径。

我们再看一下 src 下的 CMakeLists.txt 文件:

1
2
3
4
5
6
7
8
9
10
set(MAIN_SOURCE
main.c
)

add_executable(test ${MAIN_SOURCE})
target_link_libraries(test PRIVATE utils)

install(TARGETS test
RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin
)

这里我们去掉了之前的 target_include_directories(test PRIVATE ${UTILS_HEADER}),因为已经 include_directories(${PROJECT_SOURCE_DIR}/utils) 过了。然后 target_link_libraries(test PRIVATE utils) 这里,我们用 utils 库的名字(即 add_library(utils STATIC ${UTILS_SOURCE}) 指定的名字)取代之前的变量。
最后我们使用 install 命令,将源码打包成 bin 文件,并放到 ${PROJECT_SOURCE_DIR}/bin 路径下,其中 RUNTIME 代表可执行文件的意思。