在CMake项目中,我使用git标签作为版本号。使用https://github.com/iPenguin/version_git的方法,我可以将版本号放入源代码中(也就是说,CMake创建一个带有const字符串的version.cpp文件,该字符串包含我可以在C ++源代码中使用的版本号码)。问题是,当我使用CPack创建源包时,我排除了.git目录,并且在编译从包中提取的源时,版本号不可用。
如何让CPack将版本号放入源包中?
我有以下要求:
我不希望构建目录包含在我的源包中。值得注意的是,我从项目根目录下的目录中进行了源外构建。也就是说,如果我的顶级CMakeLists.txt在目录my_project中,那么我运行" cmake .."和"制作"在目录my_project / build。
我不想在我的源包中包含.git目录。
我想要cmake生成的所有文件和#34; make package_source"在build目录中。另外,我不希望cmake修改或删除构建目录之外的任何文件。
我不想使用cmake和cpack的未记录行为,特别是cpack使用的路径。
到目前为止,我无法找到满足我所有要求的解决方案。以下是我的尝试:
我让cmake创建一个文件versionForSourcePackage.cmake,当后来由cmake包含时,它将设置VERSION变量。然后我想把这个文件放到源包中,这样当在提取的包中运行cmake时,它将设置VERSION变量。此文件是在build目录下创建的,但我不知道如何正确地让CPack将它复制到源包中。
第一种可能性是https://github.com/iPenguin/version_git的略微修改,但它不符合我的要求编号4.完整示例位于https://github.com/josefcibulka/version_git。
从存储库构建时,我从git获取版本号并将其保存在$ {PROJECT_BINARY_DIR} /versionForSourcePackage.cmake中。然后我使用CPACK_INSTALL_COMMANDS让CPack将此文件复制到$ {PROJECT_BINARY_DIR} / _ CPack_Packages / Linux-Source / $ {CPACK_SOURCE_GENERATOR} / $ {CPACK_SOURCE_PACKAGE_FILE_NAME} /,以便它包含在包中。这违反了第4号要求,而且,如果我想在将来创建TGZ和ZIP包,我需要做一些更改。是否有一些我可以在CPACK_INSTALL_COMMANDS中使用的变量来获取CPack正在准备包内容的目录的路径?
CMakeLists.txt看起来像:
cmake_minimum_required(VERSION 2.8)
project("version_from_git")
# Appends the cmake/modules path to MAKE_MODULE_PATH variable.
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
# When in the extracted package, use the previously generated file, otherwise get the current version from git.
if(EXISTS "${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake")
include("${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake")
else()
include(GetGitRevisionDescription)
git_describe(VERSION --tags --dirty=-dirty)
endif()
# Parse the version information into pieces.
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}")
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+(.*)" "\\1" VERSION_SHA1 "${VERSION}")
set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}")
# The following will copy the version file to the source package.
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_SHORT}-Source")
set(CPACK_INSTALL_COMMANDS "${CMAKE_COMMAND} -E make_directory \
${PROJECT_BINARY_DIR}/_CPack_Packages/Linux-Source/${CPACK_SOURCE_GENERATOR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}/"
"${CMAKE_COMMAND} -E copy \
${PROJECT_BINARY_DIR}/versionForSourcePackage.cmake \
${PROJECT_BINARY_DIR}/_CPack_Packages/Linux-Source/${CPACK_SOURCE_GENERATOR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}/")
# Exclude the build and .git directory from the source package.
set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_SOURCE_DIR}/.git/;${PROJECT_BINARY_DIR}/;${CPACK_SOURCE_IGNORE_FILES}")
include (CPack)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/version.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/version.cpp)
# Prepare the versionForSourcePackage.cmake file that will be included in the source package.
configure_file(
${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake.in
${PROJECT_BINARY_DIR}/versionForSourcePackage.cmake @ONLY)
set(version_file "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
set(source_files "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp")
#Add the version_file to the project build.
add_executable(${PROJECT_NAME} ${source_files} ${version_file})
文件versionForSourcePackage.cmake.in:
set(VERSION "v@VERSION_SHORT@")
第二种可能性是https://github.com/lcw/cmake_git_version使用的方法。完整示例位于https://github.com/josefcibulka/version_git中的second_possibility分支中。文件versionForSourcePackage.cmake放置在构建目录的子目录version_file中,此目录添加到CPACK_SOURCE_INSTALLED_DIRECTORIES中。当项目和构建目录处于同一级别时,这很有效。 问题是如果构建目录在项目目录下,我将构建目录添加到CPACK_SOURCE_IGNORE_FILES以满足要求1.然后,即使我将CPACK_SOURCE_INSTALLED_DIRECTORIES设置为包含version_file目录,它也将被忽略。可以这样做,我只忽略build目录中除version_file目录之外的所有内容。然后源包中的build目录只包含version_file目录,该目录优于整个构建目录,但仍然不完美。
更新:似乎也不满足要求4,因为我在the CMake documentation中找不到CPACK_SOURCE_INSTALLED_DIRECTORIES。
与第一种可能性的区别在于CMakeLists.txt:
# The following will transfer the version from git to the source package.
set(CPACK_SOURCE_INSTALLED_DIRECTORIES "${PROJECT_SOURCE_DIR};/;${PROJECT_BINARY_DIR}/version_file;/")
# Exclude the build and .git directory from the source package.
set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_SOURCE_DIR}/.git/;${PROJECT_BINARY_DIR}/([^v].*|v[^e].*|ve[^r].*|ver[^s].*|vers[^i].*|vers[^i].*|versi[^o].*|versio[^n].*|version[^_].*|version_[^f].*|version_f[^i].*|version_fi[^l].*|version_fil[^e].*);${CPACK_SOURCE_IGNORE_FILES}")
include (CPack)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/version.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/version.cpp)
configure_file(
${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake.in
${PROJECT_BINARY_DIR}/version_file/versionForSourcePackage.cmake @ONLY)
答案 0 :(得分:0)
最后,我正在使用第一种可能性的修改,但问题只能部分解决。
我使用 CPACK_INSTALL_SCRIPT 和CMake脚本代替 CPACK_INSTALL_COMMANDS 。对于正在创建的每个包都执行此脚本,并且好处是在此脚本内部, CMAKE_CURRENT_BINARY_DIR 指向正在收集包的内容的目录。也就是说,无论我复制到该目录,都会进入包内。
然而,这看起来是 CMAKE_CURRENT_BINARY_DIR 的未记录行为。例如,在CPack执行的CMake脚本中使用时, CMAKE_BINARY_DIR 和 PROJECT_BINARY_DIR 为空。因此,在其他版本的CMake中,当由CPack执行时, CMAKE_CURRENT_BINARY_DIR 也将为空。
另一个问题是我确实希望将版本文件仅复制到源包而不是二进制包。我如何区分的是,如果 CMAKE_CURRENT_BINARY_DIR 以" Source"结尾,我假设脚本在准备源包期间正在运行。
完整示例位于https://github.com/josefcibulka/version_git的 using_cpack_install_script 分支中。 CMakeLists.txt的更改部分:
# The following will transfer the version from git to the source package.
set(CPACK_INSTALL_SCRIPT "${CMAKE_BINARY_DIR}/versionNumberToPackage.cmake")
configure_file(${CMAKE_SOURCE_DIR}/versionNumberToPackage.cmake.in
${CMAKE_BINARY_DIR}/versionNumberToPackage.cmake @ONLY)
versionNumberToPackage.cmake.in的内容是:
# Copies VersionForSourcePackage.cmake to the source package (it should not be copied to binary package).
# Detection if this is the source package is that the path ends with "Source" and an optional slash.
if("${CMAKE_CURRENT_BINARY_DIR}" MATCHES "Source/?$")
file(COPY @CMAKE_BINARY_DIR@/versionForSourcePackage.cmake DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
endif()