Browse Source

CPack/DEB per component dependencies

Dependencies may now be set per component
Raffi Enficiaud 10 years ago
parent
commit
e3f522f6e4

+ 53 - 15
Modules/CPackDeb.cmake

@@ -48,11 +48,31 @@
 #  The debian package architecture
 #
 # .. variable:: CPACK_DEBIAN_PACKAGE_DEPENDS
+#               CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS
+#
+#  May be used to set deb dependencies.
 #
 #  * Mandatory : NO
-#  * Default   : -
+#  * Default   :
 #
-#  May be used to set deb dependencies.
+#    - An empty string for non-component based installations
+#    - :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS` for component-based
+#      installations.
+#
+#  .. note::
+#
+#    If :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS` or
+#    more specifically :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS`
+#    is set for this component, the discovered dependencies will be appended
+#    to :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS` intead of
+#    :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS`. If
+#    :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS` is an empty string,
+#    only the automatically discovered dependencies will be set for this
+#    component.
+#
+#  Example::
+#
+#    set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libc6 (< 2.4)")
 #
 # .. variable:: CPACK_DEBIAN_PACKAGE_MAINTAINER
 #
@@ -356,33 +376,24 @@ function(cpack_deb_prepare_package_vars)
         string(REGEX REPLACE "^.*Depends=" "" CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS "${SHLIBDEPS_OUTPUT}")
 
         if(CPACK_DEBIAN_PACKAGE_DEBUG)
-          message( "CPackDeb Debug: Found dependency: ${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}")
+          message("CPackDeb Debug: Found dependency: ${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS} from output ${SHLIBDEPS_OUTPUT}")
         endif()
 
         # Remove blank control file
         # Might not be safe if package actual contain file or directory named debian
         file(REMOVE_RECURSE "${CPACK_TEMPORARY_DIRECTORY}/debian")
-
-        # Append user depend if set
-        if(CPACK_DEBIAN_PACKAGE_DEPENDS)
-          set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}, ${CPACK_DEBIAN_PACKAGE_DEPENDS}")
-        else()
-          set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}")
-        endif()
       else()
         if(CPACK_DEBIAN_PACKAGE_DEBUG)
-          message( "CPackDeb Debug: Using only user-provided depends because package does not contain executable files that contain dynamically linked libraries.")
+          message(AUTHOR_WARNING "CPackDeb Debug: Using only user-provided depends because package does not contain executable files that link to shared libraries.")
         endif()
       endif()
     else()
-      if(CPACK_DEBIAN_PACKAGE_DEBUG)
-        message( "CPackDeb Debug: Using only user-provided depends because dpkg-shlibdeps is not found.")
-      endif()
+      message("CPackDeb: Using only user-provided dependencies because dpkg-shlibdeps is not found.")
     endif()
 
   else()
     if(CPACK_DEBIAN_PACKAGE_DEBUG)
-      message( "CPackDeb Debug: Using only user-provided depends")
+      message("CPackDeb Debug: Using only user-provided dependencies")
     endif()
   endif()
 
@@ -426,6 +437,33 @@ function(cpack_deb_prepare_package_vars)
   # Depends:
   # You should set: DEBIAN_PACKAGE_DEPENDS
   # TODO: automate 'objdump -p | grep NEEDED'
+
+  # if per-component dependency, overrides the global CPACK_DEBIAN_PACKAGE_DEPENDS
+  # automatic dependency discovery will be performed afterwards.
+  if(CPACK_DEB_PACKAGE_COMPONENT)
+    string(TOUPPER "${CPACK_DEB_PACKAGE_COMPONENT}" _local_component_name)
+    set(_component_depends_var "CPACK_DEBIAN_${_local_component_name}_PACKAGE_DEPENDS")
+
+    # if set, overrides the global dependency
+    if(DEFINED ${_component_depends_var})
+      set(CPACK_DEBIAN_PACKAGE_DEPENDS "${${_component_depends_var}}")
+      if(CPACK_DEBIAN_PACKAGE_DEBUG)
+        message("CPackDeb Debug: component '${_local_component_name}' dependencies set to '${CPACK_DEBIAN_PACKAGE_DEPENDS}'")
+      endif()
+    endif()
+  endif()
+
+  # at this point, the CPACK_DEBIAN_PACKAGE_DEPENDS is properly set
+  # to the minimal dependency of the package
+  # Append automatically discovered dependencies .
+  if(NOT "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}" STREQUAL "")
+    if (CPACK_DEBIAN_PACKAGE_DEPENDS)
+      set (CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}, ${CPACK_DEBIAN_PACKAGE_DEPENDS}")
+    else ()
+      set (CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}")
+    endif ()
+  endif()
+
   if(NOT CPACK_DEBIAN_PACKAGE_DEPENDS)
     message(STATUS "CPACK_DEBIAN_PACKAGE_DEPENDS not set, the package will have no dependencies.")
   endif()

+ 3 - 1
Tests/CMakeLists.txt

@@ -1013,7 +1013,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
       set(DEB_CONFIGURATIONS_TO_TEST "components-lintian-dpkgdeb-checks"
                                      "components-description1"
                                      "components-description2"
-                                     "components-shlibdeps1")
+                                     "components-shlibdeps1"
+                                     "components-depend1"
+                                     "components-depend2")
       set(CPackGen "DEB")
       set(CPackRun_CPackGen "-DCPackGen=${CPackGen}")
 

+ 20 - 0
Tests/CPackComponentsDEB/MyLibCPackConfig-components-depend1.cmake.in

@@ -0,0 +1,20 @@
+#
+# Activate component packaging
+#
+
+if(CPACK_GENERATOR MATCHES "DEB")
+   set(CPACK_DEB_COMPONENT_INSTALL "ON")
+endif()
+
+#
+# Choose grouping way
+#
+#set(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE)
+#set(CPACK_COMPONENTS_GROUPING)
+set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
+#set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
+
+# setting dependencies
+set(CPACK_DEBIAN_PACKAGE_DEPENDS                "depend-default")
+set(CPACK_DEBIAN_APPLICATIONS_PACKAGE_DEPENDS   "depend-application")
+set(CPACK_DEBIAN_HEADERS_PACKAGE_DEPENDS        "depend-headers")

+ 29 - 0
Tests/CPackComponentsDEB/MyLibCPackConfig-components-depend2.cmake.in

@@ -0,0 +1,29 @@
+#
+# Activate component packaging
+#
+
+if(CPACK_GENERATOR MATCHES "DEB")
+   set(CPACK_DEB_COMPONENT_INSTALL "ON")
+endif()
+
+#
+# Choose grouping way
+#
+#set(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE)
+#set(CPACK_COMPONENTS_GROUPING)
+set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
+#set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 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        "")

+ 85 - 0
Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake

@@ -0,0 +1,85 @@
+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(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 dependencies 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_depends
+                                      DPKGDEB_OUTPUT "${dpkg_output}"
+                                      METAENTRY "Depends:")
+
+    message(STATUS "package='${dpkg_package_name}', dependencies='${dpkg_depends}'")
+
+    if("${dpkg_package_name}" STREQUAL "mylib-applications")
+      if(NOT "${dpkg_depends}" STREQUAL "depend-application")
+        set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
+                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-application'\n")
+      endif()
+    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
+      if(NOT "${dpkg_depends}" STREQUAL "depend-headers")
+        set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
+                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-headers'\n")
+      endif()
+    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
+      if(NOT "${dpkg_depends}" STREQUAL "depend-default")
+        set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
+                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n")
+      endif()
+    else()
+      set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
+                                    "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
+    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()

+ 97 - 0
Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake

@@ -0,0 +1,97 @@
+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_depends
+                                      DPKGDEB_OUTPUT "${dpkg_output}"
+                                      METAENTRY "Depends:")
+
+    message(STATUS "package='${dpkg_package_name}', dependencies='${dpkg_depends}'")
+
+    if("${dpkg_package_name}" STREQUAL "mylib-applications")
+      find_program(DPKG_SHLIBDEP_EXECUTABLE dpkg-shlibdeps)
+      if(DPKG_SHLIBDEP_EXECUTABLE)
+        string(FIND "${dpkg_depends}" "lib" index_libwhatever)
+        if(NOT index_libwhatever GREATER "-1")
+          set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+                                        "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does not contain any 'lib'\n")
+        endif()
+      else()
+        message("dpkg-shlibdeps executable not found - skipping dpkg-shlibdeps test")
+      endif()
+
+      # should not contain the default
+      string(FIND "${dpkg_depends}" "depend-default" index_default)
+      if(index_default GREATER "0")
+        set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does contains 'depend-default'\n")
+      endif()
+    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
+      if(NOT "${dpkg_depends}" STREQUAL "depend-headers")
+        set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-headers'\n")
+      endif()
+    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
+      if(NOT "${dpkg_depends}" STREQUAL "depend-default")
+        set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n")
+      endif()
+    else()
+      set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
+                                    "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
+    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()

+ 1 - 0
Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake

@@ -58,6 +58,7 @@ function(run_cpack output_expected_file CPack_output_parent CPack_error_parent)
     message(FATAL_ERROR "error: CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}")
   else ()
     message(STATUS "CPack_output=${CPack_output}")
+    message(STATUS "CPack_error=${CPack_error}")
   endif()