该文件在 ${CMAKE_SOURCE_DIR}/pvsb/superbuild/cmake 文件夹中
该文件定义了一系列宏和函数,用于查找指定源码的版本,并定义一系列的关于版本的变量。
find_package(Git)
加载git包
用于定义变量。该变量同时在父作用域及当前作用域可用:
macro (_superbuild_set_up variable value)
set("${variable}" "${value}"
PARENT_SCOPE)
set("${variable}" "${value}")
endmacro ()
使用正则表达式将版本号进行拆分,并分别创建变量存储:完整版本号,主版本号,次版本号,补丁号,额外补丁号。
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()
下载版本号文件,解析文件中存储的版本号,并创建对应项目的版本号变量
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 ()
在源码目录下执行,检查源码的版本号。首先通过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(
对
如果有用于项目的源目录,则“
以下变量将被创建:
`
`
`
`
`
`
`
`
`
# 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 ()
配置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()