[cmake-developers] [CPackDEB] handling "Source" field and Launchpad support
Raffi Enficiaud
raffi.enficiaud at mines-paris.org
Tue Nov 3 06:01:03 EST 2015
Hi all,
Please find attached a patch that enables the proper handling of the
"Source" field for binary Debian packages.
For the little story, this field references the source package (with
possible revision number) that was used to generate the binary package.
This is indeed needed when several .deb packages are generated by one
source tree, otherwise the generated binary packages are rejected by eg.
Launchpad at the upload step.
Without this patch, mono-component installs work as expected (see cmake
below).
I have successfully used the patch (and all the previous developments on
CPackDEB) to generate my little C++ project on Launchpad from a GIT
repository (check the packages content):
https://code.launchpad.net/~raffi-enficiaud-x/+archive/ubuntu/yayi/+packages
Also, I would like to announce that I created a little "debian/" folder
for the cmake project that allows to build "cmake" on Launchpad without
any effort/hassle, just by using a few dpkg tools and the cmake CPackDEB
machinery (based on the previous improvements of CPackDEB):
https://bitbucket.org/renficiaud/cmake-debian-ppa/src/3f79ec63ccdc331a7142f2088cd5e0311d04c7cc?at=master
The generated cmake debian packages are also in the same PPA.
I would be happy to know more about the best practices for being able to
generate multiple Debian packages from one source. Any comments more
than welcome.
Kind regards,
Raffi Enficiaud
PS: I posted on the gmane.linux.debian.devel.mentors list in the
following thread
http://thread.gmane.org/gmane.linux.debian.devel.mentors/72992
-------------- next part --------------
From c8fdbafdff7ed2556be53371a2357aa82ad6db5c Mon Sep 17 00:00:00 2001
From: Raffi Enficiaud <raffi.enficiaud at mines-paris.org>
Date: Wed, 28 Oct 2015 23:59:42 +0100
Subject: [PATCH] CPackDEB: handling binary packages "Source" field
- CPackeDEB now honour the Source field with multicomponent support
- minor documentation enhancements
---
Modules/CPackDeb.cmake | 48 ++++++++++++--
Source/CPack/cmCPackDebGenerator.cxx | 7 ++
Tests/CMakeLists.txt | 3 +-
.../MyLibCPackConfig-components-source.cmake.in | 33 ++++++++++
.../RunCPackVerifyResult-components-source.cmake | 75 ++++++++++++++++++++++
5 files changed, 158 insertions(+), 8 deletions(-)
create mode 100644 Tests/CPackComponentsDEB/MyLibCPackConfig-components-source.cmake.in
create mode 100644 Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake
diff --git a/Modules/CPackDeb.cmake b/Modules/CPackDeb.cmake
index 60e0d1f..3b82c73 100644
--- a/Modules/CPackDeb.cmake
+++ b/Modules/CPackDeb.cmake
@@ -8,7 +8,7 @@
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# CPackDeb may be used to create Deb package using CPack.
-# CPackDeb is a CPack generator thus it uses the CPACK_XXX variables
+# CPackDeb is a CPack generator thus it uses the `CPACK_XXX` variables
# used by CPack : https://cmake.org/Wiki/CMake:CPackConfiguration.
# CPackDeb generator should work on any linux host but it will produce
# better deb package when Debian specific tools 'dpkg-xxx' are usable on
@@ -18,7 +18,7 @@
# :code:`CPACK_DEBIAN_XXX` variables.
#
# :code:`CPACK_DEBIAN_<COMPONENT>_XXXX` variables may be used in order to have
-# **component** specific values. Note however that <COMPONENT> refers to the
+# **component** specific values. Note however that `<COMPONENT>` refers to the
# **grouping name** written in upper case. It may be either a component name or
# a component GROUP name.
#
@@ -354,7 +354,28 @@
# set by Debian policy
# https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
#
-
+# .. variable:: CPACK_DEBIAN_PACKAGE_SOURCE
+# CPACK_DEBIAN_<COMPONENT>_PACKAGE_SOURCE
+#
+# Sets the `Source` field of the binary Debian package.
+# When the binary package name is not the same as the source package name
+# in particular when several components/binaries are generated from one source)
+# the source from which the binary has been generated should be indicated with
+# the field `Source`.
+#
+# * Mandatory : NO
+# * Default :
+#
+# - An empty string for non-component based installations
+# - :variable:`CPACK_DEBIAN_PACKAGE_SOURCE` for component-based
+# installations.
+#
+# See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
+#
+# .. note::
+#
+# This value is not interpreted, it is then possible to pass an optional
+# revision number for the referenced source package as well.
#=============================================================================
# Copyright 2007-2009 Kitware, Inc.
@@ -554,6 +575,16 @@ function(cpack_deb_prepare_package_vars)
)
endif()
+ # Source: (optional)
+ # in case several packages are constructed from a unique source
+ # (multipackaging), the the source may be indicated as well.
+ # The source might contain a version if the generated package
+ # version is different from the source version
+ if(NOT CPACK_DEBIAN_PACKAGE_SOURCE)
+ set(CPACK_DEBIAN_PACKAGE_SOURCE "")
+ endif()
+
+
# have a look at get_property(result GLOBAL PROPERTY ENABLED_FEATURES),
# this returns the successful find_package() calls, maybe this can help
# Depends:
@@ -563,15 +594,15 @@ function(cpack_deb_prepare_package_vars)
# if per-component dependency, overrides the global CPACK_DEBIAN_PACKAGE_${dependency_type_}
# automatic dependency discovery will be performed afterwards.
if(CPACK_DEB_PACKAGE_COMPONENT)
- foreach(dependency_type_ DEPENDS RECOMMENDS SUGGESTS PREDEPENDS ENHANCES BREAKS CONFLICTS PROVIDES REPLACES)
+ foreach(dependency_type_ DEPENDS RECOMMENDS SUGGESTS PREDEPENDS ENHANCES BREAKS CONFLICTS PROVIDES REPLACES SOURCE)
set(_component_var "CPACK_DEBIAN_${_local_component_name}_PACKAGE_${dependency_type_}")
# if set, overrides the global dependency
if(DEFINED ${_component_var})
set(CPACK_DEBIAN_PACKAGE_${dependency_type_} "${${_component_var}}")
if(CPACK_DEBIAN_PACKAGE_DEBUG)
- message("CPackDeb Debug: component '${_local_component_name}' ${dependency_type_}"
- "dependencies set to '${CPACK_DEBIAN_PACKAGE_${dependency_}}'")
+ message("CPackDeb Debug: component '${_local_component_name}' ${dependency_type_} "
+ "dependencies set to '${CPACK_DEBIAN_PACKAGE_${dependency_type_}}'")
endif()
endif()
endforeach()
@@ -680,7 +711,8 @@ function(cpack_deb_prepare_package_vars)
message("CPackDeb:Debug: CPACK_PACKAGE_FILE_NAME = ${CPACK_PACKAGE_FILE_NAME}")
message("CPackDeb:Debug: CPACK_PACKAGE_INSTALL_DIRECTORY = ${CPACK_PACKAGE_INSTALL_DIRECTORY}")
message("CPackDeb:Debug: CPACK_TEMPORARY_PACKAGE_FILE_NAME = ${CPACK_TEMPORARY_PACKAGE_FILE_NAME}")
- message("CPackDeb:Debug: CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION = ${CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION}")
+ message("CPackDeb:Debug: CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION = '${CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION}'")
+ message("CPackDeb:Debug: CPACK_DEBIAN_PACKAGE_SOURCE = '${CPACK_DEBIAN_PACKAGE_SOURCE}'")
endif()
# For debian source packages:
@@ -719,6 +751,8 @@ function(cpack_deb_prepare_package_vars)
set(GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION
"${CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION}" PARENT_SCOPE)
+ set(GEN_CPACK_DEBIAN_PACKAGE_SOURCE
+ "${CPACK_DEBIAN_PACKAGE_SOURCE}" PARENT_SCOPE)
set(GEN_WDIR "${WDIR}" PARENT_SCOPE)
endfunction()
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 04efb71..13c8d8f 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -339,6 +339,9 @@ int cmCPackDebGenerator::createDeb()
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES");
const char* debian_pkg_replaces =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES");
+ const char* debian_pkg_source =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
+
{ // the scope is needed for cmGeneratedFileStream
cmGeneratedFileStream out(ctlfilename.c_str());
@@ -347,6 +350,10 @@ int cmCPackDebGenerator::createDeb()
out << "Section: " << debian_pkg_section << "\n";
out << "Priority: " << debian_pkg_priority << "\n";
out << "Architecture: " << debian_pkg_arch << "\n";
+ if(debian_pkg_source && *debian_pkg_source)
+ {
+ out << "Source: " << debian_pkg_source << "\n";
+ }
if(debian_pkg_dep && *debian_pkg_dep)
{
out << "Depends: " << debian_pkg_dep << "\n";
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index ae61bca..cd4c61d 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1035,7 +1035,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
"components-description2"
"components-shlibdeps1"
"components-depend1"
- "components-depend2")
+ "components-depend2"
+ "components-source")
set(CPackGen "DEB")
set(CPackRun_CPackGen "-DCPackGen=${CPackGen}")
diff --git a/Tests/CPackComponentsDEB/MyLibCPackConfig-components-source.cmake.in b/Tests/CPackComponentsDEB/MyLibCPackConfig-components-source.cmake.in
new file mode 100644
index 0000000..352f10b
--- /dev/null
+++ b/Tests/CPackComponentsDEB/MyLibCPackConfig-components-source.cmake.in
@@ -0,0 +1,33 @@
+#
+# Activate component packaging
+#
+
+if(CPACK_GENERATOR MATCHES "DEB")
+ set(CPACK_DEB_COMPONENT_INSTALL "ON")
+endif()
+
+#
+# Choose grouping way
+#
+set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
+
+# setting dependencies
+set(CPACK_DEBIAN_PACKAGE_DEPENDS "depend-default")
+set(CPACK_DEBIAN_HEADERS_PACKAGE_DEPENDS "depend-headers")
+
+# this time we set shlibdeps to on
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+set(CPACK_DEBIAN_HEADERS_PACKAGE_SHLIBDEPS OFF)
+set(CPACK_DEBIAN_LIBRARIES_PACKAGE_SHLIBDEPS OFF)
+
+# we also set the dependencies of APPLICATION component to empty, and let
+# shlibdeps do the job for this component. Otherwise the default will
+# override
+set(CPACK_DEBIAN_APPLICATIONS_PACKAGE_DEPENDS "")
+
+# this sets the generated packages source to the desired one, in case
+# several packages are generated from a unique source (the case with
+# multicomponents packaging).
+
+set(CPACK_DEBIAN_PACKAGE_SOURCE "test-source")
+set(CPACK_DEBIAN_APPLICATIONS_PACKAGE_SOURCE "test-other-source")
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake
new file mode 100644
index 0000000..51fa3ad
--- /dev/null
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake
@@ -0,0 +1,75 @@
+if(NOT CPackComponentsDEB_SOURCE_DIR)
+ message(FATAL_ERROR "CPackComponentsDEB_SOURCE_DIR not set")
+endif()
+
+include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake)
+
+
+# expected results
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/MyLib-*.deb")
+set(expected_count 3)
+
+set(config_verbose -V)
+set(actual_output)
+run_cpack(actual_output
+ CPack_output
+ CPack_error
+ EXPECTED_FILE_MASK "${expected_file_mask}"
+ CONFIG_ARGS ${config_args}
+ CONFIG_VERBOSE ${config_verbose})
+
+
+if(NOT actual_output)
+ message(STATUS "expected_count='${expected_count}'")
+ message(STATUS "expected_file_mask='${expected_file_mask}'")
+ message(STATUS "actual_output_files='${actual_output}'")
+ message(FATAL_ERROR "error: expected_files do not exist: CPackComponentsDEB test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error}")
+endif()
+
+list(LENGTH actual_output actual_count)
+if(NOT actual_count EQUAL expected_count)
+ message(STATUS "actual_count='${actual_count}'")
+ message(FATAL_ERROR "error: expected_count=${expected_count} does not match actual_count=${actual_count}: CPackComponents test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error})")
+endif()
+
+
+# dpkg-deb checks for the summary of the packages
+find_program(DPKGDEB_EXECUTABLE dpkg-deb)
+if(DPKGDEB_EXECUTABLE)
+ set(dpkgdeb_output_errors_all "")
+ foreach(_f IN LISTS actual_output)
+
+ # extracts the metadata from the package
+ run_dpkgdeb(dpkg_output
+ FILENAME "${_f}"
+ )
+
+ dpkgdeb_return_specific_metaentry(dpkg_package_name
+ DPKGDEB_OUTPUT "${dpkg_output}"
+ METAENTRY "Package:")
+
+ dpkgdeb_return_specific_metaentry(dpkg_package_source
+ DPKGDEB_OUTPUT "${dpkg_output}"
+ METAENTRY "Source:")
+
+ message(STATUS "package='${_f}', source='${dpkg_package_source}'")
+
+ if(NOT ("${dpkg_package_name}" STREQUAL "mylib-applications"))
+ if(NOT ("${dpkg_package_source}" STREQUAL "test-source"))
+ set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+ "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-source'\n")
+ endif()
+ else()
+ if(NOT ("${dpkg_package_source}" STREQUAL "test-other-source"))
+ set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+ "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-other-source'\n")
+ endif()
+ endif()
+ endforeach()
+
+ if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
+ message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
+ endif()
+else()
+ message("dpkg-deb executable not found - skipping dpkg-deb test")
+endif()
--
2.0.1
More information about the cmake-developers
mailing list