CPackRPM honors all the different ways of packaging components

RPM cannot easily 'merge' differents directory into a single RPM
with shared prefix. So more flexibility has been added to generic
CPackGenerator in order to let the specific generator chose the
local installation directory for each component.
This commit is contained in:
Eric NOULARD 2011-02-06 21:23:10 +01:00
parent 76976a59e9
commit 494bb8ada7
5 changed files with 229 additions and 23 deletions

View File

@ -226,8 +226,6 @@ int cmCPackArchiveGenerator::PackageFiles()
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
<< toplevel << std::endl);
PrepareGroupingKind();
if (SupportsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL GROUPS or ALL COMPONENTS in ONE package has been requested

View File

@ -684,7 +684,14 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
if (componentInstall)
{
tempInstallDirectory += "/";
tempInstallDirectory += installComponent;
// Some CPack generators would rather chose
// the local installation directory suffix.
// Some (e.g. RPM) use
// one install directory for each component **GROUP**
// instead of the default
// one install directory for each component.
tempInstallDirectory +=
GetComponentInstallDirNameSuffix(installComponent);
}
if (!setDestDir)
@ -873,6 +880,12 @@ int cmCPackGenerator::DoPackage()
return 0;
}
// Digest Component grouping specification
if ( !this->PrepareGroupingKind() )
{
return 0;
}
if ( cmSystemTools::IsOn(
this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY")) )
{
@ -1251,11 +1264,11 @@ int cmCPackGenerator::PrepareGroupingKind()
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
<< this->Name << "]"
<< " requested component grouping = "<< groupingType <<std::endl);
if (groupingType == "ALL_GROUP_IN_ONE")
if (groupingType == "ALL_GROUPS_IN_ONE")
{
allGroupInOne = true;
}
else if (groupingType == "ALL_COMPONENT_IN_ONE")
else if (groupingType == "ALL_COMPONENTS_IN_ONE")
{
allComponentInOne = true;
}
@ -1268,11 +1281,19 @@ int cmCPackGenerator::PrepareGroupingKind()
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);
<< "> UNKNOWN not in (ALL_GROUPS_IN_ONE,"
"ALL_COMPONENTS_IN_ONE,IGNORE)" <<std::endl);
}
}
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
<< this->Name << "]"
<< " requested component grouping = ("
<< "ALL_GROUPS_IN_ONE=" << allGroupInOne
<< ", ALL_COMPONENTS_IN_ONE=" << allComponentInOne
<< ", IGNORE_GROUPS=" << ignoreComponentGroup
<< ")"
<< std::endl);
// Some components were defined but NO group
// force ignoreGroups
if (this->ComponentGroups.empty() && (!this->Components.empty())
@ -1288,6 +1309,11 @@ int cmCPackGenerator::PrepareGroupingKind()
return 1;
}
std::string cmCPackGenerator::GetComponentInstallDirNameSuffix(
const std::string& componentName) {
return componentName;
}
//----------------------------------------------------------------------
bool cmCPackGenerator::SupportsComponentInstallation() const
{

View File

@ -131,6 +131,19 @@ protected:
*/
virtual int PrepareGroupingKind();
/**
* Some CPack generators may prefer to have
* CPack install all components belonging to the same
* [component] group to be install in the same directory.
* The default behavior is to install each component in
* a separate directory.
* @param[in] componentName the name of the component to be installed
* @return the name suffix the generator wants for the specified component
* default is "componentName"
*/
virtual std::string GetComponentInstallDirNameSuffix(
const std::string& componentName);
/**
* Package the list of files and/or components which
* has been prepared by the beginning of DoPackage.

View File

@ -35,26 +35,63 @@ int cmCPackRPMGenerator::InitializeInternal()
}
//----------------------------------------------------------------------
int cmCPackRPMGenerator::PackageFiles()
int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
{
int retval = 1;
/* Digest Component grouping specification */
retval = PrepareGroupingKind();
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
<< toplevel << std::endl);
/* Reset package file name list it will be populated during the
* component packaging run*/
packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
/* Are we in the component packaging case */
if (SupportsComponentInstallation() & (!this->ComponentGroups.empty()))
// 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);
// Begin the archive for this group
std::string localToplevel(initialTopLevel);
std::string packageFileName(
cmSystemTools::GetParentDirectory(toplevel.c_str())
);
std::string outputFileName(
std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
+"-"+compGIt->first + this->GetOutputExtension()
);
localToplevel += "/"+ compGIt->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());
// Tell CPackRPM.cmake the name of the component GROUP.
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",compGIt->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);
}
}
// CPACK_COMPONENTS_IGNORE_GROUPS is set
// We build 1 package per component
else
{
/* 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 )
compIt!=this->Components.end(); ++compIt )
{
std::string localToplevel(initialTopLevel);
std::string packageFileName(
@ -82,12 +119,101 @@ int cmCPackRPMGenerator::PackageFiles()
"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 */
return retval;
}
//----------------------------------------------------------------------
int cmCPackRPMGenerator::PackageComponentsAllInOne(bool allComponent)
{
int retval = 1;
std::string compInstDirName;
/* Reset package file name list it will be populated during the
* component packaging run*/
packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
// all GROUP in one vs all COMPONENT in one
if (allComponent)
{
compInstDirName = "ALL_COMPONENTS_IN_ONE";
}
else
{
compInstDirName = "ALL_GROUPS_IN_ONE";
}
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging all groups in one package..."
"(CPACK_COMPONENTS_ALL_[GROUPS_]IN_ONE_PACKAGE is set)"
<< std::endl);
// The ALL GROUPS in ONE package case
std::string localToplevel(initialTopLevel);
std::string packageFileName(
cmSystemTools::GetParentDirectory(toplevel.c_str())
);
std::string outputFileName(
std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
+"-ALL"+ this->GetOutputExtension()
);
// all GROUP in one vs all COMPONENT in one
localToplevel += "/"+compInstDirName;
/* 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());
// Tell CPackRPM.cmake the name of the component GROUP.
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",compInstDirName.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);
return 1;
}
//----------------------------------------------------------------------
int cmCPackRPMGenerator::PackageFiles()
{
int retval = 1;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
<< toplevel << std::endl);
/* Are we in the component packaging case */
if (SupportsComponentInstallation()) {
// 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.
if (allComponentInOne ||
(allGroupInOne && (!this->ComponentGroups.empty()))
)
{
return PackageComponentsAllInOne(allComponentInOne);
}
// CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
// There will be 1 package for each component group
// however one may require to ignore component group and
// in this case you'll get 1 package for each component.
else if ((!this->ComponentGroups.empty()) || (ignoreComponentGroup))
{
return PackageComponents(ignoreComponentGroup);
}
}
// CASE 3 : NON COMPONENT package.
else
{
if (!this->ReadListFile("CPackRPM.cmake"))
@ -118,3 +244,33 @@ bool cmCPackRPMGenerator::SupportsComponentInstallation() const
}
}
std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
const std::string& componentName)
{
if (ignoreComponentGroup) {
return componentName;
}
if (allComponentInOne) {
return std::string("ALL_COMPONENTS_IN_ONE");
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
std::string groupVar = "CPACK_COMPONENT_" +
cmSystemTools::UpperCase(componentName) + "_GROUP";
if (NULL != GetOption(groupVar.c_str()))
{
if (allGroupInOne)
{
return std::string("ALL_GROUPS_IN_ONE");
}
else
{
return std::string(GetOption(groupVar.c_str()));
}
}
else
{
return componentName;
}
}

View File

@ -38,8 +38,21 @@ public:
protected:
virtual int InitializeInternal();
virtual int PackageFiles();
/**
* The method used to package files when component
* install is used. This will create one
* archive for each component group.
*/
int PackageComponents(bool ignoreGroup);
/**
* Special case of component install where all
* components will be put in a single installer.
*/
int PackageComponentsAllInOne(bool allComponent);
virtual const char* GetOutputExtension() { return ".rpm"; }
virtual bool SupportsComponentInstallation() const;
virtual std::string GetComponentInstallDirNameSuffix(
const std::string& componentName);
};