[Cmake-commits] CMake branch, next, updated. v3.7.0-rc1-199-gb331083

Brad King brad.king at kitware.com
Fri Oct 7 09:19:23 EDT 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  b3310831a55d40848cb76dfbccf44c5179e916e0 (commit)
       via  bb8cf5215680efe76f8197d52aa2620a8e939895 (commit)
       via  758f58b4a18fbb512edd1baf520017e816fee20b (commit)
      from  f724cf9c8d03d8e14a109bc99de497328936e992 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b3310831a55d40848cb76dfbccf44c5179e916e0
commit b3310831a55d40848cb76dfbccf44c5179e916e0
Merge: f724cf9 bb8cf52
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Oct 7 09:19:22 2016 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Fri Oct 7 09:19:22 2016 -0400

    Merge topic 'cpack-rpm-single-debuginfo' into next
    
    bb8cf521 CPack/RPM single debuginfo packaging
    758f58b4 CPack/RPM learned defining main component


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bb8cf5215680efe76f8197d52aa2620a8e939895
commit bb8cf5215680efe76f8197d52aa2620a8e939895
Author:     Domen Vrankar <domen.vrankar at gmail.com>
AuthorDate: Thu Oct 6 08:33:16 2016 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Oct 7 09:19:04 2016 -0400

    CPack/RPM single debuginfo packaging
    
    Generate a single debuginfo package even
    if components packaging is enabled.
    
    This makes issue #15668 resolution feature complete.
    
    Closes: #15486

diff --git a/Help/release/dev/cpack-rpm-single-debuginfo.rst b/Help/release/dev/cpack-rpm-single-debuginfo.rst
index 281a988..34a710d 100644
--- a/Help/release/dev/cpack-rpm-single-debuginfo.rst
+++ b/Help/release/dev/cpack-rpm-single-debuginfo.rst
@@ -5,3 +5,7 @@ cpack-rpm-single-debuginfo
   which forces generation of a rpm for defined component without component
   suffix in filename and package name.
   See :variable:`CPACK_RPM_MAIN_COMPONENT` variable.
+
+* The :module:`CPackRPM` module learned to generate a single debuginfo package
+  on demand even if components packagin is used.
+  See :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` variable.
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index 2c8c0e0..6017ce3 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -803,6 +803,26 @@
 #  * Mandatory : NO
 #  * Default   : -
 #
+# .. variable:: CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE
+#
+#  Create a single debuginfo package even if components packaging is set.
+#
+#  * Mandatory : NO
+#  * Default   : OFF
+#
+#  When this variable is enabled it produces a single debuginfo package even if
+#  component packaging is enabled.
+#
+#  When using this feature in combination with components packaging and there is
+#  more than one component this variable requires :variable:`CPACK_RPM_MAIN_COMPONENT`
+#  to be set.
+#
+# .. note::
+#
+#  If none of the :variable:`CPACK_RPM_<component>_DEBUGINFO_PACKAGE` variables
+#  is set then :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is automatically set to
+#  ``ON`` when :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` is set.
+#
 # Packaging of sources (SRPM)
 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 #
@@ -2076,7 +2096,7 @@ function(cpack_rpm_generate_package)
     "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_PACKAGE"
     "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_PACKAGE"
     "CPACK_RPM_DEBUGINFO_PACKAGE")
-  if(CPACK_RPM_DEBUGINFO_PACKAGE)
+  if(CPACK_RPM_DEBUGINFO_PACKAGE OR (CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND NOT GENERATE_SPEC_PARTS))
     cpack_rpm_variable_fallback("CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX"
       "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_BUILD_SOURCE_DIRS_PREFIX"
       "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_BUILD_SOURCE_DIRS_PREFIX"
@@ -2084,9 +2104,81 @@ function(cpack_rpm_generate_package)
     if(NOT CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX)
       set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/src/debug/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}")
     endif()
-    cpack_rpm_debugsymbol_check("${CPACK_RPM_INSTALL_FILES}" "${WDIR}")
 
-    set(TMP_RPM_DEBUGINFO "
+    if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS)
+      file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.files"
+        "${CPACK_RPM_INSTALL_FILES}")
+    else()
+      if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND CPACK_RPM_PACKAGE_COMPONENT)
+        # this part is only required by components packaging - with monolithic
+        # packages we can be certain that there are no other components present
+        # so CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is a noop
+        if(CPACK_RPM_DEBUGINFO_PACKAGE)
+          # only add current package files to debuginfo list if debuginfo
+          # generation is enabled for current package
+          set(install_files_ "${CPACK_RPM_INSTALL_FILES}")
+        else()
+          unset(install_files_)
+        endif()
+
+        file(GLOB files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.files")
+
+        foreach(f_ IN LISTS files_)
+          file(READ "${f_}" tmp_)
+          string(APPEND install_files_ ";${tmp_}")
+        endforeach()
+
+        # if there were other components/groups so we need to move files from them
+        # to current component otherwise those files won't be found
+        file(GLOB components_ LIST_DIRECTORIES true RELATIVE
+          "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}"
+          "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/*")
+        foreach(component_ IN LISTS components_)
+          string(TOUPPER "${component_}" component_dir_upper_)
+          if(component_dir_upper_ STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER)
+            # skip current component
+            continue()
+          endif()
+
+          cmake_policy(PUSH)
+            cmake_policy(SET CMP0009 NEW)
+            file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES false RELATIVE
+              "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}"
+              "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/*")
+          cmake_policy(POP)
+
+          foreach(f_ IN LISTS files_for_move_)
+            get_filename_component(dir_path_ "${f_}" DIRECTORY)
+            set(src_file_
+              "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/${f_}")
+
+            # check that we are not overriding an existing file that doesn't
+            # match the file that we want to copy
+            if(EXISTS "${src_file_}" AND EXISTS "${WDIR}/${f_}")
+              execute_process(
+                  COMMAND ${CMAKE_COMMAND} -E compare_files "${src_file_}" "${WDIR}/${f_}"
+                  RESULT_VARIABLE res_
+                )
+              if(res_)
+                message(FATAL_ERROR "CPackRPM:Error: File on path '${WDIR}/${f_}'"
+                  " already exists but is a different than the one in component"
+                  " '${component_}'! Packages will not be generated.")
+              endif()
+            endif()
+
+            file(MAKE_DIRECTORY "${WDIR}/${dir_path_}")
+            file(RENAME "${src_file_}"
+              "${WDIR}/${f_}")
+          endforeach()
+        endforeach()
+
+        cpack_rpm_debugsymbol_check("${install_files_}" "${WDIR}")
+      else()
+        cpack_rpm_debugsymbol_check("${CPACK_RPM_INSTALL_FILES}" "${WDIR}")
+      endif()
+
+      if(TMP_DEBUGINFO_ADDITIONAL_SOURCES)
+        set(TMP_RPM_DEBUGINFO "
 # Modified version of %%debug_package macro
 # defined in /usr/lib/rpm/macros as that one
 # can't handle injection of extra source files.
@@ -2105,6 +2197,15 @@ package or when debugging this package.
 ${TMP_DEBUGINFO_ADDITIONAL_SOURCES}
 %endif
 ")
+      elseif(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE)
+        message(AUTHOR_WARNING "CPackRPM:Warning: debuginfo package was requested"
+          " but will not be generated as no source files were found!")
+      else()
+        message(AUTHOR_WARNING "CPackRPM:Warning: debuginfo package was requested"
+          " but will not be generated as no source files were found! Component: '"
+          "${CPACK_RPM_PACKAGE_COMPONENT}'.")
+      endif()
+    endif()
   endif()
 
   # Prepare install files
@@ -2194,7 +2295,12 @@ ${TMP_DEBUGINFO_ADDITIONAL_SOURCES}
     # else example:
     #set(CPACK_RPM_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}-${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm")
 
-    if(NOT CPACK_RPM_DEBUGINFO_PACKAGE)
+    if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS)
+      string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" expected_filename_)
+
+      file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.rpm_name"
+        "${expected_filename_};${CPACK_RPM_FILE_NAME}")
+    elseif(NOT CPACK_RPM_DEBUGINFO_PACKAGE)
       set(FILE_NAME_DEFINE "%define _rpmfilename ${CPACK_RPM_FILE_NAME}")
     endif()
   endif()
@@ -2289,7 +2395,54 @@ Vendor:         \@CPACK_RPM_PACKAGE_VENDOR\@
 \@CPACK_RPM_SPEC_CHANGELOG\@
 "
     )
+
+  elseif(GENERATE_SPEC_PARTS) # binary rpm with single debuginfo package
+    file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in
+        "# -*- rpm-spec -*-
+%package -n \@CPACK_RPM_PACKAGE_NAME\@
+Summary:        \@CPACK_RPM_PACKAGE_SUMMARY\@
+Version:        \@CPACK_RPM_PACKAGE_VERSION\@
+Release:        \@CPACK_RPM_PACKAGE_RELEASE\@
+License:        \@CPACK_RPM_PACKAGE_LICENSE\@
+Group:          \@CPACK_RPM_PACKAGE_GROUP\@
+Vendor:         \@CPACK_RPM_PACKAGE_VENDOR\@
+
+\@TMP_RPM_URL\@
+\@TMP_RPM_REQUIRES\@
+\@TMP_RPM_REQUIRES_PRE\@
+\@TMP_RPM_REQUIRES_POST\@
+\@TMP_RPM_REQUIRES_PREUN\@
+\@TMP_RPM_REQUIRES_POSTUN\@
+\@TMP_RPM_PROVIDES\@
+\@TMP_RPM_OBSOLETES\@
+\@TMP_RPM_CONFLICTS\@
+\@TMP_RPM_AUTOPROV\@
+\@TMP_RPM_AUTOREQ\@
+\@TMP_RPM_AUTOREQPROV\@
+\@TMP_RPM_BUILDARCH\@
+\@TMP_RPM_PREFIXES\@
+
+%description -n \@CPACK_RPM_PACKAGE_NAME\@
+\@CPACK_RPM_PACKAGE_DESCRIPTION\@
+
+%files -n \@CPACK_RPM_PACKAGE_NAME\@
+%defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@)
+\@CPACK_RPM_INSTALL_FILES\@
+\@CPACK_RPM_ABSOLUTE_INSTALL_FILES\@
+\@CPACK_RPM_USER_INSTALL_FILES\@
+"
+    )
+
   else()  # binary rpm
+    if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE)
+      # find generated spec file and take its name
+      file(GLOB spec_files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.spec")
+
+      foreach(f_ IN LISTS spec_files_)
+        file(READ "${f_}" tmp_)
+        string(APPEND TMP_OTHER_COMPONENTS "\n${tmp_}\n")
+      endforeach()
+    endif()
 
     # We should generate a USER spec file template:
     #  - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE
@@ -2375,6 +2528,8 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT
 
 %changelog
 \@CPACK_RPM_SPEC_CHANGELOG\@
+
+\@TMP_OTHER_COMPONENTS\@
 "
       )
     endif()
@@ -2401,60 +2556,90 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT
     configure_file(${CPACK_RPM_BINARY_SPECFILE}.in ${CPACK_RPM_BINARY_SPECFILE} @ONLY)
   endif()
 
-  if(RPMBUILD_EXECUTABLE)
-    # Now call rpmbuild using the SPECFILE
-    execute_process(
-      COMMAND "${RPMBUILD_EXECUTABLE}" ${RPMBUILD_FLAGS}
-              --define "_topdir ${CPACK_RPM_DIRECTORY}"
-              --buildroot "%_topdir/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
-              --target "${CPACK_RPM_PACKAGE_ARCHITECTURE}"
-              "${CPACK_RPM_BINARY_SPECFILE}"
-      WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
-      RESULT_VARIABLE CPACK_RPMBUILD_EXEC_RESULT
-      ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err"
-      OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out")
-    if(CPACK_RPM_PACKAGE_DEBUG OR CPACK_RPMBUILD_EXEC_RESULT)
-      file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err RPMBUILDERR)
-      file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out RPMBUILDOUT)
-      message("CPackRPM:Debug: You may consult rpmbuild logs in: ")
-      message("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err")
-      message("CPackRPM:Debug: *** ${RPMBUILDERR} ***")
-      message("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out")
-      message("CPackRPM:Debug: *** ${RPMBUILDOUT} ***")
+  if(NOT GENERATE_SPEC_PARTS) # generate package
+    if(RPMBUILD_EXECUTABLE)
+      # Now call rpmbuild using the SPECFILE
+      execute_process(
+        COMMAND "${RPMBUILD_EXECUTABLE}" ${RPMBUILD_FLAGS}
+                --define "_topdir ${CPACK_RPM_DIRECTORY}"
+                --buildroot "%_topdir/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
+                --target "${CPACK_RPM_PACKAGE_ARCHITECTURE}"
+                "${CPACK_RPM_BINARY_SPECFILE}"
+        WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
+        RESULT_VARIABLE CPACK_RPMBUILD_EXEC_RESULT
+        ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err"
+        OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out")
+      if(CPACK_RPM_PACKAGE_DEBUG OR CPACK_RPMBUILD_EXEC_RESULT)
+        file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err RPMBUILDERR)
+        file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out RPMBUILDOUT)
+        message("CPackRPM:Debug: You may consult rpmbuild logs in: ")
+        message("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err")
+        message("CPackRPM:Debug: *** ${RPMBUILDERR} ***")
+        message("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out")
+        message("CPackRPM:Debug: *** ${RPMBUILDOUT} ***")
+      endif()
+    else()
+      if(ALIEN_EXECUTABLE)
+        message(FATAL_ERROR "RPM packaging through alien not done (yet)")
+      endif()
     endif()
-  else()
-    if(ALIEN_EXECUTABLE)
-      message(FATAL_ERROR "RPM packaging through alien not done (yet)")
+
+    # find generated rpm files and take their names
+    cmake_policy(PUSH)
+      # Tell file(GLOB_RECURSE) not to follow directory symlinks
+      # even if the project does not set this policy to NEW.
+      cmake_policy(SET CMP0009 NEW)
+      file(GLOB_RECURSE GENERATED_FILES "${CPACK_RPM_DIRECTORY}/RPMS/*.rpm"
+        "${CPACK_RPM_DIRECTORY}/SRPMS/*.rpm")
+    cmake_policy(POP)
+
+    if(NOT GENERATED_FILES)
+      message(FATAL_ERROR "RPM package was not generated! ${CPACK_RPM_DIRECTORY}")
     endif()
-  endif()
 
-  # find generated rpm files and take their names
-  cmake_policy(PUSH)
-    # Tell file(GLOB_RECURSE) not to follow directory symlinks
-    # even if the project does not set this policy to NEW.
-    cmake_policy(SET CMP0009 NEW)
-    file(GLOB_RECURSE GENERATED_FILES "${CPACK_RPM_DIRECTORY}/RPMS/*.rpm"
-      "${CPACK_RPM_DIRECTORY}/SRPMS/*.rpm")
-  cmake_policy(POP)
+    unset(expected_filenames_)
+    unset(filenames_)
+    if(CPACK_RPM_DEBUGINFO_PACKAGE AND NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT")
+      string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" efn_)
+      list(APPEND expected_filenames_ "${efn_}")
+      list(APPEND filenames_ "${CPACK_RPM_FILE_NAME}")
+    endif()
 
-  if(NOT GENERATED_FILES)
-    message(FATAL_ERROR "RPM package was not generated! ${CPACK_RPM_DIRECTORY}")
-  endif()
+    # check if other files have to be renamed
+    file(GLOB rename_files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.rpm_name")
+    if(rename_files_)
+      foreach(f_ IN LISTS rename_files_)
+        file(READ "${f_}" tmp_)
+        list(GET tmp_ 0 efn_)
+        list(APPEND expected_filenames_ "${efn_}")
+        list(GET tmp_ 1 fn_)
+        list(APPEND filenames_ "${fn_}")
+      endforeach()
+    endif()
 
-  if(CPACK_RPM_DEBUGINFO_PACKAGE AND NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT")
-    string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" EXPECTED_FILENAME)
+    if(expected_filenames_)
+      foreach(F IN LISTS GENERATED_FILES)
+        unset(matched_)
+        foreach(expected_ IN LISTS expected_filenames_)
+          if(F MATCHES ".*/${expected_}")
+            list(FIND expected_filenames_ "${expected_}" idx_)
+            list(GET filenames_ ${idx_} filename_)
+            get_filename_component(FILE_PATH "${F}" DIRECTORY)
+            file(RENAME "${F}" "${FILE_PATH}/${filename_}")
+            list(APPEND new_files_list_ "${FILE_PATH}/${filename_}")
+            set(matched_ "YES")
+
+            break()
+          endif()
+        endforeach()
 
-    foreach(F IN LISTS GENERATED_FILES)
-      if(F MATCHES ".*/${EXPECTED_FILENAME}")
-        get_filename_component(FILE_PATH "${F}" DIRECTORY)
-        file(RENAME "${F}" "${FILE_PATH}/${CPACK_RPM_FILE_NAME}")
-        list(APPEND new_files_list_ "${FILE_PATH}/${CPACK_RPM_FILE_NAME}")
-      else()
-        list(APPEND new_files_list_ "${F}")
-      endif()
-    endforeach()
+        if(NOT matched_)
+          list(APPEND new_files_list_ "${F}")
+        endif()
+      endforeach()
 
-    set(GENERATED_FILES "${new_files_list_}")
+      set(GENERATED_FILES "${new_files_list_}")
+    endif()
   endif()
 
   set(GEN_CPACK_OUTPUT_FILES "${GENERATED_FILES}" PARENT_SCOPE)
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 7f89d5e..9817327 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -107,7 +107,78 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
 
   const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");
 
+  if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") &&
+      !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) {
+    // check if we need to set CPACK_RPM_DEBUGINFO_PACKAGE because non of
+    // the components is setting per component debuginfo package variable
+    bool shouldSet = true;
+
+    if (ignoreGroup) {
+      std::map<std::string, cmCPackComponent>::iterator compIt;
+      for (compIt = this->Components.begin(); compIt != this->Components.end();
+           ++compIt) {
+        std::string component(compIt->first);
+        std::transform(component.begin(), component.end(), component.begin(),
+                       ::toupper);
+
+        if (this->IsOn("CPACK_RPM_" + compIt->first + "_DEBUGINFO_PACKAGE") ||
+            this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
+          shouldSet = false;
+          break;
+        }
+      }
+    } else {
+      std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
+      for (compGIt = this->ComponentGroups.begin();
+           compGIt != this->ComponentGroups.end(); ++compGIt) {
+        std::string component(compGIt->first);
+        std::transform(component.begin(), component.end(), component.begin(),
+                       ::toupper);
+
+        if (this->IsOn("CPACK_RPM_" + compGIt->first + "_DEBUGINFO_PACKAGE") ||
+            this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
+          shouldSet = false;
+          break;
+        }
+      }
+
+      if (shouldSet) {
+        std::map<std::string, cmCPackComponent>::iterator compIt;
+        for (compIt = this->Components.begin();
+             compIt != this->Components.end(); ++compIt) {
+          // Does the component belong to a group?
+          if (compIt->second.Group == CM_NULLPTR) {
+            std::string component(compIt->first);
+            std::transform(component.begin(), component.end(),
+                           component.begin(), ::toupper);
+
+            if (this->IsOn("CPACK_RPM_" + compIt->first +
+                           "_DEBUGINFO_PACKAGE") ||
+                this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
+              shouldSet = false;
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    if (shouldSet) {
+      cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Setting "
+                      << "CPACK_RPM_DEBUGINFO_PACKAGE because "
+                      << "CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is set but "
+                      << " none of the "
+                      << "CPACK_RPM_<component>_DEBUGINFO_PACKAGE variables "
+                      << "are set." << std::endl);
+      this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON");
+    }
+  }
+
   if (mainComponent) {
+    if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
+      this->SetOption("GENERATE_SPEC_PARTS", "ON");
+    }
+
     std::string mainComponentUpper(mainComponent);
     std::transform(mainComponentUpper.begin(), mainComponentUpper.end(),
                    mainComponentUpper.begin(), ::toupper);
@@ -163,6 +234,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
       }
 
       if (retval) {
+        this->SetOption("GENERATE_SPEC_PARTS", "OFF");
+
         if (mainCompGIt != this->ComponentGroups.end()) {
           retval &= PackageOnePack(initialTopLevel, mainCompGIt->first);
         } else if (mainCompIt != this->Components.end()) {
@@ -197,6 +270,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
       }
 
       if (retval) {
+        this->SetOption("GENERATE_SPEC_PARTS", "OFF");
+
         if (mainCompIt != this->Components.end()) {
           retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
         } else {
@@ -206,7 +281,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
         }
       }
     }
-  } else {
+  } else if (!this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") ||
+             this->Components.size() == 1) {
     // The default behavior is to have one package by component group
     // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
     if (!ignoreGroup) {
@@ -241,6 +317,12 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
         retval &= PackageOnePack(initialTopLevel, compIt->first);
       }
     }
+  } else {
+    cmCPackLogger(
+      cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT not set but"
+        << " it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE"
+        << " being set.\n");
+    retval = 0;
   }
 
   if (retval) {
@@ -259,6 +341,10 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
   packageFileNames.clear();
   std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
 
+  if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
+    this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON");
+  }
+
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                 "Packaging all groups in one package..."
                 "(CPACK_COMPONENTS_ALL_[GROUPS_]IN_ONE_PACKAGE is set)"
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-ExpectedFiles.cmake b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-ExpectedFiles.cmake
new file mode 100644
index 0000000..dc49343
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-ExpectedFiles.cmake
@@ -0,0 +1,30 @@
+set(whitespaces_ "[\t\n\r ]*")
+
+set(EXPECTED_FILES_COUNT "0")
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo")
+  set(EXPECTED_FILES_COUNT "4")
+  set(EXPECTED_FILE_1 "single_debuginfo-0.1.1-1.*.rpm")
+  set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/test_prog$")
+  set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm")
+  set(EXPECTED_FILE_CONTENT_2 "^/usr/bar${whitespaces_}/usr/bar/CMakeLists.txt$")
+  set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm")
+  set(EXPECTED_FILE_CONTENT_3 "^/usr/bas${whitespaces_}/usr/bas/libtest_lib.so$")
+
+  set(EXPECTED_FILE_4 "single_debuginfo-debuginfo*.rpm")
+  set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo")
+  set(EXPECTED_FILES_COUNT "2")
+  set(EXPECTED_FILE_1 "single_debuginfo-0*-applications.rpm")
+  set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/test_prog$")
+
+  set(EXPECTED_FILE_2 "single_debuginfo-applications-debuginfo*.rpm")
+  set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_components")
+  set(EXPECTED_FILES_COUNT "2")
+  set(EXPECTED_FILE_1 "single_debuginfo-0*.rpm")
+  set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/test_prog$")
+
+  set(EXPECTED_FILE_2 "single_debuginfo-debuginfo*.rpm")
+  set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
+endif()
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_components-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_components-stderr.txt
new file mode 100644
index 0000000..d80939f
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_components-stderr.txt
@@ -0,0 +1 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_components-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_debuginfo-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_debuginfo-stderr.txt
new file mode 100644
index 0000000..86396db
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_debuginfo-stderr.txt
@@ -0,0 +1,3 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-headers.spec
+CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-libs.spec
+CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_main_component-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_main_component-stderr.txt
new file mode 100644
index 0000000..454283c
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_main_component-stderr.txt
@@ -0,0 +1 @@
+CPack Error: CPACK_RPM_MAIN_COMPONENT not set but it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE being set.
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component-stderr.txt
new file mode 100644
index 0000000..080c4ff
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component-stderr.txt
@@ -0,0 +1 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-one_component-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-applications.spec$
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_main-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_main-stderr.txt
new file mode 100644
index 0000000..665597c
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_main-stderr.txt
@@ -0,0 +1 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-one_component_main-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_no_debuginfo-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_no_debuginfo-stderr.txt
new file mode 100644
index 0000000..b64b1f5
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_no_debuginfo-stderr.txt
@@ -0,0 +1 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-one_component_no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-applications.spec$
diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-valid-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-valid-stderr.txt
new file mode 100644
index 0000000..f4c1bef
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-valid-stderr.txt
@@ -0,0 +1,3 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-valid-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-headers.spec
+CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-valid-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-libs.spec
+CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-valid-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 45dbcea..474ee33 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -19,5 +19,6 @@ run_cpack_test(INSTALL_SCRIPTS "RPM" false)
 run_cpack_test(DEB_GENERATE_SHLIBS "DEB" true)
 run_cpack_test(DEB_GENERATE_SHLIBS_LDCONFIG "DEB" true)
 run_cpack_test(DEBUGINFO "RPM" true)
+run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component;one_component;one_component_main;no_debuginfo;one_component_no_debuginfo;no_components;valid" "RPM" true)
 run_cpack_test(LONG_FILENAMES "DEB" false)
 run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false)
diff --git a/Tests/RunCMake/CPack/SINGLE_DEBUGINFO.cmake b/Tests/RunCMake/CPack/SINGLE_DEBUGINFO.cmake
new file mode 100644
index 0000000..ae4995e
--- /dev/null
+++ b/Tests/RunCMake/CPack/SINGLE_DEBUGINFO.cmake
@@ -0,0 +1,56 @@
+set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
+
+# PGI compiler doesn't add build id to binaries by default
+if(CMAKE_CXX_COMPILER_ID STREQUAL "PGI")
+  string(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--build-id")
+  string(APPEND CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id")
+endif()
+
+if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "no_components")
+  set(CPACK_RPM_COMPONENT_INSTALL "ON")
+endif()
+
+set(CMAKE_BUILD_TYPE Debug)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.hpp"
+    "int test_lib();\n")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp"
+    "#include \"test_lib.hpp\"\nint test_lib() {return 0;}\n")
+add_library(test_lib SHARED "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+    "#include \"test_lib.hpp\"\nint main() {return test_lib();}\n")
+add_executable(test_prog "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+target_link_libraries(test_prog test_lib)
+
+install(TARGETS test_prog DESTINATION foo COMPONENT applications)
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_main_component"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo")
+  install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers)
+  install(TARGETS test_lib DESTINATION bas COMPONENT libs)
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo")
+  set(CPACK_COMPONENTS_ALL applications)
+endif()
+
+set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON)
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo")
+  set(CPACK_RPM_MAIN_COMPONENT "applications")
+  set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
+endif()
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_main_component"
+  OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component")
+  set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON)
+  set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON)
+endif()
+
+set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/src")
+
+set(CPACK_PACKAGE_NAME "single_debuginfo")

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=758f58b4a18fbb512edd1baf520017e816fee20b
commit 758f58b4a18fbb512edd1baf520017e816fee20b
Author:     Domen Vrankar <domen.vrankar at gmail.com>
AuthorDate: Wed Oct 5 00:43:28 2016 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Oct 7 09:19:04 2016 -0400

    CPack/RPM learned defining main component
    
    Main component rpm package is generated
    without component suffix in filename
    and package name.

diff --git a/Help/release/dev/cpack-rpm-single-debuginfo.rst b/Help/release/dev/cpack-rpm-single-debuginfo.rst
new file mode 100644
index 0000000..281a988
--- /dev/null
+++ b/Help/release/dev/cpack-rpm-single-debuginfo.rst
@@ -0,0 +1,7 @@
+cpack-rpm-single-debuginfo
+--------------------------
+
+* The :module:`CPackRPM` module learned to generate main component package
+  which forces generation of a rpm for defined component without component
+  suffix in filename and package name.
+  See :variable:`CPACK_RPM_MAIN_COMPONENT` variable.
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index 15b62c7..2c8c0e0 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -95,6 +95,17 @@
 #    and it is up to the packager to set the variables in a manner that will
 #    prevent such errors.
 #
+# .. variable:: CPACK_RPM_MAIN_COMPONENT
+#
+#  Main component that is packaged without component suffix.
+#
+#  * Mandatory : NO
+#  * Default   : -
+#
+#  This variable can be set to any component or group name so that component or
+#  group rpm package is generated without component suffix in filename and
+#  package name.
+#
 # .. variable:: CPACK_RPM_PACKAGE_VERSION
 #
 #  The RPM package version.
@@ -1649,10 +1660,16 @@ function(cpack_rpm_generate_package)
   endif()
 
   if(CPACK_RPM_PACKAGE_COMPONENT)
-    string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}")
-    cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_NAME"
-      "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME"
-      "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME")
+    string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}"
+      CPACK_RPM_MAIN_COMPONENT_UPPER)
+
+    if(NOT CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER)
+      string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}")
+
+      cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_NAME"
+        "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME"
+        "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME")
+    endif()
   endif()
 
   # CPACK_RPM_PACKAGE_VERSION (mandatory)
@@ -2164,7 +2181,15 @@ ${TMP_DEBUGINFO_ADDITIONAL_SOURCES}
       cmake_policy(POP)
     else()
       # old file name format for back compatibility
-      set(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}")
+      string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}"
+        CPACK_RPM_MAIN_COMPONENT_UPPER)
+
+      if(CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER)
+        # this is the main component so ignore the component filename part
+        set(CPACK_RPM_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.rpm")
+      else()
+        set(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}")
+      endif()
     endif()
     # else example:
     #set(CPACK_RPM_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}-${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm")
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index bd55206..7f89d5e 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -105,38 +105,141 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
   packageFileNames.clear();
   std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
 
-  // The default behavior is to have one package by component group
-  // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
-  if (!ignoreGroup) {
-    std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
-    for (compGIt = this->ComponentGroups.begin();
-         compGIt != this->ComponentGroups.end(); ++compGIt) {
-      cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
-                      << compGIt->first << std::endl);
-      retval &= PackageOnePack(initialTopLevel, compGIt->first);
+  const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");
+
+  if (mainComponent) {
+    std::string mainComponentUpper(mainComponent);
+    std::transform(mainComponentUpper.begin(), mainComponentUpper.end(),
+                   mainComponentUpper.begin(), ::toupper);
+
+    // The default behavior is to have one package by component group
+    // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
+    if (!ignoreGroup) {
+      std::map<std::string, cmCPackComponentGroup>::iterator mainCompGIt =
+        this->ComponentGroups.end();
+
+      std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
+      for (compGIt = this->ComponentGroups.begin();
+           compGIt != this->ComponentGroups.end(); ++compGIt) {
+        std::string component(compGIt->first);
+        std::transform(component.begin(), component.end(), component.begin(),
+                       ::toupper);
+
+        if (mainComponentUpper == component) {
+          // main component will be handled last
+          mainCompGIt = compGIt;
+          continue;
+        }
+
+        cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
+                        << compGIt->first << std::endl);
+        retval &= PackageOnePack(initialTopLevel, compGIt->first);
+      }
+      // Handle Orphan components (components not belonging to any groups)
+      std::map<std::string, cmCPackComponent>::iterator mainCompIt =
+        this->Components.end();
+      std::map<std::string, cmCPackComponent>::iterator compIt;
+      for (compIt = this->Components.begin(); compIt != this->Components.end();
+           ++compIt) {
+        // Does the component belong to a group?
+        if (compIt->second.Group == CM_NULLPTR) {
+          std::string component(compIt->first);
+          std::transform(component.begin(), component.end(), component.begin(),
+                         ::toupper);
+
+          if (mainComponentUpper == component) {
+            // main component will be handled last
+            mainCompIt = compIt;
+            continue;
+          }
+
+          cmCPackLogger(
+            cmCPackLog::LOG_VERBOSE, "Component <"
+              << compIt->second.Name
+              << "> does not belong to any group, package it separately."
+              << std::endl);
+          retval &= PackageOnePack(initialTopLevel, compIt->first);
+        }
+      }
+
+      if (retval) {
+        if (mainCompGIt != this->ComponentGroups.end()) {
+          retval &= PackageOnePack(initialTopLevel, mainCompGIt->first);
+        } else if (mainCompIt != this->Components.end()) {
+          retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
+        } else {
+          cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+                          << " to non existing component.\n");
+          retval = 0;
+        }
+      }
     }
-    // Handle Orphan components (components not belonging to any groups)
-    std::map<std::string, cmCPackComponent>::iterator compIt;
-    for (compIt = this->Components.begin(); compIt != this->Components.end();
-         ++compIt) {
-      // Does the component belong to a group?
-      if (compIt->second.Group == CM_NULLPTR) {
-        cmCPackLogger(
-          cmCPackLog::LOG_VERBOSE, "Component <"
-            << compIt->second.Name
-            << "> does not belong to any group, package it separately."
-            << std::endl);
+    // CPACK_COMPONENTS_IGNORE_GROUPS is set
+    // We build 1 package per component
+    else {
+      std::map<std::string, cmCPackComponent>::iterator mainCompIt =
+        this->Components.end();
+
+      std::map<std::string, cmCPackComponent>::iterator compIt;
+      for (compIt = this->Components.begin(); compIt != this->Components.end();
+           ++compIt) {
+        std::string component(compIt->first);
+        std::transform(component.begin(), component.end(), component.begin(),
+                       ::toupper);
+
+        if (mainComponentUpper == component) {
+          // main component will be handled last
+          mainCompIt = compIt;
+          continue;
+        }
+
         retval &= PackageOnePack(initialTopLevel, compIt->first);
       }
+
+      if (retval) {
+        if (mainCompIt != this->Components.end()) {
+          retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
+        } else {
+          cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+                          << " to non existing component.\n");
+          retval = 0;
+        }
+      }
     }
-  }
-  // CPACK_COMPONENTS_IGNORE_GROUPS is set
-  // We build 1 package per component
-  else {
-    std::map<std::string, cmCPackComponent>::iterator compIt;
-    for (compIt = this->Components.begin(); compIt != this->Components.end();
-         ++compIt) {
-      retval &= PackageOnePack(initialTopLevel, compIt->first);
+  } else {
+    // The default behavior is to have one package by component group
+    // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
+    if (!ignoreGroup) {
+      std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
+      for (compGIt = this->ComponentGroups.begin();
+           compGIt != this->ComponentGroups.end(); ++compGIt) {
+        cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
+                        << compGIt->first << std::endl);
+        retval &= PackageOnePack(initialTopLevel, compGIt->first);
+      }
+      // Handle Orphan components (components not belonging to any groups)
+      std::map<std::string, cmCPackComponent>::iterator compIt;
+      for (compIt = this->Components.begin(); compIt != this->Components.end();
+           ++compIt) {
+        // Does the component belong to a group?
+        if (compIt->second.Group == CM_NULLPTR) {
+          cmCPackLogger(
+            cmCPackLog::LOG_VERBOSE, "Component <"
+              << compIt->second.Name
+              << "> does not belong to any group, package it separately."
+              << std::endl);
+          retval &= PackageOnePack(initialTopLevel, compIt->first);
+        }
+      }
+    }
+    // CPACK_COMPONENTS_IGNORE_GROUPS is set
+    // We build 1 package per component
+    else {
+      std::map<std::string, cmCPackComponent>::iterator compIt;
+      for (compIt = this->Components.begin(); compIt != this->Components.end();
+           ++compIt) {
+        retval &= PackageOnePack(initialTopLevel, compIt->first);
+      }
     }
   }
 
diff --git a/Tests/RunCMake/CPack/MAIN_COMPONENT.cmake b/Tests/RunCMake/CPack/MAIN_COMPONENT.cmake
new file mode 100644
index 0000000..99c6cae
--- /dev/null
+++ b/Tests/RunCMake/CPack/MAIN_COMPONENT.cmake
@@ -0,0 +1,14 @@
+set(CPACK_RPM_COMPONENT_INSTALL "ON")
+
+install(FILES CMakeLists.txt DESTINATION foo COMPONENT applications)
+install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers)
+install(FILES CMakeLists.txt DESTINATION bas COMPONENT libs)
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "invalid")
+  set(CPACK_RPM_MAIN_COMPONENT "")
+else()
+  set(CPACK_RPM_MAIN_COMPONENT "applications")
+  set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
+endif()
+
+set(CPACK_PACKAGE_NAME "main_component")
diff --git a/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-ExpectedFiles.cmake b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-ExpectedFiles.cmake
new file mode 100644
index 0000000..69603dd
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-ExpectedFiles.cmake
@@ -0,0 +1,13 @@
+set(whitespaces_ "[\t\n\r ]*")
+
+set(EXPECTED_FILES_COUNT "0")
+
+if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "invalid")
+  set(EXPECTED_FILES_COUNT "3")
+  set(EXPECTED_FILE_1 "main_component-0.1.1-1.*.rpm")
+  set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/CMakeLists.txt$")
+  set(EXPECTED_FILE_2 "main_component*-headers.rpm")
+  set(EXPECTED_FILE_CONTENT_2 "^/usr/bar${whitespaces_}/usr/bar/CMakeLists.txt$")
+  set(EXPECTED_FILE_3 "main_component*-libs.rpm")
+  set(EXPECTED_FILE_CONTENT_3 "^/usr/bas${whitespaces_}/usr/bas/CMakeLists.txt$")
+endif()
diff --git a/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-found-stderr.txt b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-found-stderr.txt
new file mode 100644
index 0000000..dff163d
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-found-stderr.txt
@@ -0,0 +1,3 @@
+^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/MAIN_COMPONENT-build-found-subtest/_CPack_Packages/.*/RPM/SPECS/main_component-headers.spec
+CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/MAIN_COMPONENT-build-found-subtest/_CPack_Packages/.*/RPM/SPECS/main_component-libs.spec
+CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/MAIN_COMPONENT-build-found-subtest/_CPack_Packages/.*/RPM/SPECS/main_component.spec$
diff --git a/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-invalid-stderr.txt b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-invalid-stderr.txt
new file mode 100644
index 0000000..4d8ac6e
--- /dev/null
+++ b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-invalid-stderr.txt
@@ -0,0 +1 @@
+CPACK_RPM_MAIN_COMPONENT set to non existing component.
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 60d42ac..45dbcea 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -12,6 +12,7 @@ run_cpack_test(DEPENDENCIES "RPM;DEB" true)
 run_cpack_test(EMPTY_DIR "RPM;DEB;TGZ" true)
 run_cpack_test(COMPONENTS_EMPTY_DIR "RPM;DEB;TGZ" true)
 run_cpack_test(CUSTOM_NAMES "RPM;DEB" true)
+run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM" false)
 run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false)
 run_cpack_test(RPM_DIST "RPM" false)
 run_cpack_test(INSTALL_SCRIPTS "RPM" false)

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list