第三方库通过 cmake 加到主工程上的一种方法演示

多个开源软件以 fetchcontent_declare 的方法进行加载

Posted by Jerry Chen on January 6, 2021

工程概览

库文件压缩包会解压到 ext 目录;

ext/simpleini 和 ext/lvgl 需要手动解压拷贝至此;

include 目录下 lv_conf.h.in 来源于 ext/lvgl 中 lv_conf_template.h,其中 #if 0 改为 #if 1

  • libuv 下载地址:github
  • spdlog 下载地址:github
  • nlohmann_json 下载地址:github
  • pugixml 下载地址:github
  • yaml-cpp 下载地址:github
  • mosquitto 下载地址:官网
  • lvgl 下载地址:github
  • simpleini 下载地址:github
  • sdl2 下载地址:官网

主 CMake 脚本

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 设置 CMake 最低可用版本
cmake_minimum_required(VERSION 3.14)

# 设置工程名称和其他属性
project(desktopGui)

# 设定取模块路径:./cmake 路径以及原本的模块路径
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
# 使用 FetchContent 插件
include(FetchContent)

# 设置版本为 c99 c++11
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 导入 CMake 模块
include(libuv2)
include(spdlog2)
include(pugixml2)
include(yaml-cpp2)
include(nlohmann_json2)
include(mosquitto2)
include(sdl22)

# 导入未使用 CMake 的模块,手写 CMake 脚本
include(simpleini2)
include(lvgl2)

# 创建可执行程序项目
add_executable(main src/main.cpp ${simpleini_src} ${lvgl_src})

# 链接库,使用 libuv
target_link_libraries(main
	PRIVATE uv
	PRIVATE spdlog::spdlog
	PRIVATE pugixml::pugixml
	PRIVATE yaml-cpp
	PRIVATE nlohmann_json::nlohmann_json
	PRIVATE libmosquitto
	PRIVATE SDL2main
	PRIVATE SDL2
)

# 构建成功后复制依赖库到可执行程序所在目录
if (WIN32)
    add_custom_command(TARGET main POST_BUILD 
	    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/uv-build/uv.dll ${CMAKE_BINARY_DIR}
	    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/mqtt-build/lib/mosquitto.dll ${CMAKE_BINARY_DIR}
	    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/sdl2-build/SDL2d.dll ${CMAKE_BINARY_DIR}
    )
else ()
    add_custom_command(TARGET main POST_BUILD 
	    COMMAND cp ${CMAKE_BINARY_DIR}/_deps/uv-build/libuv.so ${CMAKE_BINARY_DIR}/libuv.so.1
	    COMMAND cp ${CMAKE_BINARY_DIR}/_deps/mqtt-build/lib/libmosquitto.so ${CMAKE_BINARY_DIR}/libmosquitto.so.1
	    COMMAND cp ${CMAKE_BINARY_DIR}/_deps/sdl2-build/libSDL2-2.0.so ${CMAKE_BINARY_DIR}/libSDL2-2.0.so.0
    )
endif ()

main.cpp

1
2
3
4
5
6
7
#include <stdio.h>

int main(int argc, char *argv[])
{
  printf("Hello world!\n");
  return 0;
}

模块 CMake 脚本

libuv2.cmake

1
2
3
4
5
6
7
8
9
10
11
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(uv
 URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/libuv-v1.x.zip
 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/libuv
)
# 设置目标 CMakeLists.txt 中的选项,不编译库的附加程序
set(LIBUV_BUILD_TESTS OFF CACHE INTERNAL "")
fetchcontent_makeavailable(uv)
# 不主动编译静态库
set_target_properties(uv_a PROPERTIES EXCLUDE_FROM_ALL ON)

spdlog2.cmake

1
2
3
4
5
6
7
8
9
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(spdlog
	URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/spdlog-v1.x.zip
	SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/spdlog
)
# 设置目标 CMakeLists.txt 中的选项,不编译库的附加程序
set(SPDLOG_BUILD_EXAMPLE OFF CACHE INTERNAL "")
fetchcontent_makeavailable(spdlog)

nlohmann_json2.cmake

1
2
3
4
5
6
7
8
9
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(json
	URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/json-develop.zip
	SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/nlohmann_json
)
# 设置目标 CMakeLists.txt 中的变量,不编译库的测试程序
set(JSON_BuildTests OFF CACHE INTERNAL "")
fetchcontent_makeavailable(json)

pugixml2.cmake

1
2
3
4
5
6
7
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(pugixml
	URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/pugixml-master.zip
	SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/pugixml
)
fetchcontent_makeavailable(pugixml)

yaml-cpp2.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(yaml
	URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/yaml-cpp-master.zip
	SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/yaml-cpp
)
# 设置目标 CMakeLists.txt 中的选项,不编译库的附加程序
set(YAML_CPP_BUILD_TESTS OFF CACHE INTERNAL "")
set(YAML_CPP_BUILD_TESTS OFF CACHE INTERNAL "")
set(YAML_CPP_BUILD_CONTRIB OFF CACHE INTERNAL "")
set(YAML_CPP_BUILD_TOOLS OFF CACHE INTERNAL "")
set(YAML_CPP_INSTALL OFF CACHE INTERNAL "")
fetchcontent_makeavailable(yaml)

mosquitto2.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(mqtt
	URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/mosquitto-master.zip
	SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/mosquitto
)
# 设置目标 CMakeLists.txt 中的变量,不编译库的测试程序
set(WITH_TLS OFF CACHE INTERNAL "")
set(WITH_UNIX_SOCKETS OFF CACHE INTERNAL "")
set(WITH_SOCKS OFF CACHE INTERNAL "")
set(WITH_THREADING OFF CACHE INTERNAL "")
set(WITH_LIB_CPP OFF CACHE INTERNAL "")
set(WITH_CLIENTS OFF CACHE INTERNAL "")
set(WITH_BROKER OFF CACHE INTERNAL "")
set(WITH_APPS OFF CACHE INTERNAL "")
set(WITH_PLUGINS OFF CACHE INTERNAL "")
set(DOCUMENTATION OFF CACHE INTERNAL "")
fetchcontent_makeavailable(mqtt)
include_directories(ext/mosquitto/include)

sdl22.cmake

1
2
3
4
5
6
7
8
9
10
11
12
# 指定远程仓库地址、版本,本地存放地址
# 如果 github 太慢,可用 gitee 代替
fetchcontent_declare(sdl2
 URL        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/SDL2-2.0.14.zip
 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/SDL2
)
# 设置目标 CMakeLists.txt 中的变量,不编译库的测试库,编译动态库
set(SDL_TEST OFF CACHE INTERNAL "")
set(SDL_SHARED ON CACHE INTERNAL ON)
fetchcontent_makeavailable(sdl2)
# 不主动编译静态库
set_target_properties(SDL2-static PROPERTIES EXCLUDE_FROM_ALL ON)

lvgl2.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 导入未使用 CMake 的模块,手动写脚本
# 请事先解压如下压缩包
# URL               ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/lvgl-master.zip
# 到如下目录
# SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR}/ext/lvgl
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ext/lvgl)
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/ext/lvgl)
	# 查找满足规则的文件名放到 SOURCES 变量
	file(GLOB_RECURSE lvgl_src ${CMAKE_CURRENT_SOURCE_DIR}/ext/lvgl/src/*.c)

	if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include/lv_conf.h.in)
		# 写入文件从 include/lv_conf.h.in 到 ext/lv_conf.h
		configure_file(
			"${CMAKE_CURRENT_SOURCE_DIR}/include/lv_conf.h.in"
			"${CMAKE_CURRENT_SOURCE_DIR}/ext/lv_conf.h"
		)
	else ()
		message(FATAL_ERROR "Not found ${CMAKE_CURRENT_SOURCE_DIR}/include/lv_conf.h.in")
	endif ()
else()
	message(FATAL_ERROR "Not found ${CMAKE_CURRENT_SOURCE_DIR}/ext/lvgl")
endif()

simpleini2.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
# 导入未使用 CMake 的模块,手动写脚本
# 请事先解压如下压缩包
# URL               ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Archive/simpleini-master.zip
# 到如下目录
# SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR}/ext/simpleini
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ext/simpleini)
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/ext/simpleini)
	set(simpleini_src
		${CMAKE_CURRENT_SOURCE_DIR}/ext/simpleini/ConvertUTF.c
	)
else()
	message(FATAL_ERROR "Not found ${CMAKE_CURRENT_SOURCE_DIR}/ext/simpleini")
endif()