소스 검색

CPackRPM add basic component support to CPackRPM

basic means 1 RPM per component and no dependency handling
this implies some CPackGenerator refactoring
Eric NOULARD 15 년 전
부모
커밋
2c84d169b3

+ 24 - 13
Modules/CPackRPM.cmake

@@ -331,7 +331,7 @@ ELSE(CPACK_RPM_COMPRESSION_TYPE)
 ENDIF(CPACK_RPM_COMPRESSION_TYPE)
 
 if(CPACK_PACKAGE_RELOCATABLE)
-    set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE)
+  set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE)
 endif(CPACK_PACKAGE_RELOCATABLE)
 if(CPACK_RPM_PACKAGE_RELOCATABLE)
   if(CPACK_RPM_PACKAGE_DEBUG)
@@ -453,6 +453,17 @@ SET(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}")
 #STRING(REGEX REPLACE " " "\\\\ " CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}")
 SET(CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}")
 
+
+# Are we packaging components ?
+IF(CPACK_RPM_PACKAGE_COMPONENT)
+  SET(CPACK_RPM_PACKAGE_COMPONENT_PART_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}")
+  SET(CPACK_RPM_PACKAGE_COMPONENT_PART_PATH "/${CPACK_RPM_PACKAGE_COMPONENT}")
+  SET(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${CPACK_RPM_PACKAGE_COMPONENT}")
+ELSE(CPACK_RPM_PACKAGE_COMPONENT)
+  SET(CPACK_RPM_PACKAGE_COMPONENT_PART_NAME "")
+  SET(CPACK_RPM_PACKAGE_COMPONENT_PART_PATH "")
+  SET(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}")
+ENDIF(CPACK_RPM_PACKAGE_COMPONENT)
 # Use files tree to construct files command (spec file)
 # We should not forget to include symlinks (thus -o -type l)
 # We must remove the './' due to the local search and escape the
@@ -460,10 +471,10 @@ SET(CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}")
 # Then we must authorize any man pages extension (adding * at the end)
 # because rpmbuild may automatically compress those files
 EXECUTE_PROCESS(COMMAND find -type f -o -type l
-               COMMAND sed {s:.*/man.*/.*:&*:}
-               COMMAND sed {s/\\.\\\(.*\\\)/\"\\1\"/}
-               WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}"
-               OUTPUT_VARIABLE CPACK_RPM_INSTALL_FILES)
+                COMMAND sed {s:.*/man.*/.*:&*:}
+                COMMAND sed {s/\\.\\\(.*\\\)/\"\\1\"/}
+                WORKING_DIRECTORY "${WDIR}"
+                OUTPUT_VARIABLE CPACK_RPM_INSTALL_FILES)
 
 if (CPACK_ABSOLUTE_DESTINATION_FILES)
   IF(CPACK_RPM_PACKAGE_DEBUG)
@@ -494,7 +505,7 @@ if (CPACK_ABSOLUTE_DESTINATION_FILES)
 endif(CPACK_ABSOLUTE_DESTINATION_FILES)
 
 # The name of the final spec file to be used by rpmbuild
-SET(CPACK_RPM_BINARY_SPECFILE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_NAME}.spec")
+SET(CPACK_RPM_BINARY_SPECFILE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.spec")
 
 # Print out some debug information if we were asked for that
 IF(CPACK_RPM_PACKAGE_DEBUG)
@@ -517,7 +528,7 @@ ENDIF(CPACK_RPM_PACKAGE_DEBUG)
 IF(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE)
    FILE(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in
       "# -*- rpm-spec -*-
-BuildRoot:      \@CPACK_RPM_DIRECTORY\@/\@CPACK_PACKAGE_FILE_NAME\@
+BuildRoot:      \@CPACK_RPM_DIRECTORY\@/\@CPACK_PACKAGE_FILE_NAME\@\@CPACK_RPM_PACKAGE_COMPONENT_PART_PATH\@
 Summary:        \@CPACK_RPM_PACKAGE_SUMMARY\@
 Name:           \@CPACK_RPM_PACKAGE_NAME\@
 Version:        \@CPACK_RPM_PACKAGE_VERSION\@
@@ -608,15 +619,15 @@ IF(RPMBUILD_EXECUTABLE)
   # Now call rpmbuild using the SPECFILE
   EXECUTE_PROCESS(
     COMMAND "${RPMBUILD_EXECUTABLE}" -bb
-            --buildroot "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}"
+            --buildroot "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
             "${CPACK_RPM_BINARY_SPECFILE}"
-    WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}"
-    ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild.err"
-    OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild.out")
+    WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
+    ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err"
+    OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out")
   IF(CPACK_RPM_PACKAGE_DEBUG)
     MESSAGE("CPackRPM:Debug: You may consult rpmbuild logs in: ")
-    MESSAGE("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild.err")
-    MESSAGE("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild.out")
+    MESSAGE("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err")
+    MESSAGE("CPackRPM:Debug:    - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out")
   ENDIF(CPACK_RPM_PACKAGE_DEBUG)
 ELSE(RPMBUILD_EXECUTABLE)
   IF(ALIEN_EXECUTABLE)

+ 5 - 60
Source/CPack/cmCPackArchiveGenerator.cxx

@@ -105,12 +105,12 @@ if (!archive) \
   }
 
 //----------------------------------------------------------------------
-int cmCPackArchiveGenerator::PackageComponents(bool ignoreComponentGroup)
+int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
 {
   packageFileNames.clear();
   // The default behavior is to have one package by component group
   // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
-  if (!ignoreComponentGroup)
+  if (!ignoreGroup)
     {
     std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
     for (compGIt=this->ComponentGroups.begin();
@@ -170,7 +170,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreComponentGroup)
 }
 
 //----------------------------------------------------------------------
-int cmCPackArchiveGenerator::PackageComponentsAllInOne(bool allComponentInOne)
+int cmCPackArchiveGenerator::PackageComponentsAllInOne(bool allComponent)
 {
   // reset the package file names
   packageFileNames.clear();
@@ -185,7 +185,7 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne(bool allComponentInOne)
   DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive);
 
   // The ALL GROUP in ONE package case
-  if (! allComponentInOne) {
+  if (! allComponent) {
     // iterate over the component groups
     std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
     for (compGIt=this->ComponentGroups.begin();
@@ -226,63 +226,8 @@ int cmCPackArchiveGenerator::PackageFiles()
   cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
                 << toplevel << std::endl);
 
-  // The default behavior is to create 1 package by component group
-  // unless the user asked to put all COMPONENTS in a single package
-  bool allGroupInOne = (NULL !=
-                        (this->GetOption(
-                          "CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE")));
-  bool allComponentInOne = (NULL !=
-                            (this->GetOption(
-                              "CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE")));
-  bool ignoreComponentGroup = ( NULL !=
-                                (this->GetOption(
-                                  "CPACK_COMPONENTS_IGNORE_GROUPS")));
+  PrepareGroupingKind();
 
-  std::string groupingType;
-
-  // Second way to specify grouping
-  if (NULL != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
-     groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
-  }
-
-  if (groupingType.length()>0)
-    {
-    cmCPackLogger(cmCPackLog::LOG_VERBOSE,  "["
-        << this->Name << "]"
-        << " requested component grouping = "<< groupingType <<std::endl);
-    if (groupingType == "ALL_GROUP_IN_ONE")
-      {
-      allGroupInOne = true;
-      }
-    else if (groupingType == "ALL_COMPONENT_IN_ONE")
-      {
-      allComponentInOne = true;
-      }
-    else if (groupingType == "IGNORE")
-      {
-      ignoreComponentGroup = true;
-      }
-    else
-      {
-      cmCPackLogger(cmCPackLog::LOG_WARNING, "["
-              << this->Name << "]"
-              << " requested component grouping type <"<< groupingType
-              << "> UNKNOWN not in (ALL_GROUP_IN_ONE,"
-                    "ALL_COMPONENT_IN_ONE,IGNORE)" <<std::endl);
-      }
-    }
-
-  // Some components were defined but NO group
-  // force ignoreGroups
-  if (this->ComponentGroups.empty() && (!this->Components.empty())
-      && (!ignoreComponentGroup)) {
-    cmCPackLogger(cmCPackLog::LOG_WARNING, "["
-              << this->Name << "]"
-              << " Some Components defined but NO component group:"
-              << " Ignoring component group."
-              << std::endl);
-    ignoreComponentGroup = true;
-  }
   // CASE 1 : COMPONENT ALL-IN-ONE package
   // If ALL GROUPS or ALL COMPONENTS in ONE package has been requested
   // then the package file is unique and should be open here.

+ 2 - 2
Source/CPack/cmCPackArchiveGenerator.h

@@ -60,12 +60,12 @@ protected:
    * install is used. This will create one
    * archive for each component group.
    */
-  int PackageComponents(bool ignoreComponentGroup);
+  int PackageComponents(bool ignoreGroup);
   /**
    * Special case of component install where all
    * components will be put in a single installer.
    */
-  int PackageComponentsAllInOne(bool allComponentInOne);
+  int PackageComponentsAllInOne(bool allComponent);
   virtual const char* GetOutputExtension() = 0;
   cmArchiveWrite::Compress Compress;
   cmArchiveWrite::Type Archive;

+ 81 - 3
Source/CPack/cmCPackGenerator.cxx

@@ -35,6 +35,9 @@ cmCPackGenerator::cmCPackGenerator()
   this->GeneratorVerbose = false;
   this->MakefileMap = 0;
   this->Logger = 0;
+  this->allGroupInOne = false;
+  this->allComponentInOne = false;
+  this->ignoreComponentGroup = false;
 }
 
 //----------------------------------------------------------------------
@@ -220,7 +223,7 @@ int cmCPackGenerator::InstallProject()
 
   // If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
   // then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
-  // This is used in Source packageing
+  // This is used in Source packaging
   if ( !this->InstallProjectViaInstalledDirectories(
       setDestDir, tempInstallDirectory) )
     {
@@ -691,7 +694,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
           //
           // If DESTDIR has been 'internally set ON' this means that
           // the underlying CPack specific generator did ask for that
-          // In this case we may overrode CPACK_INSTALL_PREFIX with
+          // In this case we may override CPACK_INSTALL_PREFIX with
           // CPACK_PACKAGING_INSTALL_PREFIX
           // I know this is tricky and awkward but it's the price for
           // CPACK_SET_DESTDIR backward compatibility.
@@ -727,7 +730,18 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
             {
             dir = tempInstallDirectory + "/" + dir;
             }
-
+          /*
+           *  We must re-set DESTDIR for each component
+           *  We must not add the CPACK_INSTALL_PREFIX part because
+           *  it will be added using the override of CMAKE_INSTALL_PREFIX
+           *  The main reason for this awkward trick is that
+           *  are using DESTDIR for 2 different reasons:
+           *     - Because it was asked by the CPack Generator or the user
+           *       using CPACK_SET_DESTDIR
+           *     - Because it was already used for component install
+           *       in order to put things in subdirs...
+           */
+          cmSystemTools::PutEnv((std::string("DESTDIR=")+tempInstallDirectory).c_str());
           cmCPackLogger(cmCPackLog::LOG_DEBUG,
                         "- Creating directory: '" << dir << "'" << std::endl);
 
@@ -1195,6 +1209,70 @@ int cmCPackGenerator::CleanTemporaryDirectory()
   return 1;
 }
 
+//----------------------------------------------------------------------
+int cmCPackGenerator::PrepareGroupingKind()
+{
+  // The default behavior is to create 1 package by component group
+  // unless the user asked to put all COMPONENTS in a single package
+  allGroupInOne = (NULL !=
+                    (this->GetOption(
+                      "CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE")));
+  allComponentInOne = (NULL !=
+                        (this->GetOption(
+                          "CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE")));
+  ignoreComponentGroup = (NULL !=
+                           (this->GetOption(
+                             "CPACK_COMPONENTS_IGNORE_GROUPS")));
+
+  std::string groupingType;
+
+  // Second way to specify grouping
+  if (NULL != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
+     groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
+  }
+
+  if (groupingType.length()>0)
+    {
+    cmCPackLogger(cmCPackLog::LOG_VERBOSE,  "["
+        << this->Name << "]"
+        << " requested component grouping = "<< groupingType <<std::endl);
+    if (groupingType == "ALL_GROUP_IN_ONE")
+      {
+      allGroupInOne = true;
+      }
+    else if (groupingType == "ALL_COMPONENT_IN_ONE")
+      {
+      allComponentInOne = true;
+      }
+    else if (groupingType == "IGNORE")
+      {
+      ignoreComponentGroup = true;
+      }
+    else
+      {
+      cmCPackLogger(cmCPackLog::LOG_WARNING, "["
+              << this->Name << "]"
+              << " requested component grouping type <"<< groupingType
+              << "> UNKNOWN not in (ALL_GROUP_IN_ONE,"
+                    "ALL_COMPONENT_IN_ONE,IGNORE)" <<std::endl);
+      }
+    }
+
+  // Some components were defined but NO group
+  // force ignoreGroups
+  if (this->ComponentGroups.empty() && (!this->Components.empty())
+      && (!ignoreComponentGroup)) {
+    cmCPackLogger(cmCPackLog::LOG_WARNING, "["
+              << this->Name << "]"
+              << " Some Components defined but NO component group:"
+              << " Ignoring component group."
+              << std::endl);
+    ignoreComponentGroup = true;
+  }
+
+  return 1;
+}
+
 //----------------------------------------------------------------------
 bool cmCPackGenerator::SupportsComponentInstallation() const
 {

+ 25 - 0
Source/CPack/cmCPackGenerator.h

@@ -119,6 +119,17 @@ protected:
   virtual const char* GetOutputExtension() { return ".cpack"; }
   virtual const char* GetOutputPostfix() { return 0; }
 
+  /**
+   * Prepare requested grouping kind from CPACK_xxx vars
+   * CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE
+   * CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE
+   * CPACK_COMPONENTS_IGNORE_GROUPS
+   * or
+   * CPACK_COMPONENTS_GROUPING
+   * @return 1 on success 0 on failure.
+   */
+  virtual int PrepareGroupingKind();
+
   /**
    * Package the list of files and/or components which
    * has been prepared by the beginning of DoPackage.
@@ -200,6 +211,20 @@ protected:
    */
   std::map<std::string, cmCPackComponent> Components;
   std::map<std::string, cmCPackComponentGroup> ComponentGroups;
+  /**
+   * If true All component groups will be put in a single package.
+   */
+  bool allGroupInOne;
+  /**
+   * If true All component will be put in a single package.
+   */
+  bool allComponentInOne;
+  /**
+   * If true component grouping will be ignored.
+   * You will still get 1 package for each component unless
+   * allComponentInOne is true.
+   */
+  bool ignoreComponentGroup;
 
   cmCPackLog* Logger;
 private:

+ 56 - 3
Source/CPack/cmCPackRPMGenerator.cxx

@@ -37,13 +37,66 @@ int cmCPackRPMGenerator::InitializeInternal()
 //----------------------------------------------------------------------
 int cmCPackRPMGenerator::PackageFiles()
 {
-  this->ReadListFile("CPackRPM.cmake");
+  int retval = 1;
+  /* Digest Component grouping specification */
+  retval = PrepareGroupingKind();
+  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
+                  << toplevel << std::endl);
+
+  /* Are we in the component packaging case */
+  if (!this->ComponentGroups.empty())
+    {
+    /* Reset package file name list it will be populated during the
+     * component packaging run*/
+    packageFileNames.clear();
+    std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
+    /* One Package per component CASE */
+    /* Iterate over components */
+    std::map<std::string, cmCPackComponent>::iterator compIt;
+    for (compIt=this->Components.begin();
+        compIt!=this->Components.end(); ++compIt )
+      {
+      std::string localToplevel(initialTopLevel);
+      std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel.c_str()));
+      std::string outputFileName(std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
+        +"-"+compIt->first + this->GetOutputExtension());
+
+      localToplevel += "/"+ compIt->first;
+      /* replace the TEMP DIRECTORY with the component one */
+      this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str());
+      packageFileName += "/"+ outputFileName;
+      /* replace proposed CPACK_OUTPUT_FILE_NAME */
+      this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str());
+      /* replace the TEMPORARY package file name */
+      this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",packageFileName.c_str());
+
+      this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",compIt->first.c_str());
+      if (!this->ReadListFile("CPackRPM.cmake"))
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake" << std::endl);
+        retval = 0;
+        }
+
+      // add the generated package to package file names list
+      packageFileNames.push_back(packageFileName);
+      }
+    }
+  /* This is the non component case */
+  else
+    {
+    if (!this->ReadListFile("CPackRPM.cmake"))
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake" << std::endl);
+      retval = 0;
+      }
+    }
+
   if (!this->IsSet("RPMBUILD_EXECUTABLE")) 
     {
     cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find rpmbuild" << std::endl);
-    return 0;
+    retval = 0;
     }
-  return 1;
+  return retval;
 }
 
 

+ 1 - 0
Source/CPack/cmCPackRPMGenerator.h

@@ -39,6 +39,7 @@ protected:
   virtual int InitializeInternal();
   virtual int PackageFiles();
   virtual const char* GetOutputExtension() { return ".rpm"; }
+  virtual bool SupportsComponentInstallation() const {return true;}
 
 };