summaryrefslogtreecommitdiffstats
path: root/cmake/cpack/CPackConfigDEB.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/cpack/CPackConfigDEB.cmake')
-rw-r--r--cmake/cpack/CPackConfigDEB.cmake349
1 files changed, 349 insertions, 0 deletions
diff --git a/cmake/cpack/CPackConfigDEB.cmake b/cmake/cpack/CPackConfigDEB.cmake
new file mode 100644
index 0000000..9aa687d
--- /dev/null
+++ b/cmake/cpack/CPackConfigDEB.cmake
@@ -0,0 +1,349 @@
+# include Macros.cmake to automate generation of time/date stamps, maintainer, etc.
+include(${CMAKE_SOURCE_DIR}/cmake/scripts/common/Macros.cmake)
+
+# find stuff we need
+find_program(LSB_RELEASE_CMD lsb_release)
+find_program(DPKG_CMD dpkg)
+find_package(Git)
+find_program(GZIP_CMD gzip)
+
+# set packaging dir
+if(NOT CPACK_PACKAGE_DIRECTORY)
+ set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages)
+endif()
+
+# force CPack generated DEBs to use the same path as CMAKE_INSTALL_PREFIX
+set(CPACK_SET_DESTDIR true)
+
+# set architecture
+if(NOT CPACK_SYSTEM_NAME)
+ set(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_PROCESSOR})
+ # sanity check
+ if(CPACK_SYSTEM_NAME STREQUAL x86_64)
+ set(CPACK_SYSTEM_NAME amd64)
+ endif()
+endif()
+
+# set packaging by components
+set(CPACK_DEB_COMPONENT_INSTALL ON)
+
+# enforce Debian policy permission rules
+set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION ON)
+
+# packaging by components doesn't fully work with CMake/CPack <3.6.0
+# CPACK_DEBIAN_<COMPONENT>_FILE_NAME is a 3.6.0 addition
+# warn if detected version is lower
+if(CMAKE_VERSION VERSION_LESS 3.6)
+ message(WARNING "DEB Generator: CMake/CPack 3.6 or higher is needed to produce correctly named packages.")
+endif()
+
+# distro codename
+if(NOT DISTRO_CODENAME)
+ if(NOT LSB_RELEASE_CMD)
+ message(WARNING "DEB Generator: Can't find lsb_release in your path. Setting DISTRO_CODENAME to unknown.")
+ set(DISTRO_CODENAME unknown)
+ else()
+ execute_process(COMMAND ${LSB_RELEASE_CMD} -cs
+ OUTPUT_VARIABLE DISTRO_CODENAME
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ endif()
+endif()
+
+# package version
+if(DEBIAN_PACKAGE_VERSION)
+ set(DISTRO_CODENAME ${DEBIAN_PACKAGE_VERSION}${DISTRO_CODENAME})
+else()
+ set(DISTRO_CODENAME 0${DISTRO_CODENAME})
+endif()
+
+# package revision
+if(DEBIAN_PACKAGE_REVISION)
+ set(DISTRO_CODENAME ${DISTRO_CODENAME}${DEBIAN_PACKAGE_REVISION})
+endif()
+
+# package type
+if(DEBIAN_PACKAGE_TYPE STREQUAL stable)
+ set(RELEASE_IDENTIFIER final)
+elseif(DEBIAN_PACKAGE_TYPE STREQUAL unstable)
+ set(RELEASE_IDENTIFIER ${APP_VERSION_TAG_LC})
+else()
+ core_find_git_rev(RELEASE_IDENTIFIER)
+endif()
+
+# package name
+string(TIMESTAMP PACKAGE_TIMESTAMP "%Y%m%d.%H%M" UTC)
+set(PACKAGE_NAME_VERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}~git${PACKAGE_TIMESTAMP}-${RELEASE_IDENTIFIER}-${DISTRO_CODENAME})
+
+# package version
+if(DEBIAN_PACKAGE_EPOCH)
+ set(CPACK_DEBIAN_PACKAGE_VERSION ${DEBIAN_PACKAGE_EPOCH}:${PACKAGE_NAME_VERSION})
+else()
+ set(CPACK_DEBIAN_PACKAGE_VERSION 2:${PACKAGE_NAME_VERSION})
+endif()
+
+# architecture
+if(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
+ if(NOT DPKG_CMD)
+ message(WARNING "DEB Generator: Can't find dpkg in your path. Setting CPACK_DEBIAN_PACKAGE_ARCHITECTURE to i386.")
+ set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
+ endif()
+ execute_process(COMMAND "${DPKG_CMD}" --print-architecture
+ OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif()
+
+# package maintainer
+if(NOT CPACK_DEBIAN_PACKAGE_MAINTAINER)
+ userstamp()
+ set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${PACKAGE_MAINTAINER})
+ unset(PACKAGE_MAINTAINER)
+endif()
+
+# package description common to all packages
+if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION)
+ file(STRINGS ${CMAKE_SOURCE_DIR}/cmake/cpack/deb/package-description.txt DESC_LINES)
+ foreach(LINE IN LISTS DESC_LINES)
+ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_DEBIAN_PACKAGE_DESCRIPTION} ${LINE}\n")
+ endforeach()
+endif()
+
+# package homepage
+if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE)
+ set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${APP_WEBSITE})
+endif()
+
+# generate a Debian compliant changelog
+set(CHANGELOG_HEADER "${APP_NAME_LC} (${CPACK_DEBIAN_PACKAGE_VERSION}) ${DISTRO_CODENAME}\; urgency=high")
+rfc2822stamp()
+# two spaces between maintainer and timestamp is NOT a mistake
+set(CHANGELOG_FOOTER " -- ${CPACK_DEBIAN_PACKAGE_MAINTAINER} ${RFC2822_TIMESTAMP}")
+
+if(GIT_FOUND AND GZIP_CMD AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
+ execute_process(COMMAND ${GIT_EXECUTABLE} log --no-merges --pretty=format:"%n [%an]%n * %s" --since="30 days ago"
+ OUTPUT_VARIABLE CHANGELOG
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ string(REPLACE "\"" "" CHANGELOG ${CHANGELOG})
+ file(WRITE ${CPACK_PACKAGE_DIRECTORY}/deb/changelog.Debian ${CHANGELOG_HEADER}\n${CHANGELOG}\n\n${CHANGELOG_FOOTER})
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/changelog.Debian)
+ unset(CHANGELOG_HEADER)
+ unset(CHANGELOG_FOOTER)
+ unset(RFC2822_TIMESTAMP)
+else()
+ message(WARNING "DEB Generator: Can't find git and/or gzip in your path. DEB packages will be missing changelog.Debian.gz.")
+endif()
+
+# Generate NEWS.Debian
+configure_file(${CMAKE_SOURCE_DIR}/cmake/cpack/deb/NEWS.Debian
+ ${CPACK_PACKAGE_DIRECTORY}/deb/NEWS.Debian @ONLY)
+if(GZIP_CMD)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/NEWS.Debian)
+else()
+ message(WARNING "DEB Generator: Can't find gzip in your path. DEB packages will be missing NEWS.Debian.")
+endif()
+
+# Generate man pages
+configure_file(${CMAKE_SOURCE_DIR}/docs/manpages/kodi.bin.1
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.1 COPYONLY)
+configure_file(${CMAKE_SOURCE_DIR}/docs/manpages/kodi.bin.1
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.bin.1 COPYONLY)
+configure_file(${CMAKE_SOURCE_DIR}/docs/manpages/kodi-standalone.1
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-standalone.1 COPYONLY)
+if(ENABLE_EVENTCLIENTS)
+ configure_file(${CMAKE_SOURCE_DIR}/docs/manpages/kodi-ps3remote.1
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-ps3remote.1 COPYONLY)
+ configure_file(${CMAKE_SOURCE_DIR}/docs/manpages/kodi-send.1
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-send.1 COPYONLY)
+ configure_file(${CMAKE_SOURCE_DIR}/docs/manpages/kodi-wiiremote.1
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-wiiremote.1 COPYONLY)
+endif()
+
+if(GZIP_CMD)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.1)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.bin.1)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-standalone.1)
+ if(ENABLE_EVENTCLIENTS)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-ps3remote.1)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-send.1)
+ execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-wiiremote.1)
+ endif()
+else()
+ message(WARNING "DEB Generator: Can't find gzip in your path. Several DEB packages will be missing man pages.")
+endif()
+
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.1.gz
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.bin.1.gz
+ ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-standalone.1.gz
+ DESTINATION share/man/man1
+ COMPONENT kodi)
+if(ENABLE_EVENTCLIENTS)
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-ps3remote.1.gz
+ DESTINATION share/man/man1
+ COMPONENT kodi-eventclients-ps3)
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-send.1.gz
+ DESTINATION share/man/man1
+ COMPONENT kodi-eventclients-kodi-send)
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-wiiremote.1.gz
+ DESTINATION share/man/man1
+ COMPONENT kodi-eventclients-wiiremote)
+endif()
+
+# configure package metadata files
+file(GLOB DEBIAN_PACKAGE_FILES ${CMAKE_SOURCE_DIR}/cmake/cpack/deb/packages/*.txt.in)
+foreach(file ${DEBIAN_PACKAGE_FILES})
+ get_filename_component(package ${file} NAME_WE)
+ # filter eventclients so we don't have to support two more deps
+ # (libbluetooth-dev and libcwiid-dev) just because of wii-remote
+ string(SUBSTRING ${package} 0 17 PACKAGE_FILTER)
+ if(NOT ENABLE_EVENTCLIENTS AND PACKAGE_FILTER STREQUAL kodi-eventclients)
+ message(STATUS "DEB Generator: ${package} matches ${PACKAGE_FILTER}, skipping.")
+ # do nothing
+ else()
+ configure_file(${file}
+ ${CPACK_PACKAGE_DIRECTORY}/deb/${package}.txt @ONLY)
+ list(APPEND DEBIAN_PACKAGES ${package})
+ endif()
+endforeach()
+unset(DEBIAN_PACKAGE_FILES)
+
+# generate packages
+include(CMakeParseArguments)
+foreach(file ${DEBIAN_PACKAGES})
+ core_file_read_filtered(DEBIAN_METADATA ${CPACK_PACKAGE_DIRECTORY}/deb/${file}.txt)
+ string(REPLACE " " ";" DEBIAN_METADATA "${DEBIAN_METADATA}")
+ cmake_parse_arguments(DEB
+ ""
+ "PACKAGE_NAME;PACKAGE_ARCHITECTURE;PACKAGE_SECTION;PACKAGE_PRIORITY;PACKAGE_SHLIBDEPS"
+ "PACKAGE_DEPENDS;PACKAGE_RECOMMENDS;PACKAGE_SUGGESTS;PACKAGE_BREAKS;PACKAGE_REPLACES;PACKAGE_PROVIDES;PACKAGE_DESCRIPTION_HEADER;PACKAGE_DESCRIPTION_FOOTER"
+ ${DEBIAN_METADATA})
+ string(REPLACE ";" " " DEB_PACKAGE_DEPENDS "${DEB_PACKAGE_DEPENDS}")
+ string(REPLACE ";" " " DEB_PACKAGE_RECOMMENDS "${DEB_PACKAGE_RECOMMENDS}")
+ string(REPLACE ";" " " DEB_PACKAGE_SUGGESTS "${DEB_PACKAGE_SUGGESTS}")
+ string(REPLACE ";" " " DEB_PACKAGE_BREAKS "${DEB_PACKAGE_BREAKS}")
+ string(REPLACE ";" " " DEB_PACKAGE_REPLACES "${DEB_PACKAGE_REPLACES}")
+ string(REPLACE ";" " " DEB_PACKAGE_PROVIDES "${DEB_PACKAGE_PROVIDES}")
+ string(REPLACE ";" " " DEB_PACKAGE_DESCRIPTION_HEADER "${DEB_PACKAGE_DESCRIPTION_HEADER}")
+ string(REPLACE ";" " " DEB_PACKAGE_DESCRIPTION_FOOTER "${DEB_PACKAGE_DESCRIPTION_FOOTER}")
+
+ string(TOUPPER ${file} COMPONENT)
+
+ if(NOT DEB_PACKAGE_ARCHITECTURE)
+ message(STATUS "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_ARCHITECTURE is empty. Setting to ${CPACK_SYSTEM_NAME}.")
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_ARCHITECTURE ${CPACK_SYSTEM_NAME})
+ else()
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_ARCHITECTURE ${DEB_PACKAGE_ARCHITECTURE})
+ endif()
+
+ if(DEB_PACKAGE_NAME)
+ if(DEB_PACKAGE_ARCHITECTURE)
+ set(CPACK_DEBIAN_${COMPONENT}_FILE_NAME ${DEB_PACKAGE_NAME}_${PACKAGE_NAME_VERSION}_${DEB_PACKAGE_ARCHITECTURE}.deb)
+ else()
+ set(CPACK_DEBIAN_${COMPONENT}_FILE_NAME ${DEB_PACKAGE_NAME}_${PACKAGE_NAME_VERSION}_${CPACK_SYSTEM_NAME}.deb)
+ endif()
+ else()
+ message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_FILE_NAME is not set.")
+ endif()
+
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SOURCE ${APP_NAME_LC})
+
+ if(DEB_PACKAGE_NAME)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_NAME ${DEB_PACKAGE_NAME})
+ else()
+ message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_NAME is not set.")
+ endif()
+
+ if(DEB_PACKAGE_SECTION)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SECTION ${DEB_PACKAGE_SECTION})
+ else()
+ message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_SECTION is not set.")
+ endif()
+
+ if(DEB_PACKAGE_PRIORITY)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_PRIORITY ${DEB_PACKAGE_PRIORITY})
+ else()
+ message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_PRIORITY is not set.")
+ endif()
+
+ if(DEB_PACKAGE_SHLIBDEPS)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SHLIBDEPS ON)
+ endif()
+
+ if(DEB_PACKAGE_DEPENDS)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_DEPENDS "${DEB_PACKAGE_DEPENDS}")
+ endif()
+
+ if(DEB_PACKAGE_RECOMMENDS)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_RECOMMENDS "${DEB_PACKAGE_RECOMMENDS}")
+ endif()
+
+ if(DEB_PACKAGE_SUGGESTS)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SUGGESTS "${DEB_PACKAGE_SUGGESTS}")
+ endif()
+
+ if(DEB_PACKAGE_BREAKS)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_BREAKS "${DEB_PACKAGE_BREAKS}")
+ endif()
+
+ if(DEB_PACKAGE_REPLACES)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_REPLACES "${DEB_PACKAGE_REPLACES}")
+ endif()
+
+ if(DEB_PACKAGE_PROVIDES)
+ set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_PROVIDES "${DEB_PACKAGE_PROVIDES}")
+ endif()
+
+ if(NOT DEB_PACKAGE_DESCRIPTION_HEADER OR NOT DEB_PACKAGE_DESCRIPTION_FOOTER)
+ message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_COMPONENT_${COMPONENT}_DESCRIPTION is not set.")
+ else()
+ set(CPACK_COMPONENT_${COMPONENT}_DESCRIPTION "\
+${DEB_PACKAGE_DESCRIPTION_HEADER}\n\
+${CPACK_DEBIAN_PACKAGE_DESCRIPTION} \
+${DEB_PACKAGE_DESCRIPTION_FOOTER}")
+ endif()
+
+ install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/changelog.Debian.gz
+ ${CPACK_PACKAGE_DIRECTORY}/deb/NEWS.Debian.gz
+ ${CMAKE_SOURCE_DIR}/cmake/cpack/deb/copyright
+ DESTINATION share/doc/${file}
+ COMPONENT ${file})
+
+ # kodi package exclusive files
+ if(CPACK_DEBIAN_KODI_PACKAGE_NAME)
+ set(CPACK_DEBIAN_KODI_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_SOURCE_DIR}/cmake/cpack/deb/postinst;${CMAKE_SOURCE_DIR}/cmake/cpack/deb/postrm")
+ install(FILES ${CMAKE_SOURCE_DIR}/cmake/cpack/deb/lintian/overrides/kodi
+ DESTINATION share/lintian/overrides
+ COMPONENT kodi)
+ install(FILES ${CMAKE_SOURCE_DIR}/cmake/cpack/deb/menu/kodi
+ DESTINATION share/menu
+ COMPONENT kodi)
+ endif()
+endforeach()
+unset(DEBIAN_PACKAGES)
+
+### source package generation specific variables
+# source generator
+set(CPACK_SOURCE_GENERATOR TGZ)
+
+# source package name
+set(CPACK_SOURCE_PACKAGE_FILE_NAME ${APP_NAME_LC}_${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}~git${PACKAGE_TIMESTAMP}-${RELEASE_IDENTIFIER}.orig)
+unset(RELEASE_IDENTIFIER)
+
+# ignore files for source package
+set(CPACK_SOURCE_IGNORE_FILES
+ "/build/"
+ "/debian/"
+ "/.git/"
+ ".gitignore"
+ "yml$"
+ "~$")
+
+# unset variables
+unset(PACKAGE_TIMESTAMP)
+unset(DISTRO_CODENAME)
+
+# reference docs
+# https://cmake.org/cmake/help/latest/module/CPack.html
+# https://cmake.org/cmake/help/latest/module/CPackDeb.html
+# https://cmake.org/cmake/help/latest/module/CPackComponent.html
+include(CPack)