summaryrefslogtreecommitdiffstats
path: root/Source/CPack
diff options
context:
space:
mode:
authorDavid Cole <david.cole@kitware.com>2008-07-09 17:38:56 (GMT)
committerDavid Cole <david.cole@kitware.com>2008-07-09 17:38:56 (GMT)
commit71f61636b6abfe5f243374b5575019098418b4c6 (patch)
treed6ca84ec6701ed19ae98b8dfbeb321aafa81495e /Source/CPack
parent3366e6c2cd8bb2d9e30d2deb5637c840d52221a3 (diff)
downloadCMake-71f61636b6abfe5f243374b5575019098418b4c6.zip
CMake-71f61636b6abfe5f243374b5575019098418b4c6.tar.gz
CMake-71f61636b6abfe5f243374b5575019098418b4c6.tar.bz2
ENH: One more patch from Doug Gregor including PackageMaker functionality for componentized-for-the-end-user and download-some-bit-on-demand installers.
Diffstat (limited to 'Source/CPack')
-rw-r--r--Source/CPack/cmCPackComponentGroup.cxx49
-rw-r--r--Source/CPack/cmCPackComponentGroup.h14
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx289
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.h1
4 files changed, 254 insertions, 99 deletions
diff --git a/Source/CPack/cmCPackComponentGroup.cxx b/Source/CPack/cmCPackComponentGroup.cxx
new file mode 100644
index 0000000..63ad9d7
--- /dev/null
+++ b/Source/CPack/cmCPackComponentGroup.cxx
@@ -0,0 +1,49 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include "cmCPackComponentGroup.h"
+#include "cmSystemTools.h"
+#include <vector>
+#include <string>
+
+//----------------------------------------------------------------------
+unsigned long cmCPackComponent::GetInstalledSize(const char* installDir) const
+{
+ if (this->TotalSize != 0)
+ {
+ return this->TotalSize;
+ }
+
+ std::vector<std::string>::const_iterator fileIt;
+ for (fileIt = this->Files.begin(); fileIt != this->Files.end(); ++fileIt)
+ {
+ std::string path = installDir;
+ path += '/';
+ path += *fileIt;
+ this->TotalSize += cmSystemTools::FileLength(path.c_str());
+ }
+
+ return this->TotalSize;
+}
+
+//----------------------------------------------------------------------
+unsigned long
+cmCPackComponent::GetInstalledSizeInKbytes(const char* installDir) const
+{
+ unsigned long result = (GetInstalledSize(installDir) + 512) / 1024;
+ return result? result : 1;
+}
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index d080a87..e17b1b7 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -49,7 +49,7 @@ public:
class cmCPackComponent
{
public:
- cmCPackComponent() : Group(0) { }
+ cmCPackComponent() : Group(0), TotalSize(0) { }
/// The name of the component (used to reference the component).
std::string Name;
@@ -95,6 +95,18 @@ public:
/// The list of installed directories that are part of this component.
std::vector<std::string> Directories;
+
+ /// Get the total installed size of all of the files in this
+ /// component, in bytes. installDir is the directory into which the
+ /// component was installed.
+ unsigned long GetInstalledSize(const char* installDir) const;
+
+ /// Identical to GetInstalledSize, but returns the result in
+ /// kilobytes.
+ unsigned long GetInstalledSizeInKbytes(const char* installDir) const;
+
+ private:
+ mutable unsigned long TotalSize;
};
/** \class cmCPackComponentGroup
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index a156971..d35e764 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -32,6 +32,7 @@
cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator()
{
this->PackageMakerVersion = 0.0;
+ this->PackageCompatibilityVersion = 10.4;
}
//----------------------------------------------------------------------
@@ -42,7 +43,7 @@ cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator()
//----------------------------------------------------------------------
bool cmCPackPackageMakerGenerator::SupportsComponentInstallation() const
{
- return true;
+ return this->PackageCompatibilityVersion >= 10.4;
}
//----------------------------------------------------------------------
@@ -165,7 +166,7 @@ int cmCPackPackageMakerGenerator::CompressFiles(const char* outFileName,
if (!this->Components.empty())
{
- // Create the directory where component packages will be installed.
+ // Create the directory where component packages will be built.
std::string basePackageDir = packageDirFileName;
basePackageDir += "/Contents/Packages";
if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str()))
@@ -176,12 +177,78 @@ int cmCPackPackageMakerGenerator::CompressFiles(const char* outFileName,
return 0;
}
+ // Create the directory where downloaded component packages will
+ // be placed.
+ const char* userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY");
+ std::string uploadDirectory;
+ if (userUploadDirectory && *userUploadDirectory)
+ {
+ uploadDirectory = userUploadDirectory;
+ }
+ else
+ {
+ uploadDirectory= this->GetOption("CPACK_PACKAGE_DIRECTORY");
+ uploadDirectory += "/CPackUploads";
+ }
+
// Create packages for each component
+ bool warnedAboutDownloadCompatibility = false;
+
std::map<std::string, cmCPackComponent>::iterator compIt;
for (compIt = this->Components.begin(); compIt != this->Components.end();
++compIt)
{
- std::string packageFile = basePackageDir;
+ std::string packageFile;
+ if (compIt->second.IsDownloaded)
+ {
+ if (this->PackageCompatibilityVersion >= 10.5 &&
+ this->PackageMakerVersion >= 3.0)
+ {
+ // Build this package within the upload directory.
+ packageFile = uploadDirectory;
+
+ if(!cmSystemTools::FileExists(uploadDirectory.c_str()))
+ {
+ if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unable to create package upload directory "
+ << uploadDirectory << std::endl);
+ return 0;
+ }
+ }
+ }
+ else if (!warnedAboutDownloadCompatibility)
+ {
+ if (this->PackageCompatibilityVersion < 10.5)
+ {
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPack warning: please set CPACK_OSX_PACKAGE_VERSION to 10.5 or greater enable downloaded packages. CPack will build a non-downloaded package."
+ << std::endl);
+ }
+
+ if (this->PackageMakerVersion < 3)
+ {
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPack warning: unable to build downloaded packages with PackageMaker versions prior to 3.0. CPack will build a non-downloaded package."
+ << std::endl);
+ }
+
+ warnedAboutDownloadCompatibility = true;
+ }
+ }
+
+ if (packageFile.empty())
+ {
+ // Build this package within the overall distribution
+ // metapackage.
+ packageFile = basePackageDir;
+
+ // We're not downloading this component, even if the user
+ // requested it.
+ compIt->second.IsDownloaded = false;
+ }
+
packageFile += '/';
packageFile += GetPackageName(compIt->second);
@@ -229,7 +296,7 @@ int cmCPackPackageMakerGenerator::CompressFiles(const char* outFileName,
<< "/Resources\" -i \""
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
<< "/Info.plist\" -d \""
- << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
+ << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
<< "/Description.plist\"";
if ( this->PackageMakerVersion > 2.0 )
{
@@ -339,6 +406,30 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
cmCPackLogger(cmCPackLog::LOG_DEBUG, "PackageMaker version is: "
<< this->PackageMakerVersion << std::endl);
+ // Determine the package compatibility version. If it wasn't
+ // specified by the user, we define it based on which features the
+ // user requested.
+ const char *packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION");
+ if (packageCompat && *packageCompat)
+ {
+ this->PackageCompatibilityVersion = atof(packageCompat);
+ }
+ else if (this->GetOption("CPACK_DOWNLOAD_SITE"))
+ {
+ this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.5");
+ this->PackageCompatibilityVersion = 10.5;
+ }
+ else if (this->GetOption("CPACK_COMPONENTS_ALL"))
+ {
+ this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.4");
+ this->PackageCompatibilityVersion = 10.4;
+ }
+ else
+ {
+ this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.3");
+ this->PackageCompatibilityVersion = 10.3;
+ }
+
pkgPath += "/MacOS";
path.push_back(pkgPath);
pkgPath = cmSystemTools::FindProgram("PackageMaker", path, false);
@@ -491,12 +582,19 @@ bool cmCPackPackageMakerGenerator::RunPackageMaker(const char *command,
std::string
cmCPackPackageMakerGenerator::GetPackageName(const cmCPackComponent& component)
{
- std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- packagesDir += ".dummy";
- cmOStringStream out;
- out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir)
- << "-" << component.Name << ".pkg";
- return out.str();
+ if (component.ArchiveFile.empty())
+ {
+ std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ packagesDir += ".dummy";
+ cmOStringStream out;
+ out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir)
+ << "-" << component.Name << ".pkg";
+ return out.str();
+ }
+ else
+ {
+ return component.ArchiveFile + ".pkg";
+ }
}
//----------------------------------------------------------------------
@@ -509,46 +607,74 @@ GenerateComponentPackage(const char *packageFile,
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Building component package: " << packageFile << std::endl);
- // Create the description file for this component.
- std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- descriptionFile += '/' + component.Name + "-Description.plist";
- std::ofstream out(descriptionFile.c_str());
- out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl
- << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
- << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" << std::endl
- << "<plist version=\"1.4\">" << std::endl
- << "<dict>" << std::endl
- << " <key>IFPkgDescriptionTitle</key>" << std::endl
- << " <string>" << component.DisplayName << "</string>" << std::endl
- << " <key>IFPkgDescriptionVersion</key>" << std::endl
- << " <string>" << this->GetOption("CPACK_PACKAGE_VERSION")
- << "</string>" << std::endl
- << " <key>IFPkgDescriptionDescription</key>" << std::endl
- << " <string>" + this->EscapeForXML(component.Description)
- << "</string>" << std::endl
- << "</dict>" << std::endl
- << "</plist>" << std::endl;
- out.close();
-
- // Create the Info.plist file for this component
- std::string moduleVersionSuffix = ".";
- moduleVersionSuffix += component.Name;
- this->SetOption("CPACK_MODULE_VERSION_SUFFIX", moduleVersionSuffix.c_str());
- std::string infoFileName = component.Name;
- infoFileName += "-Info.plist";
- if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str()))
+ // The command that will be used to run PackageMaker
+ cmOStringStream pkgCmd;
+
+ if (this->PackageCompatibilityVersion < 10.5 ||
+ this->PackageMakerVersion < 3.0)
+ {
+ // Create Description.plist and Info.plist files for normal Mac OS
+ // X packages, which work on Mac OS X 10.3 and newer.
+ std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ descriptionFile += '/' + component.Name + "-Description.plist";
+ std::ofstream out(descriptionFile.c_str());
+ out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl
+ << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
+ << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" << std::endl
+ << "<plist version=\"1.4\">" << std::endl
+ << "<dict>" << std::endl
+ << " <key>IFPkgDescriptionTitle</key>" << std::endl
+ << " <string>" << component.DisplayName << "</string>" << std::endl
+ << " <key>IFPkgDescriptionVersion</key>" << std::endl
+ << " <string>" << this->GetOption("CPACK_PACKAGE_VERSION")
+ << "</string>" << std::endl
+ << " <key>IFPkgDescriptionDescription</key>" << std::endl
+ << " <string>" + this->EscapeForXML(component.Description)
+ << "</string>" << std::endl
+ << "</dict>" << std::endl
+ << "</plist>" << std::endl;
+ out.close();
+
+ // Create the Info.plist file for this component
+ std::string moduleVersionSuffix = ".";
+ moduleVersionSuffix += component.Name;
+ this->SetOption("CPACK_MODULE_VERSION_SUFFIX", moduleVersionSuffix.c_str());
+ std::string infoFileName = component.Name;
+ infoFileName += "-Info.plist";
+ if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str()))
+ {
+ return false;
+ }
+
+ pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
+ << "\" -build -p \"" << packageFile << "\""
+ << " -f \"" << packageDir << "\""
+ << " -i \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
+ << "/" << infoFileName << "\""
+ << " -d \"" << descriptionFile << "\"";
+ }
+ else
{
- return false;
+ // Create a "flat" package on Mac OS X 10.5 and newer. Flat
+ // packages are stored in a single file, rather than a directory
+ // like normal packages, and can be downloaded by the installer
+ // on-the-fly in Mac OS X 10.5 or newer. Thus, we need to create
+ // flat packages when the packages will be downloaded on the fly.
+ std::string pkgId = "com.";
+ pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
+ pkgId += '.';
+ pkgId += this->GetOption("CPACK_PACKAGE_NAME");
+ pkgId += '.';
+ pkgId += component.Name;
+
+ pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
+ << "\" --root \"" << packageDir << "\""
+ << " --id " << pkgId
+ << " --target " << this->GetOption("CPACK_OSX_PACKAGE_VERSION")
+ << " --out \"" << packageFile << "\"";
}
// Run PackageMaker
- cmOStringStream pkgCmd;
- pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
- << "\" -build -p \"" << packageFile << "\""
- << " -f \"" << packageDir << "\""
- << " -i \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
- << "/" << infoFileName << "\""
- << " -d \"" << descriptionFile << "\"";
return RunPackageMaker(pkgCmd.str().c_str(), packageFile);
}
@@ -670,8 +796,6 @@ cmCPackPackageMakerGenerator::CreateChoice(const cmCPackComponent& component,
packageId += '.';
packageId += this->GetOption("CPACK_PACKAGE_NAME");
packageId += '.';
- packageId += this->GetOption("CPACK_PACKAGE_VERSION");
- packageId += '.';
packageId += component.Name;
out << "<choice id=\"" << component.Name << "Choice\" "
@@ -716,60 +840,29 @@ cmCPackPackageMakerGenerator::CreateChoice(const cmCPackComponent& component,
// Create a description of the package associated with this
// component.
std::string relativePackageLocation = "Contents/Packages/";
- relativePackageLocation += GetPackageName(component);
-
- // Determine the installed size of the package. To do so, we dig
- // into the Info.plist file from the generated package to retrieve
- // this size.
- int installedSize = 0;
- std::string infoPlistFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- infoPlistFile += ".mpkg/";
- infoPlistFile += relativePackageLocation;
- infoPlistFile += "/Contents/Info.plist";
- bool foundFlagInstalledSize = false;
- std::string line;
- std::ifstream ifs(infoPlistFile.c_str());
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
- if (foundFlagInstalledSize)
- {
- std::string::size_type pos = line.find("<integer>");
- if (pos == std::string::npos)
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot parse package size in "
- << infoPlistFile << std::endl
- << "String is \"" << line << "\"" << std::endl);
- }
- else
- {
- line.erase(0, pos + 9);
- pos = line.find("</integer>");
- if (pos == std::string::npos)
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot parse package size in "
- << infoPlistFile << std::endl);
- }
- else
- {
- line.erase(pos, std::string::npos);
- installedSize = atoi(line.c_str());
- }
- }
- foundFlagInstalledSize = false;
- }
- else
- {
- foundFlagInstalledSize
- = line.find("IFPkgFlagInstalledSize") != std::string::npos;
- }
- }
-
+ relativePackageLocation += this->GetPackageName(component);
+
+ // Determine the installed size of the package.
+ std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ dirName += '/';
+ dirName += component.Name;
+ unsigned long installedSize
+ = component.GetInstalledSizeInKbytes(dirName.c_str());
out << "<pkg-ref id=\"" << packageId << "\" "
<< "version=\"" << this->GetOption("CPACK_PACKAGE_VERSION") << "\" "
<< "installKBytes=\"" << installedSize << "\" "
- << "auth=\"Admin\" onConclusion=\"None\">"
- << "file:./" << relativePackageLocation << "</pkg-ref>" << std::endl;
+ << "auth=\"Admin\" onConclusion=\"None\">";
+ if (component.IsDownloaded)
+ {
+ out << this->GetOption("CPACK_DOWNLOAD_SITE")
+ << this->GetPackageName(component);
+ }
+ else
+ {
+ out << "file:./" << relativePackageLocation;
+ }
+ out << "</pkg-ref>" << std::endl;
}
//----------------------------------------------------------------------
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h
index 37f8f0e..228e099 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.h
+++ b/Source/CPack/cmCPackPackageMakerGenerator.h
@@ -116,6 +116,7 @@ protected:
std::string EscapeForXML(std::string str);
double PackageMakerVersion;
+ double PackageCompatibilityVersion;
};
#endif