[CMake] Multiple installer packages from subsets of one large CMake project?

KSpam keesling_spam at cox.net
Tue Apr 14 13:16:19 EDT 2009


Kerry,

On Tuesday 14 April 2009 06:37:28 Kerry Bonin wrote:
> Short version:  Is there a simple way to generate multiple separate
> installers from within one CMake project?

The short answer is that it is possible, but perhaps it is not "simple".  This 
task does take some digging into CPack, and CPack could benefit from more 
documentation.  It is a wonderful tool despite the shortcomings though!

I am using CPack for packaging many different kinds of installers for a very 
large commercial source base, and my requirements are likely similar to 
yours.  I will try to explain the general idea.

1) You need to create many components.  In my case, I have different 
components for source (i.e. .cpp and .hpp files), library (i.e. .lib files 
and .hpp files), and runtime (i.e. .so or .dll files and .exe files) variants 
of each of my libraries and applications.  To create components, you simply 
need to specify "COMPONENT" for the "INSTALL" commands.

2) You need to create a custom CPack script.  Normally, you will want to name 
this CPackConfig.cmake.  This file will specify the components that you want 
to include in your installer.  You will probably want to create a different 
CPackConfig.cmake file for each installer configuration you want to build.

3) Run cpack.  This will read your CPackConfig.cmake file and generate an 
istaller for it.

In my case, I have a Python script that reads a simple configuration file 
(i.e. the necessary components) for my desired installer and creates the 
appropriate CPackConfig.cmake file.  Then, I run cpack to generate the 
desired installer from the CPackConfig.cmake file.

So the real magic is what's inside the CPackConfig.cmake file.  In my case, I 
set a bunch of CMake variables at the top of the file:

	CPACK_PACKAGE_NAME
	CPACK_PACKAGE_VERSION_MAJOR
	CPACK_PACKAGE_VERSION_MINOR
	CPACK_PACKAGE_VERSION_PATCH
	CPACK_PACKAGE_DESCRIPTION_FILE
	CPACK_RESOURCE_FILE_LICENSE
	CPACK_RESOURCE_FILE_README
	CPACK_RESOURCE_FILE_WELCOME
	CPACK_PACKAGE_VENDOR
	CPACK_PACKAGE_VERSION
	CPACK_PACKAGE_FILE_NAME
	CPACK_PACKAGE_INSTALL_DIRECTORY
	CPACK_PACKAGE_INSTALL_REGISTRY_KEY
	CPACK_GENERATOR

Some of the variables are required, and CPack will error out if you do not set 
them.  This part will probably take a little trial-and-error.  After setting 
the variables, I compose a list of components:

	# Components that I want to include in my installer
	set(myComponentList
		libA-rt # "rt" for runtime
		libB-lib # "lib" includes headers, libraries, and runtime
		exampleApp-src # "src" Source component for an example app
		appC-rt # "rt" for runtime ... just the executable
	)

I also set a variable for the build directory and install prefix:

	# This is used to find the top-level cmake_install.cmake script
	set(myBuildDir
		"/location/to/the/build/directory
	)

	# This is where the files are "staged"
	set(myInstallPrefix
		"_CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}"
	)

Finally, the components are installed by appending an appropriate command to 
CPACK_INSTALL_COMMANDS:

	# Append a command to CPACK_INSTALL_COMMANDS for each component
	foreach (component ${myComponentList
		set(standardArgs "-D CMAKE_INSTALL_COMPONENT=${component}")
		set(standardArgs "${standardArgs} -D CMAKE_INSTALL_DO_STRIP=TRUE")
		set(standardArgs "${standardArgs} -D 
CMAKE_INSTALL_PREFIX=${myInstallPrefix}")
		set(standardArgs "${standardArgs} -P ${myBuildDir}/cmake_install.cmake")

		list(APPEND CPACK_INSTALL_COMMANDS
			"${CMAKE_COMMAND} -D CMAKE_INSTALL_CONFIG_NAME=Release ${standardArgs}"
		)
	endforeach (component)

Hopefully, this will give you enough information to start playing with CPack!

Hope This Helps,
Justin


More information about the CMake mailing list