Git 子模组(Submodule)

如果你想要添加一个 Git 仓库,它与你的项目仓库使用相同的 Git 托管服务(诸如 GitHub、GitLab、BitBucker 等等),下面是正确的添加一个子模组到 extern 目录中的命令:

gitbook $ git submodule add ../../owner/repo.git extern/repo

此处的关键是使用相对于你的项目仓库的相对路径,它可以保证你使用与主仓库相同的访问方式( ssh 或 https )访问子模组。这在大多数情况都能工作得相当好。当你在一个子模组里的时候,你可以把它看作一个正常的仓库,而当你在主仓库里时,你可以用 add 来改变当前的提交指针。

但缺点是你的用户必须懂 git submodule 命令,这样他们才可以 initupdate 仓库,或者他们可以在最开始克隆你的仓库的时候加上 --recursive 选项。针对这种情况,CMake 提供了一种解决方案:

find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
# Update submodules as needed
    option(GIT_SUBMODULE "Check submodules during build" ON)
    if(GIT_SUBMODULE)
        message(STATUS "Submodule update")
        execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
                        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                        RESULT_VARIABLE GIT_SUBMOD_RESULT)
        if(NOT GIT_SUBMOD_RESULT EQUAL "0")
            message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
        endif()
    endif()
endif()

if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/repo/CMakeLists.txt")
    message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.")
endif()

第一行使用 CMake 自带的 FindGit.cmake 检测是否安装了 Git 。然后,如果项目源目录是一个 git 仓库,则添加一个选项(默认值为 ON),用户可以自行决定是否打开这个功能。然后我们运行命令来获取所有需要的仓库,如果该命令出错了,则 CMake 配置失败,同时会有一份很好的报错信息。最后无论我们以什么方式获取了子模组,CMake 都会检查仓库是否已经被拉取到本地。你也可以使用 OR 来列举其中的几个。

现在,你的用户可以完全忽视子模组的存在了,而你同时可以拥有良好的开发体验!唯一需要开发者注意的一点是,如果你正在子模组里开发,你会在重新运行 CMake 的时候重置你的子模组。只需要添加一个新的提交到主仓库的暂存区,就可以避免这个问题。

然后你就可以添加对 CMake 有良好支持的项目了:

add_subdirectory(extern/repo)

或者,如果这是一个只有头文件的库,你可以创建一个接口库目标 (interface library target) 。或者,如果支持的话,你可以使用find_package,可能初始的搜索目录就是你所添加的目录(查看文档或你所使用的Find*.cmake文件)。如果你追加到你的CMAKE_MODULE_PATH,你也可以包括一个CMake帮助文件目录,例如添加pybind11改进过的FindPython*.cmake文件。

小贴士:获取 Git 版本号

将下面的命令加入到上述 Git 更新子仓库的那段中:

execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
                WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                OUTPUT_VARIABLE PACKAGE_GIT_VERSION
                ERROR_QUIET
                OUTPUT_STRIP_TRAILING_WHITESPACE)

results matching ""

    No results matching ""