Rename the output of CPack
Asked Answered
N

3

8

I would like to rename the installer file that CPack (v2.8.7) produces to include a version number that is obtained at build time from the version control system. It appears this cannot be be done by setting the CPACK_* variables because that happens at "cmake" time.

What I want to be able to do is to run "(n)make package" and have the installer file be created with no further commands required. The two possible approaches that I am aware of are manipulating the CPack filename variables at build time and renaming the final output of CPack.

If using "include(CPack)" in a CMakeLists.txt file then it appears that CPack always runs last and you can't have a post-build command. This mailing list message suggests that a custom target can be written to run CPack, but I was unable to figure out how to do that without creating infinite recursion.

How can this be done?

Needlefish answered 8/3, 2012 at 4:48 Comment(0)
N
5

With a bit of help from the CMake mailing list I figured out how to do it, using subversion.

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(myapp)

add_executable(main main.cpp)
install(TARGETS main DESTINATION .)

add_custom_target(first ALL
    # update the working copy
    COMMAND ${Subversion_SVN_EXECUTABLE} update ${CMAKE_SOURCE_DIR}

    # generate cpackoptions.cmake at build time so we get the
    # most recent revision number
    COMMAND ${CMAKE_COMMAND}
    -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
    -DBINARY_DIR=${CMAKE_BINARY_DIR}
    -Dproj_name=${CMAKE_PROJECT_NAME}
    -P ${CMAKE_SOURCE_DIR}/create-cpackoptions.cmake
    )

add_dependencies(main first)

set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackOptions.cmake)

include(CPack)

create-cpackoptions.cmake

include(FindSubversion)
Subversion_WC_INFO(${SOURCE_DIR} ${proj_name})

set(revision ${${proj_name}_WC_REVISION})

configure_file(${SOURCE_DIR}/CPackOptions.cmake.in
    ${BINARY_DIR}/CPackOptions.cmake
    @ONLY)

cpackOptions.cmake.in

set(CPACK_PACKAGE_FILE_NAME "@proj_name@-${CPACK_PACKAGE_VERSION}r@revision@-${CPACK_SYSTEM_NAME}")
Needlefish answered 9/3, 2012 at 1:39 Comment(1)
You could go one step further and generate the CPackOptions.cmake.in and the create-cpackoptions.cmake from the CMakeFile.txt. This means that you don't need two files in your source tree. For example: file(WRITE ${CMAKE_BINARY_DIR}/CPackOptions.cmake.in "set(CPACK_PACKAGE_FILE_NAME \"@proj_name@-\${CPACK_PACKAGE_VERSION}r@revision@-\${CPACK_SYSTEM_NAME}\")")Septuagesima
G
5

Why not extract the build-info from the VCS at cmake-time? Then you can easily modify the CPACK_PACKAGE_FILE_NAME to include your version-number.

Added bonus: When doing this at CMake-time, you can e.g. fill a "Readme.txt" file with the git-info using CMake's configure_file and add it to your package. Or perhaps use it to fill a "config.h", which is used in your builds.

Example: in one of my own projects, I have a little piece of CMake code which finds Git and extracts the current changeset hash from the source code repository. It may not be the best Git way of extracting the info, but it works for me...

# First try to find the git-executable
find_program( Git_EXECUTABLE NAMES git git.cmd PATHS
    ${Git_DIR}
    ENV PATHS
    $ENV{Git_DIR}
)
# Run "git log -n 1 --pretty="%h" for the current commit-hash
execute_process( COMMAND ${Git_EXECUTABLE} "log" "-n" "1" "--pretty=\"%h\"" 
                 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 
                 OUTPUT_VARIABLE Git_Commit_Hash 
                 OUTPUT_STRIP_TRAILING_WHITESPACE
                 )
# and use a regex to strip quotes.
string( REGEX REPLACE "^\"(.*)\"$" "\\1" Git_Commit_Hash ${Git_Commit_Hash} )

The result will be a Git_Commit_Hash variable with the 7-char hash value, which is used when setting up CPack:

set( CPACK_PACKAGE_NAME "MyProject" )
message( STATUS "    CPack options: " ${CPACK_PACKAGE_NAME} )
message( STATUS "    Preparing CPACK: " )
message( STATUS "      and hash: ${Git_Commit_Hash}" )

set( CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${Git_Build_Version}_${CPACK_PACKAGE_VERSION}" )
Grisons answered 8/3, 2012 at 12:45 Comment(4)
I really needed it to be at build time rather than cmake time, but thanks for your answer anyway.Needlefish
I was afraid you would say that... the altenative then is to run a custom command at build time which does this for you.Gebhardt
It's not that simple. You can't override CPACK_PACKAGE_FILE_NAME at build time because CPack reads it from a config file. You have to set CPACK_PROJECT_CONFIG_FILE to a file that is generated at build time. This is what the code in my answer does.Needlefish
Agreed, you should prepare a "custom cmake" script like in your own answer (upvoted...). In case anyone is interested in a cmake-time solution, I will leave this answer up.Gebhardt
N
5

With a bit of help from the CMake mailing list I figured out how to do it, using subversion.

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(myapp)

add_executable(main main.cpp)
install(TARGETS main DESTINATION .)

add_custom_target(first ALL
    # update the working copy
    COMMAND ${Subversion_SVN_EXECUTABLE} update ${CMAKE_SOURCE_DIR}

    # generate cpackoptions.cmake at build time so we get the
    # most recent revision number
    COMMAND ${CMAKE_COMMAND}
    -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
    -DBINARY_DIR=${CMAKE_BINARY_DIR}
    -Dproj_name=${CMAKE_PROJECT_NAME}
    -P ${CMAKE_SOURCE_DIR}/create-cpackoptions.cmake
    )

add_dependencies(main first)

set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackOptions.cmake)

include(CPack)

create-cpackoptions.cmake

include(FindSubversion)
Subversion_WC_INFO(${SOURCE_DIR} ${proj_name})

set(revision ${${proj_name}_WC_REVISION})

configure_file(${SOURCE_DIR}/CPackOptions.cmake.in
    ${BINARY_DIR}/CPackOptions.cmake
    @ONLY)

cpackOptions.cmake.in

set(CPACK_PACKAGE_FILE_NAME "@proj_name@-${CPACK_PACKAGE_VERSION}r@revision@-${CPACK_SYSTEM_NAME}")
Needlefish answered 9/3, 2012 at 1:39 Comment(1)
You could go one step further and generate the CPackOptions.cmake.in and the create-cpackoptions.cmake from the CMakeFile.txt. This means that you don't need two files in your source tree. For example: file(WRITE ${CMAKE_BINARY_DIR}/CPackOptions.cmake.in "set(CPACK_PACKAGE_FILE_NAME \"@proj_name@-\${CPACK_PACKAGE_VERSION}r@revision@-\${CPACK_SYSTEM_NAME}\")")Septuagesima
B
0

This is an old question, but I faced a similar problem recently. Based on the documentation, CPack will rerun the CPackOption file before packaging each package built.

From that, you can simply set the CPackOption file in your CMakeLists.txt.

set(CPACK_PROJECT_CONFIG_FILE ${PROJECT_SOURCE_DIR}/CPackOptions.cmake)

And in your CPackOptions.cmake you can execute a process to find the version and rename the package.

execute_process(
    COMMAND get_my_version_from_VCS
    OUTPUT_VARIABLE CPACK_PACKAGE_VERSION
)

# optionally rename the file if you need or do stuff
set(CPACK_PACKAGE_FILE_NAME "blabla-${CPACK_PACKAGE_VERSION}")

Read the defaults for CPack variables before changing them, to reduce the lines to maintain.

Bb answered 13/9, 2024 at 14:41 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.