[CMake] Multi-component packaging support

Timenkov Yuri ytimenkov at parallels.com
Fri Mar 21 06:08:02 EDT 2008


I have following requirement: I have big source tree (~100 projects - 
libraries or binaries), and want to package them in different ways. And 
encapsulate packaging knowledge in single place.

That is I want that some libraries may enter into different packages. That is 
pakcageA contains libA and libB, packageA-devel contains libA-static and 
libB-static and libA-headers, packageB contains libB and libX, and so on.

Obviously, I can't specify it in install command, because when I write 
CMakeLists.txt for some library, I don't know which package it will belong 
to.

Other words, I want somewhere in top-level makefile to write something like
add_install_package(packageA libA libB)
add_install_package(packageA-devel libA-static libB-static libA-headers)
add_install_package(packageB libB libX)

and later, to install particular package, I should call something like
make install_package_packageA

Also, it will be very helpfull to have some kind of install manifest for whole 
package. It will simplify packaging on different platforms (wither with or 
without CPack). For example, you can tell rpmbuild to get file list form text 
file rather than specifying them in .spec. Same way I can wrap other 
packaging tools on windows.

Now, I came to following solution: put every library into separate component 
with same name: install(TARGETS libA COMPONENT libA)
Next, add custom target:
        add_custom_target(install_packageA
                COMMAND ${CMAKE_COMMAND}
                -DINSTALL_PACKAGE_NAME:STRING="packageA"
                -DINSTALL_COMPONENTS:STRING="libA libB"
                -H${CMAKE_SOURCE_DIR}
                -B${CMAKE_BINARY_DIR}
                -P ${CMAKE_SOURCE_DIR}/build/InstallHelper.cmake
                COMMENT "Installing package packageA"
                WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        )
where InstallHelper.cmake is:

# Convert space-separated string into list.
separate_arguments(INSTALL_COMPONENTS)

# Install components
foreach(component ${INSTALL_COMPONENTS})
        # Set component
        set(CMAKE_INSTALL_COMPONENT ${component})

        message(STATUS "Processing component ${CMAKE_INSTALL_COMPONENT}")

        # Run install script with active component
        include(${CMAKE_BINARY_DIR}/cmake_install.cmake)
endforeach(component)

set(_manifest_file 
${CMAKE_BINARY_DIR}/install_manifest_${INSTALL_PACKAGE_NAME}.txt)

# Truncate output manifest file.
file(WRITE ${_manifest_file} "")

# Append installed files to manifest.
foreach(file ${CMAKE_INSTALL_MANIFEST_FILES})
        file(APPEND ${_manifest_file} "${file}\n")
endforeach(file)

Is there more straight-forward way to do same things? Possibly, with CPack, 
but I don't completely understand one's architecture yet.


More information about the CMake mailing list