Is it possible to add post-install commands to top level Makefile generated by CMake?

You can use the SCRIPT or CODE variant of the install command. If you put the required commands in a script PostInstall.cmake in the project root directory, add the following call to your outermost CMakeLists.txt:

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

install commands are added to the cmake_install.cmake script in order, thus the call should be added to the end of the CMakeLists.txt to have it run after all other installations have completed.


To add a post install step, you need to add a directory at the top level CMakeLists.txt. You must have a directory with a CMakeLists.txt in it in order to set up the post install steps to be executed last in the install.

The first step is to add variables and values to be used by the post install script. None of the variables available during the build will be available post install, so everything you need must be set up here.

In the top level CMakeLists.txt, after all previous add_subdirectory commands have been executed, add something like this.

# Workaround for the lack of post_install steps.
# add_subdirectory is executed in order, this one must be last.
if(CMAKE_PROGRAM_PREFIX)
    # Make sure this is the LAST directory added.
    add_subdirectory(${CMAKE_SOURCE_DIR}/cmake/postinstall)
    # Add any variables you need during post install.
    install(CODE "set(CMAKE_PROGRAM_PREFIX \"${CMAKE_PROGRAM_PREFIX}\")")
    # Add any properties to your post install.
    get_property(PROGRAM_PREFIX_FILES GLOBAL PROPERTY PROGRAM_PREFIX_FILES)
    install(CODE "set(PROGRAM_PREFIX_FILES \"${PROGRAM_PREFIX_FILES}\")")
endif()

Now we have variables, and properties converted to variables available to use at post install.

Next we need a CMakeLists.txt file in the postinstall directory. Cmake will execute this file at the end of the build. At that time we install a SCRIPT that does the work during post install.

# CMake will execute this last in the build.
# Install the script that does the post install work.
install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/postinstall/ProgramPrefix.cmake")

Now we will get control during post install in ProgramPrefix.cmake. CMake will add the variables we have set earlier.

# Make sure this was requested.
if(CMAKE_PROGRAM_PREFIX)
    # CMake builds a manifest of all files it has installed.
    foreach(file ${CMAKE_INSTALL_MANIFEST_FILES})
        # Make a list of installed files to compare.
        get_filename_component(nm ${file} NAME)
        list(APPEND fileindex ${nm})
    endforeach()

    # Process program prefix files.
    foreach(nm ${PROGRAM_PREFIX_FILES})
        list(FIND fileindex ${nm} efound)
        # Did we match a manifest file with our list of files?
        if(NOT efound LESS 0)
            # Process the file.
            program_prefix_file(${efound})
        endif()
    endforeach()
endif()

There is a little more work to actually do the program prefix, but this framework will let you execute cmake commands after everything has been installed.

Tags:

Cmake