Search code examples
cmakearchivecpack

How to specify different folder structure for CPack TGZ generator?


I have a CMake project that installs things to a system according to the install command as follows:

install (
    TARGETS myTarget
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
)

make install works perfectly. And then I want to have a binary archive:

set(CPACK_GENERATOR "TGZ")

make package produces an tar.gz file with the same folder structure as the install command specified. However, I want to have a flat structure, that is, put everything (both executables and libraries) in "prefix", without the "bin" and "lib" directory.

Is that possible? May be with some clever use of the component system, the build type system, or CPACK_PROJECT_CONFIG_FILE?


Solution

  • At the end I added a custom install script, which detects whether it is run by CPack by looking at CMAKE_INSTALL_PREFIX, and restructure the install tree if necessary.

    Here is my solution:

    In CMakeLists.txt, after all the install() commands, add

    install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/flatten.cmake")
    

    Add a file, "cmake/flatten.cmake", with content as follows

    # Detect if the install is run by CPack.
    if (${CMAKE_INSTALL_PREFIX} MATCHES "/_CPack_Packages/.*/(TGZ|ZIP)/")
        # Flatten the directory structure such that everything except the header files is placed in root.
        file(GLOB bin_files LIST_DIRECTORIES FALSE ${CMAKE_INSTALL_PREFIX}/bin/*)
        file(GLOB lib_files LIST_DIRECTORIES FALSE ${CMAKE_INSTALL_PREFIX}/lib/*)
        foreach(file ${bin_files} ${lib_files})
            get_filename_component(file_name ${file} NAME)
            execute_process(
                COMMAND ${CMAKE_COMMAND} -E rename
                ${file}
                ${CMAKE_INSTALL_PREFIX}/${file_name}
            )
        endforeach()
        execute_process( COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/bin)
        execute_process( COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/lib)
    endif()