LidarView超级构建(三):SuperbuildVersionMacros.cmake

该文件在 ${CMAKE_SOURCE_DIR}/pvsb/superbuild/cmake  文件夹中

该文件定义了一系列宏和函数,用于查找指定源码的版本,并定义一系列的关于版本的变量。

find_package(Git)

加载git包

 [宏] _superbuild_set_up

用于定义变量。该变量同时在父作用域及当前作用域可用:

macro (_superbuild_set_up variable value)
  set("${variable}" "${value}"
    PARENT_SCOPE)
  set("${variable}" "${value}")
endmacro ()

[函数] _superbuild_parse_version

使用正则表达式将版本号进行拆分,并分别创建变量存储:完整版本号,主版本号,次版本号,补丁号,额外补丁号。

function (_superbuild_parse_version var version)
  # Split the version number into fields.
  if (version MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
    set(full "${CMAKE_MATCH_0}")
    set(major "${CMAKE_MATCH_1}")
    set(minor "${CMAKE_MATCH_2}")
    set(patch "${CMAKE_MATCH_3}")
    set(patch_extra "${CMAKE_MATCH_4}")
  elseif (version MATCHES "([0-9]+)\\.([0-9]+)-?(.*)")
    set(full "${CMAKE_MATCH_0}")
    set(major "${CMAKE_MATCH_1}")
    set(minor "${CMAKE_MATCH_2}")
    set(patch "")
    set(patch_extra "${CMAKE_MATCH_3}")
  elseif (version MATCHES "([0-9]+)-?(.*)")
    set(full "${CMAKE_MATCH_0}")
    set(major "${CMAKE_MATCH_1}")
    set(minor "")
    set(patch "")
    set(patch_extra "${CMAKE_MATCH_2}")
  else ()
    message(FATAL_ERROR
      "Failed to determine the version for ${var}; got ${version}")
  endif ()

  # Set variables in the parent scope if they're available.
  if (full)
    # 完整版本号
    set("${var}_VERSION" "${major}.${minor}" PARENT_SCOPE)
    # 主版本号
    set("${var}_VERSION_MAJOR" "${major}" PARENT_SCOPE)
    # 次版本号
    set("${var}_VERSION_MINOR" "${minor}" PARENT_SCOPE)
    # 补丁号
    set("${var}_VERSION_PATCH" "${patch}" PARENT_SCOPE)
    # 额外补丁号
    set("${var}_VERSION_PATCH_EXTRA" "${patch_extra}" PARENT_SCOPE)
    # 完整版本号
    set("${var}_VERSION_FULL" "${full}" PARENT_SCOPE)
    if (patch_extra)
      set("${var}_VERSION_IS_RELEASE" FALSE PARENT_SCOPE)
    else ()
      set("${var}_VERSION_IS_RELEASE" TRUE PARENT_SCOPE)
    endif ()
  endif ()
endfunction()

[函数] _superbuild_detect_version_git_remote_tag

下载版本号文件,解析文件中存储的版本号,并创建对应项目的版本号变量

CMAKE_CURRENT_BINARY_DIR:当前正在处理的二进制文件夹。当前正在被处理cmake的build文件夹的全路径。每一个被add_subdirectory()添加的文件都会在构建树中创建一个二进制文件夹,并且将全路径赋值给该变量名。当进行源码内构建时,该变量是当前源码文件夹。

function (_superbuild_detect_version_git_remote_tag var git_repo git_tag default)
  # 将git_tag字符串中的 "origin/" 替换成空字符"",并存储在变量tag中
  string(REPLACE "origin/" "" tag "${git_tag}")
  # 将git_repo字符串中的 ".git" 替换成"/raw/${tag}/version.txt",并存储在version_url中
  string(REPLACE ".git" "/raw/${tag}/version.txt" version_url "${git_repo}")

  # 将version_url下载到本地,将操作结果存储在status变量中。
  file(DOWNLOAD "${version_url}"
    "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${var}Version.txt"
    STATUS status)
  # 状态是一个以分号(;)分割的2个元素的列表
  # 第一个元素是造作的数字返回值,0表示操作过程中无错误
  # 第二个变量是错误的字符串
  # GET为获取status列表中索引为0的值,存储到error_code中
  list(GET status 0 error_code)
 
  if (error_code)
    # error_code 非 0,即下载版本文件出现错误
    if (default STREQUAL "")
      set(error_level FATAL_ERROR)
    else ()
      set(error_level WARNING)
    endif ()
    message("${error_level}" "Could not access the version file for ${var}")
    
    set(output "${default}")
  else()
    # 读取下载的版本号文件
    # 将结果保存在output变量中,该变量是一个列表,每个元素为文件中的一行
    # 二进制文件不会被读取,换行符会被忽略,以'#'注释的内容会被忽略
    file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${var}Version.txt" output)
  endif ()
  # 设置对应代码的版本号变量
  _superbuild_parse_version(parsed "${output}")
  set("${var}_VERSION"             "${parsed_VERSION}" PARENT_SCOPE)
  set("${var}_VERSION_MAJOR"       "${parsed_VERSION_MAJOR}" PARENT_SCOPE)
  set("${var}_VERSION_MINOR"       "${parsed_VERSION_MINOR}" PARENT_SCOPE)
  set("${var}_VERSION_PATCH"       "${parsed_VERSION_PATCH}" PARENT_SCOPE)
  set("${var}_VERSION_PATCH_EXTRA" "${parsed_VERSION_PATCH_EXTRA}" PARENT_SCOPE)
  set("${var}_VERSION_FULL"        "${parsed_VERSION_FULL}" PARENT_SCOPE)
  set("${var}_VERSION_IS_RELEASE"  "${parsed_VERSION_IS_RELEASE}" PARENT_SCOPE)
endfunction ()

[函数]_superbuild_detect_version_git

在源码目录下执行,检查源码的版本号。首先通过git进行查找,如果失败,则在源码中寻找记录版本号的文件。最后将版本号保存在对应的变量中。

function (_superbuild_detect_version_git var source_dir default version_file)
  set(major)
  set(minor)
  set(patch)
  set(full)
  set(patch_extra)
  set(result -1)

  if (GIT_FOUND AND source_dir)
    # 当前工作目录位于存储库目录下方时,打印“true”,否则为“false”。
    execute_process(
      COMMAND         "${GIT_EXECUTABLE}"
                      rev-parse
                      --is-inside-work-tree
      RESULT_VARIABLE result # 最后一个子进程的返回值(正常是0)或描述发生错误的字符串
      OUTPUT_VARIABLE output # 对应于每个进程的返回值,使用分号分隔的列表
      WORKING_DIRECTORY "${source_dir}" # 在该目录下执行COMMAND命令
      ERROR_QUIET # CMake将静默地忽略标准输出和标准错误。
      OUTPUT_STRIP_TRAILING_WHITESPACE) # 可以删除运行命令的标准输出中的任何尾随空 格。

    if (NOT result) # 如果result是0,表示上个命令执行成功,则进入
      # 获取与字符串匹(v*)匹配的tag名称
      execute_process(
        COMMAND         "${GIT_EXECUTABLE}"
                        describe
                        --tags
                        --match=v*
        RESULT_VARIABLE result
        OUTPUT_VARIABLE output
        WORKING_DIRECTORY "${source_dir}"
        ERROR_QUIET
        OUTPUT_STRIP_TRAILING_WHITESPACE)
    endif ()

    # Get branch information (if `describe` worked).
    set(branch "")
    if (NOT result) # 上一步获取tags名称成功
      # name-rev命令能告诉您一个commit相对于最近一次release的位置。
      # 使用这条命令,您就可以检查您所做出的改动是否是release的一部分了
      execute_process(
        COMMAND "${GIT_EXECUTABLE}"
                name-rev
                --name-only
                --no-undefined          # error if these names don't work
                --refs=refs/tags/*      # tags
                --refs=refs/heads/*     # branches
                --refs=refs/pipelines/* # CI
                HEAD
        WORKING_DIRECTORY ${source_dir}
        RESULT_VARIABLE name_rev_result
        OUTPUT_VARIABLE name_rev_output
        ERROR_QUIET
        OUTPUT_STRIP_TRAILING_WHITESPACE
        ERROR_STRIP_TRAILING_WHITESPACE)
      if (NOT name_rev_result)
        set(branch "${name_rev_output}")
      endif ()
    endif ()
  endif ()

  # If `git describe` failed, check for a version file.
  if (result)
    set(version_path "${source_dir}/${version_file}")
    if (source_dir AND version_file AND EXISTS "${version_path}")
      # Read the first line from the version file as the version number.
      file(STRINGS "${version_path}" output
        LIMIT_COUNT 1)
    else ()
      set(output "${default}")
    endif ()
  endif ()

  _superbuild_parse_version(parsed ${output})
  message(STATUS "Determined source version for ${var}: ${parsed_VERSION_FULL}")

  set("${var}_VERSION"             "${parsed_VERSION}" PARENT_SCOPE)
  set("${var}_VERSION_MAJOR"       "${parsed_VERSION_MAJOR}" PARENT_SCOPE)
  set("${var}_VERSION_MINOR"       "${parsed_VERSION_MINOR}" PARENT_SCOPE)
  set("${var}_VERSION_PATCH"       "${parsed_VERSION_PATCH}" PARENT_SCOPE)
  set("${var}_VERSION_PATCH_EXTRA" "${parsed_VERSION_PATCH_EXTRA}" PARENT_SCOPE)
  set("${var}_VERSION_FULL"        "${parsed_VERSION_FULL}" PARENT_SCOPE)
  set("${var}_VERSION_IS_RELEASE"  "${parsed_VERSION_IS_RELEASE}" PARENT_SCOPE)
  if (parsed_VERSION_PATCH_EXTRA)
    set("${var}_VERSION_BRANCH"    "${branch}" PARENT_SCOPE)
  else ()
    set("${var}_VERSION_BRANCH"    "" PARENT_SCOPE)
  endif ()
endfunction ()

[函数]superbuild_set_version_variables

superbuild_set_version_variables( [])

项目的相关版本号信息写到文件中。如果版本无法确定(例如,因为项目将在构建期间克隆),将使用给定的版本。

如果有用于项目的源目录,则“” 将用于获取版本号。如果为空或未提供,则将使用默认值。

以下变量将被创建:

 `_version` (as `.`)

 `_version_major`

 `_version_minor`

 `_version_patch`

 `_version_patch_extra` (e.g., `rc1`)

 `_version_suffix` (equivalent to `-` if `patch_extra` is non-empty)

 `_version_full`

 `_version_is_release` (`TRUE` if the suffix is empty, `FALSE` otherwise)

 `_version_branch` (the "branch" name from Git if available, empty otherwise)

# default: ${project}-version.cmake
# include_file:version.txt
function (superbuild_set_version_variables project default include_file)
  set(source_dir "")
  if ((NOT ${project}_FROM_GIT AND ${project}_FROM_SOURCE_DIR) OR ${project}_SOURCE_SELECTION STREQUAL "source")
    set(source_dir "${${project}_SOURCE_DIR}")
  elseif (${project}_SOURCE_SELECTION STREQUAL "git")
    set(source_dir "${CMAKE_BINARY_DIR}/superbuild/${project}/src")
  endif ()
  # 使用git或者在源码中查找版本号
  # ARGV3表示传入的第4个参数,即
  _superbuild_detect_version_git("${project}" "${source_dir}" "${default}" "${ARGV3}")
  # 创建变量,该变量可以在父作用域和当前作用域可用(cmake变量区分大小写)
  _superbuild_set_up("${project}_version" "${${project}_VERSION}")
  _superbuild_set_up("${project}_version_major" "${${project}_VERSION_MAJOR}")
  _superbuild_set_up("${project}_version_minor" "${${project}_VERSION_MINOR}")
  _superbuild_set_up("${project}_version_patch" "${${project}_VERSION_PATCH}")
  _superbuild_set_up("${project}_version_patch_extra" "${${project}_VERSION_PATCH_EXTRA}")
  if (${project}_version_patch_extra)
    _superbuild_set_up("${project}_version_suffix" "-${${project}_version_patch_extra}")
  else ()
    _superbuild_set_up("${project}_version_suffix" "")
  endif ()
  _superbuild_set_up("${project}_version_full" "${${project}_VERSION_FULL}")
  _superbuild_set_up("${project}_version_is_release" "${${project}_VERSION_IS_RELEASE}")
  _superbuild_set_up("${project}_version_branch" "${${project}_VERSION_BRANCH}")

  if (include_file)
    # 创建空文件
    file(WRITE "${_superbuild_module_gen_dir}/${include_file}" "")
    foreach (variable IN ITEMS "" _major _minor _patch _patch_extra _suffix _full _is_release _branch)
      # 以此将版本信息写入文件
      file(APPEND "${_superbuild_module_gen_dir}/${include_file}"
        "set(\"${project}_version${variable}\" \"${${project}_version${variable}}\")\n")
    endforeach ()
  endif ()
endfunction ()

[函数]superbuild_configure_project_version

配置project的版本号,调用了以上的函数进行设置。

function (superbuild_configure_project_version project)
  set(default_version)
  set(is_git_source_selection OFF)
  # 判断是否需要使用git下载源码
  if (${project}_SOURCE_SELECTION STREQUAL "git")
    set(is_git_source_selection ON)
  elseif (ARGC GREATER 1)
    foreach (arg IN LISTS ARGN)
      if (${project}_SOURCE_SELECTION IN_LIST arg)
        set(is_git_source_selection ON)
      endif ()
    endforeach ()
  endif ()

  if (is_git_source_selection) # 使用git下载源码
    set("${project}_VERSION_DEFAULT" ""
      CACHE STRING "The default version of ${project} to use if it cannot be detected")
    mark_as_advanced("${project}_VERSION_DEFAULT")
    if (${project}_VERSION_DEFAULT STREQUAL "") # 使用git确认版本号
      _superbuild_detect_version_git_remote_tag(${project} "${${project}_GIT_REPOSITORY}" "${${project}_GIT_TAG}" "")
      _superbuild_set_up("${project}_VERSION_DEFAULT" "${${project}_VERSION_MAJOR}.${${project}_VERSION_MINOR}.${${project}_VERSION_PATCH}")
    endif ()
    _superbuild_set_up(default_version "${${project}_VERSION_DEFAULT}")
  elseif (${project}_SOURCE_SELECTION STREQUAL "source")
    set(default_version "")
  else ()
    set(default_version "${${project}_SOURCE_SELECTION}")
  endif()
  superbuild_set_version_variables(${project} "${default_version}" "${project}-version.cmake" "version.txt")
  _superbuild_set_up("${project}_version" "${${project}_version_major}.${${project}_version_minor}")
  _superbuild_set_up("${project}_default_version" "${default_version}")
endfunction()

你可能感兴趣的:(LidarView,c++,自动驾驶,信息可视化)