It provides several advantages.
- CPack generate new project in Visual Studio dependent from all others and building it we create installer on one click
- installer often depends on .h files (.api) or .lib files (api) or .dll (exec) which are changed in CMake by developers during building project. In all these cases installer assembles all needed component.
- cross-platform solution
As usual we need do standard steps but also encounter several problems.
Standard steps:
- install targets with COMPONENT parameter target belongs to
- if you have msvc project
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
include(InstallRequiredSystemLibraries)
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
DESTINATION bin/dll/Msvc
COMPONENT Driver)
- provide all needed dlls, i.e.
set(BoostDllDIR ${Boost_LIBRARY_DIR_RELEASE})
file(GLOB BoostDllList "${BoostDllDIR}/*.dll")
install(FILES ${BoostDllList}
DESTINATION bin/dll/Boost
COMPONENT Driver)
- provide msi installers your app depends on, i.e.
install(PROGRAMS DependencyInstall/Bonjour64.msi
DESTINATION DependencyInstall
COMPONENT Driver)
- provide exe installers your app depends on, i.e. (if your project is from msvc, do exactly this)
install(PROGRAMS DependencyInstall/vcredist_x64.exe
DESTINATION DependencyInstall
COMPONENT Driver)
- copy whole directories
set(DATA_FILE_DIR D:/data)
install(DIRECTORY ${DATA_FILE_DIR}/
DESTINATION data
COMPONENT Driver)
- set standard CPack variables
CPACK_PACKAGE_NAME
CPACK_PACKAGE_VENDOR
CPACK_PACKAGE_DESCRIPTION_SUMMARY
CPACK_PACKAGE_VERSION_MAJOR
CPACK_PACKAGE_VERSION_MINOR
CPACK_PACKAGE_VERSION_PATCH
CPACK_PACKAGE_VERSION
CPACK_PACKAGE_INSTALL_DIRECTORY
CPACK_COMPONENTS_ALL
CPACK_COMPONENT_???_DISPLAY_NAME
CPACK_COMPONENT_???_DESCRIPTION
CPACK_COMPONENT_???_DEPENDS
CPACK_COMPONENT_???_GROUP
CPACK_COMPONENT_GROUP_???_DISPLAY_NAME
CPACK_COMPONENT_GROUP_???_DESCRIPTION
CPACK_RESOURCE_FILE_LICENSE
CPACK_PACKAGE_ICON #use \\\\ where / or \ should be
CPACK_NSIS_MUI_ICON
CPACK_NSIS_MUI_UNIICON
CPACK_NSIS_MENU_LINKS
Nonstandard steps:
Not all steps you could wish are possible in CPack, but you can directly inject NSIS code. There are two lists of commands:
CPACK_NSIS_EXTRA_INSTALL_COMMANDS used in installation
CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS used in uninstallation
Main problem is how to escape strings to be parsed right. Follow the examples.
- execute 3rdParty .exe installers
list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
ExecWait '$INSTDIR\\\\DependencyInstall\\\\vcredist_x64.exe /quiet /norestart'
")
- execute 3rdParty .msi installers. There is problem (at least on my machine) to run msi installer if installation dir is protected, like Program Files. Workaround is to run it from unprotected folder like AppData/Local
list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
CopyFiles '$INSTDIR\\\\DependencyInstall\\\\Bonjour64.msi' '$LOCALAPPDATA\\\\MyProgramName\\\\Bonjour64.msi'
")
list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
ExecWait 'msiexec /quiet /qn /norestart /i $LOCALAPPDATA\\\\MyProgramName\\\\Bonjour64.msi'
")
- set entries in Windows Registry (why? check my another post about dlls and exe) and after uninstallation remove them (we filled variable ${WindowsRegistryPath} in CMake with proper string)
set(DllInstallationPrefix "$INSTDIR/bin/dll")
set(WindowsRegistryPath "")
set(WindowsRegistryPath "${WindowsRegistryPath}${DllInstallationPrefix}/Msvc;")
set(WindowsRegistryPath "${WindowsRegistryPath}${DllInstallationPrefix}/Boost;")
list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
WriteRegStr HKLM 'SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths\\\\MyProgram.exe' '' '$INSTDIR/bin/MyProgramExe.exe'
WriteRegStr HKLM 'SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths\\\\MyProgram.exe' 'Path' '${WindowsRegistryPath}'")
list(APPEND CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
DeleteRegKey HKLM 'SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths\\\\MyProgram.exe'")
No comments:
Post a Comment