一、cmake依赖管理介绍

在这里插入图片描述

CMake跨平台构建系统支持 C/C++、Objective-C、Fortran 等多种语言。CMake 提供了丰富的依赖管理功能可以帮助开发人员轻松地管理第三方库的依赖关系

CMake依赖管理功能主要包括以下几点:

CMake 的依赖管理功能可以分为两种类型

今天我们就主要介绍: 源码管理

二、源码依管理

  1. cmake自带命令FetchContent
  2. cmake三方社区支持的命令: CPM
  3. gitsubmodule

如何选择何种方式作为依赖管理:
如果你的依赖不是cmake项目,那就推荐使用git submodule进行管理
如果你的依赖项目cmake项目,那FetchContentCPM都能满足需要,但是CPM更为优雅,所以更加推荐

1. FetchContent

使用FetchContent是非常简单的,只需要三步:

  1. 引入头文件
  2. 定义依赖需要下载代码地址和一些其它属性
  3. enable依赖

比如

# 从GitHub下载代码
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)

# 从网址下载代码
FetchContent_Declare(
  myCompanyIcons
  URL      https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
  URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)
# 确保依赖项在这里已经完成下载构建
FetchContent_MakeAvailable(googletest myCompanyIcons)

FetchContent_Declare命令会生成以下变量

  1. <lowercaseName&gt;_POPULATED: 设置TRUE
  2. <lowercaseName>_SOURCE_DIR设置依赖下载位置
  3. <lowercaseName>_BINARY_DIR: 设置依赖构建的位置

设置使用关键字定义依赖源的一些信息时候,有一些可供选择的设置

# 从GitHub上下载代码
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
  
  # 先通过find_package命令,通过name Gtest来找库,找不到就调用Fetch下载依赖
  # FIND_PACKAGE_ARGS NAMES GTest
  
  # find_package不能从本地找库,要用Fetch下载下来的库
  # OVERRIDE_FIND_PACKAGE
  
  # 该依赖的cmakelist配置文件是在该项目cmake文件夹内。
  # SOURCE_SUBDIR  cmake
  
  # 设置下载的依赖存放路径
  # SOURCE_DIR firmware
  
  # 是否启用克隆,(只会克隆当前分支标签提交,以及这些提交引用的所有父提交)
  # GIT_SHALLOW
)
# 确保依赖项在这里已经完成下载和构建
FetchContent_MakeAvailable(googletest myCompanyIcons)

有些情况下,想要对依赖的管理控制的颗粒度更加精细,我们可以:

# 检查是否依赖已经下载
FetchContent_GetProperties(depname)
# 如果还没有下载
if(NOT depname_POPULATED)
		# 执行下载
		FetchContent_Populate(depname	)
endif()

使用方法进行下载安装依赖,该方法依赖FetchContent_Declare() 提前声明依赖。

但是下载依赖只会下载一次,如果二次调用则会因为错误停止

所以项目在调用FetchContent_Populate之前,应该调用FetchContent_GetProperties()方法,获得当前状态

使用保存内容详细信息时,对 FetchContent_MakeAvailable()FetchContent_Populate()调用会在全局属性记录可以随时查询信息。该信息可以包括与内容相关联的源目录二进制目录,以及内容填充是否已在当前配置运行期间被处理

find_package进行集成

include(FetchContent)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
  FIND_PACKAGE_ARGS NAMES GTest
)
FetchContent_Declare(
  Catch2
  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  GIT_TAG        605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1
  FIND_PACKAGE_ARGS
)

# This will try calling find_package() first for both dependencies
FetchContent_MakeAvailable(googletest Catch2)

对于 Catch2 ,不需要为 find_package() 提供额外参数,因此在 FIND_PACKAGE_ARGS 关键字之后不需要提供额外参数。对于 googletest ,其包通常称为 GTest ,因此添加参数以支持通过名称找到它。

OVERRIDE_FIND_PACKAGE : find_package应该使用FetchContent_Declare里的信息
FIND_PACKAGE_ARGS: 如果find_package成功在本地找到二进制文件,则不需要FetchContent_Declare里的信息
SOURCE_SUBDIR cmake: 指定依赖的项目cmakelist文件地址, 该实例配置在项目跟路径下的cmake文件夹
SOURCE_DIR firmware指定下载依赖后存放的路径,该设置配置在项目跟路径下的firmware 文件夹

2. CPM

官方的cmake依赖管理工具CPM GitHub

使用方法 直接release页面,将cmake脚本文件下载,导入到自己代码中。

image-20231203103400676

include(CPM)
# 使用GitHub用户nlohmann仓库json仓的3.11.2版本代码
cpmaddpackage("gh:nlohmann/json#v3.11.2")
  1. gh: : github
  2. nlohmann: 用户名
  3. json: 仓库
  4. #v3.11.2: tag版本

3. git submodule

cmake demo

如果依赖是cmake项目,不太推荐使用该方法,将该方法封装一个函数。可以参考


# 函数add_git_submodule, 接受一个参数dir
function(add_git_submodule dir)
		# 依赖Git
    find_package(Git REQUIRED)

		# 如果指定文件夹存在,则调用git submodule的方法拉取最新代码
    if (NOT EXISTS ${CMAKE_SOURCE_DIR}/${dir}/CMakeLists.txt)
        execute_process(COMMAND ${GIT_EXECUTABLE}
            submodule update --init --recursive -- ${CMAKE_SOURCE_DIR}/${dir}
            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
    endif()

		# 拉取下来后将项目进行编译
    if (EXISTS ${CMAKE_SOURCE_DIR}/${dir}/CMakeLists.txt)
        message("Adding: ${dir}/CMakeLists.txt")
        add_subdirectory(${CMAKE_SOURCE_DIR}/${dir})
    else()
        message("Could not add: ${dir}/CMakeLists.txt")
    endif()
endfunction(add_git_submodule)
  • 使用方法:
# 设置cmake模块的路径
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
# 引入cmake的模块xx.txt, xx就是模块名字)
include(AddGitSubmodule)

add_git_submodule(external/json)

附加: address_sanitizer 和 undefined sanitizer

option(ENABLE_SANITIZE_ADDR "Enable address sanitizer" ON)
option(ENABLE_SANITIZE_UNDEF "Enable undefined sanitizer" ON)

function(add_sanitizer_flags)
    if (NOT ENABLE_SANITIZE_ADDR AND NOT ENABLE_SANITIZE_UNDEF)
        message(STATUS "Sanitizers deactivated.")
        return()
    endif()

    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
        add_compile_options("-fno-omit-frame-pointer")
        add_link_options("-fno-omit-frame-pointer")

        if(ENABLE_SANITIZE_ADDR)
            add_compile_options("-fsanitize=address")
            add_link_options("-fsanitize=address")
        endif()

        if(ENABLE_SANITIZE_UNDEF)
            add_compile_options("-fsanitize=undefined")
            add_link_options("-fsanitize=undefined")
        endif()
    elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
        if(ENABLE_SANITIZE_ADDR)
            add_compile_options("/fsanitize=address")
        endif()

        if(ENABLE_SANITIZE_UNDEF)
            message(STATUS "Undefined sanitizer not impl. for MSVC!")
        endif()
    else()
        message(STATUS "Sanitizer not supported in this environment!")
    endif()
endfunction(add_sanitizer_flags)

原文地址:https://blog.csdn.net/sexyluna/article/details/134769920

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_37880.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注