blob: bbff9b2424df71086bcd39bf6bd0a8f2954a02ca [file] [log] [blame]
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile: cmCPackGenerator.cxx,v $
Language: C++
Date: $Date: 2012/03/29 17:21:10 $
Version: $Revision: 1.1.1.1 $
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 "cmCPackGenerator.h"
#include "cmMakefile.h"
#include "cmCPackLog.h"
#include "cmake.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmCPackComponentGroup.h"
#include <cmsys/SystemTools.hxx>
#include <cmsys/Glob.hxx>
#include <memory> // auto_ptr
//----------------------------------------------------------------------
cmCPackGenerator::cmCPackGenerator()
{
this->GeneratorVerbose = false;
this->MakefileMap = 0;
this->Logger = 0;
}
//----------------------------------------------------------------------
cmCPackGenerator::~cmCPackGenerator()
{
this->MakefileMap = 0;
}
//----------------------------------------------------------------------
void cmCPackGeneratorProgress(const char *msg, float prog, void* ptr)
{
cmCPackGenerator* self = static_cast<cmCPackGenerator*>(ptr);
self->DisplayVerboseOutput(msg, prog);
}
//----------------------------------------------------------------------
void cmCPackGenerator::DisplayVerboseOutput(const char* msg,
float progress)
{
(void)progress;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
}
//----------------------------------------------------------------------
int cmCPackGenerator::PrepareNames()
{
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Create temp directory." << std::endl);
std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
tempDirectory += "/_CPack_Packages/";
const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
if ( toplevelTag )
{
tempDirectory += toplevelTag;
tempDirectory += "/";
}
tempDirectory += this->GetOption("CPACK_GENERATOR");
std::string topDirectory = tempDirectory;
this->GetOption("CPACK_PACKAGE_FILE_NAME");
const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
if(!pfname)
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_FILE_NAME not specified" << std::endl);
return 0;
}
std::string outName = pfname;
tempDirectory += "/" + outName;
if(!this->GetOutputExtension())
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"No output extension specified" << std::endl);
return 0;
}
outName += this->GetOutputExtension();
const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
if(!pdir)
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_DIRECTORY not specified" << std::endl);
return 0;
}
std::string destFile = pdir;
destFile += "/" + outName;
std::string outFile = topDirectory + "/" + outName;
this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory.c_str());
this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory.c_str());
this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName.c_str());
this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile.c_str());
this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
outFile.c_str());
this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath());
this->SetOptionIfNotSet("CPACK_NATIVE_INSTALL_DIRECTORY",
cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str());
this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY",
tempDirectory.c_str());
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl);
const char* descFileName
= this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
if ( descFileName )
{
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Look for: " << descFileName << std::endl);
if ( !cmSystemTools::FileExists(descFileName) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find description file name: ["
<< descFileName << "]" << std::endl);
return 0;
}
std::ifstream ifs(descFileName);
if ( !ifs )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot open description file name: " << descFileName << std::endl);
return 0;
}
cmOStringStream ostr;
std::string line;
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Read description file: " << descFileName << std::endl);
while ( ifs && cmSystemTools::GetLineFromStream(ifs, line) )
{
ostr << cmSystemTools::MakeXMLSafe(line.c_str()) << std::endl;
}
this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
}
if ( !this->GetOption("CPACK_PACKAGE_DESCRIPTION") )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Project description not specified. Please specify "
"CPACK_PACKAGE_DESCRIPTION or CPACK_PACKAGE_DESCRIPTION_FILE."
<< std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_REMOVE_TOPLEVEL_DIRECTORY", "1");
return 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::InstallProject()
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Install projects" << std::endl);
this->CleanTemporaryDirectory();
std::string bareTempInstallDirectory
= this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
std::string tempInstallDirectoryStr = bareTempInstallDirectory;
bool setDestDir = cmSystemTools::IsOn(this->GetOption("CPACK_SET_DESTDIR"));
if (!setDestDir)
{
tempInstallDirectoryStr += this->GetPackagingInstallPrefix();
}
const char* tempInstallDirectory = tempInstallDirectoryStr.c_str();
int res = 1;
if ( !cmsys::SystemTools::MakeDirectory(bareTempInstallDirectory.c_str()))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< (tempInstallDirectory ? tempInstallDirectory : "(NULL}")
<< std::endl);
return 0;
}
if ( setDestDir )
{
std::string destDir = "DESTDIR=";
destDir += tempInstallDirectory;
cmSystemTools::PutEnv(destDir.c_str());
}
else
{
// Make sure there is no destdir
cmSystemTools::PutEnv("DESTDIR=");
}
// If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
// as listed
if ( !this->InstallProjectViaInstallCommands(
setDestDir, tempInstallDirectory) )
{
return 0;
}
// If the CPackConfig file sets CPACK_INSTALL_SCRIPT then run them
// as listed
if ( !this->InstallProjectViaInstallScript(
setDestDir, tempInstallDirectory) )
{
return 0;
}
// If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
// then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
// This is used in Source packageing
if ( !this->InstallProjectViaInstalledDirectories(
setDestDir, tempInstallDirectory) )
{
return 0;
}
// If the project is a CMAKE project then run pre-install
// and then read the cmake_install script to run it
if ( !this->InstallProjectViaInstallCMakeProjects(
setDestDir, bareTempInstallDirectory.c_str()) )
{
return 0;
}
if ( setDestDir )
{
cmSystemTools::PutEnv("DESTDIR=");
}
return res;
}
//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstallCommands(
bool setDestDir, const char* tempInstallDirectory)
{
(void) setDestDir;
const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
if ( installCommands && *installCommands )
{
std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX=";
tempInstallDirectoryEnv += tempInstallDirectory;
cmSystemTools::PutEnv(tempInstallDirectoryEnv.c_str());
std::vector<std::string> installCommandsVector;
cmSystemTools::ExpandListArgument(installCommands,installCommandsVector);
std::vector<std::string>::iterator it;
for ( it = installCommandsVector.begin();
it != installCommandsVector.end();
++it )
{
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << it->c_str()
<< std::endl);
std::string output;
int retVal = 1;
bool resB = cmSystemTools::RunSingleCommand(it->c_str(), &output,
&retVal, 0, this->GeneratorVerbose, 0);
if ( !resB || retVal )
{
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/InstallOutput.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << it->c_str() << std::endl
<< "# Output:" << std::endl
<< output.c_str() << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem running install command: " << it->c_str() << std::endl
<< "Please check " << tmpFile.c_str() << " for errors"
<< std::endl);
return 0;
}
}
}
return 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstalledDirectories(
bool setDestDir, const char* tempInstallDirectory)
{
(void)setDestDir;
(void)tempInstallDirectory;
std::vector<cmsys::RegularExpression> ignoreFilesRegex;
const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
if ( cpackIgnoreFiles )
{
std::vector<std::string> ignoreFilesRegexString;
cmSystemTools::ExpandListArgument(cpackIgnoreFiles,
ignoreFilesRegexString);
std::vector<std::string>::iterator it;
for ( it = ignoreFilesRegexString.begin();
it != ignoreFilesRegexString.end();
++it )
{
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Create ignore files regex for: " << it->c_str() << std::endl);
ignoreFilesRegex.push_back(it->c_str());
}
}
const char* installDirectories
= this->GetOption("CPACK_INSTALLED_DIRECTORIES");
if ( installDirectories && *installDirectories )
{
std::vector<std::string> installDirectoriesVector;
cmSystemTools::ExpandListArgument(installDirectories,
installDirectoriesVector);
if ( installDirectoriesVector.size() % 2 != 0 )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> and "
"<subdirectory>. The <subdirectory> can be '.' to be installed in "
"the toplevel directory of installation." << std::endl);
return 0;
}
std::vector<std::string>::iterator it;
const char* tempDir = tempInstallDirectory;
for ( it = installDirectoriesVector.begin();
it != installDirectoriesVector.end();
++it )
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
cmsys::Glob gl;
std::string toplevel = it->c_str();
it ++;
std::string subdir = it->c_str();
std::string findExpr = toplevel;
findExpr += "/*";
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install directory: " << toplevel << std::endl);
gl.RecurseOn();
if ( !gl.FindFiles(findExpr) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find any files in the installed directory" << std::endl);
return 0;
}
std::vector<std::string>& files = gl.GetFiles();
std::vector<std::string>::iterator gfit;
std::vector<cmsys::RegularExpression>::iterator regIt;
for ( gfit = files.begin(); gfit != files.end(); ++ gfit )
{
bool skip = false;
std::string &inFile = *gfit;
for ( regIt= ignoreFilesRegex.begin();
regIt!= ignoreFilesRegex.end();
++ regIt)
{
if ( regIt->find(inFile.c_str()) )
{
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Ignore file: "
<< inFile.c_str() << std::endl);
skip = true;
}
}
if ( skip )
{
continue;
}
std::string filePath = tempDir;
filePath += "/" + subdir + "/"
+ cmSystemTools::RelativePath(toplevel.c_str(), gfit->c_str());
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy file: "
<< inFile.c_str() << " -> " << filePath.c_str() << std::endl);
if ( !cmSystemTools::CopyFileIfDifferent(inFile.c_str(),
filePath.c_str()) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying file: "
<< inFile.c_str() << " -> " << filePath.c_str() << std::endl);
return 0;
}
}
}
}
return 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstallScript(
bool setDestDir, const char* tempInstallDirectory)
{
const char* cmakeScripts
= this->GetOption("CPACK_INSTALL_SCRIPT");
std::string currentWorkingDirectory =
cmSystemTools::GetCurrentWorkingDirectory();
if ( cmakeScripts && *cmakeScripts )
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install scripts: " << cmakeScripts << std::endl);
std::vector<std::string> cmakeScriptsVector;
cmSystemTools::ExpandListArgument(cmakeScripts,
cmakeScriptsVector);
std::vector<std::string>::iterator it;
for ( it = cmakeScriptsVector.begin();
it != cmakeScriptsVector.end();
++it )
{
std::string installScript = it->c_str();
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install script: " << installScript << std::endl);
if ( setDestDir )
{
// For DESTDIR based packaging, use the *project* CMAKE_INSTALL_PREFIX
// underneath the tempInstallDirectory. The value of the project's
// CMAKE_INSTALL_PREFIX is sent in here as the value of the
// CPACK_INSTALL_PREFIX variable.
std::string dir;
if (this->GetOption("CPACK_INSTALL_PREFIX"))
{
dir += this->GetOption("CPACK_INSTALL_PREFIX");
}
this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str());
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Using DESTDIR + CPACK_INSTALL_PREFIX... (this->SetOption)"
<< std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'" << std::endl);
}
else
{
this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Using non-DESTDIR install... (this->SetOption)" << std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
<< "'" << std::endl);
}
this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR",
tempInstallDirectory);
this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
tempInstallDirectory);
int res = this->MakefileMap->ReadListFile(0, installScript.c_str());
if ( cmSystemTools::GetErrorOccuredFlag() || !res )
{
return 0;
}
}
}
return 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
bool setDestDir, const char* baseTempInstallDirectory)
{
const char* cmakeProjects
= this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
const char* cmakeGenerator
= this->GetOption("CPACK_CMAKE_GENERATOR");
std::string currentWorkingDirectory =
cmSystemTools::GetCurrentWorkingDirectory();
if ( cmakeProjects && *cmakeProjects )
{
if ( !cmakeGenerator )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_INSTALL_CMAKE_PROJECTS is specified, but "
"CPACK_CMAKE_GENERATOR is not. CPACK_CMAKE_GENERATOR "
"is required to install the project."
<< std::endl);
return 0;
}
std::vector<std::string> cmakeProjectsVector;
cmSystemTools::ExpandListArgument(cmakeProjects,
cmakeProjectsVector);
std::vector<std::string>::iterator it;
for ( it = cmakeProjectsVector.begin();
it != cmakeProjectsVector.end();
++it )
{
if ( it+1 == cmakeProjectsVector.end() ||
it+2 == cmakeProjectsVector.end() ||
it+3 == cmakeProjectsVector.end() )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Not enough items on list: CPACK_INSTALL_CMAKE_PROJECTS. "
"CPACK_INSTALL_CMAKE_PROJECTS should hold quadruplet of install "
"directory, install project name, install component, and install "
"subdirectory."
<< std::endl);
return 0;
}
std::string installDirectory = it->c_str();
++it;
std::string installProjectName = it->c_str();
++it;
std::string installComponent = it->c_str();
++it;
std::string installSubDirectory = it->c_str();
std::string installFile = installDirectory + "/cmake_install.cmake";
std::vector<std::string> componentsVector;
bool componentInstall = false;
if (this->SupportsComponentInstallation())
{
// Determine the installation types for this project (if provided).
std::string installTypesVar = "CPACK_"
+ cmSystemTools::UpperCase(installComponent) + "_INSTALL_TYPES";
const char *installTypes = this->GetOption(installTypesVar.c_str());
if (installTypes && *installTypes)
{
std::vector<std::string> installTypesVector;
cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
std::vector<std::string>::iterator installTypeIt;
for (installTypeIt = installTypesVector.begin();
installTypeIt != installTypesVector.end();
++installTypeIt)
{
this->GetInstallationType(installProjectName.c_str(),
installTypeIt->c_str());
}
}
// Determine the set of components that will be used in this project
std::string componentsVar
= "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent);
const char *components = this->GetOption(componentsVar.c_str());
if (components && *components)
{
cmSystemTools::ExpandListArgument(components, componentsVector);
std::vector<std::string>::iterator compIt;
for (compIt = componentsVector.begin();
compIt != componentsVector.end();
++compIt)
{
GetComponent(installProjectName.c_str(), compIt->c_str());
}
componentInstall = true;
}
}
if (componentsVector.empty())
{
componentsVector.push_back(installComponent);
}
const char* buildConfig = this->GetOption("CPACK_BUILD_CONFIG");
cmGlobalGenerator* globalGenerator
= this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
cmakeGenerator);
// set the global flag for unix style paths on cmSystemTools as
// soon as the generator is set. This allows gmake to be used
// on windows.
cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
// Does this generator require pre-install?
if ( globalGenerator->GetPreinstallTargetName() )
{
globalGenerator->FindMakeProgram(this->MakefileMap);
const char* cmakeMakeProgram
= this->MakefileMap->GetDefinition("CMAKE_MAKE_PROGRAM");
std::string buildCommand
= globalGenerator->GenerateBuildCommand(cmakeMakeProgram,
installProjectName.c_str(), 0,
globalGenerator->GetPreinstallTargetName(),
buildConfig, false, false);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Install command: " << buildCommand << std::endl);
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Run preinstall target for: " << installProjectName << std::endl);
std::string output;
int retVal = 1;
bool resB =
cmSystemTools::RunSingleCommand(buildCommand.c_str(),
&output,
&retVal,
installDirectory.c_str(),
this->GeneratorVerbose, 0);
if ( !resB || retVal )
{
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/PreinstallOutput.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << buildCommand.c_str() << std::endl
<< "# Directory: " << installDirectory.c_str() << std::endl
<< "# Output:" << std::endl
<< output.c_str() << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem running install command: " << buildCommand.c_str()
<< std::endl
<< "Please check " << tmpFile.c_str() << " for errors"
<< std::endl);
return 0;
}
}
delete globalGenerator;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install project: " << installProjectName << std::endl);
// Run the installation for each component
std::vector<std::string>::iterator componentIt;
for (componentIt = componentsVector.begin();
componentIt != componentsVector.end();
++componentIt)
{
std::string tempInstallDirectory = baseTempInstallDirectory;
installComponent = *componentIt;
if (componentInstall)
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install component: " << installComponent
<< std::endl);
}
cmake cm;
cm.AddCMakePaths();
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
cmGlobalGenerator gg;
gg.SetCMakeInstance(&cm);
std::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
lg->SetGlobalGenerator(&gg);
cmMakefile *mf = lg->GetMakefile();
std::string realInstallDirectory = tempInstallDirectory;
if ( !installSubDirectory.empty() && installSubDirectory != "/" )
{
realInstallDirectory += installSubDirectory;
}
if (componentInstall)
{
tempInstallDirectory += "/";
tempInstallDirectory += installComponent;
}
if (!setDestDir)
{
tempInstallDirectory += this->GetPackagingInstallPrefix();
}
if ( setDestDir )
{
// For DESTDIR based packaging, use the *project* CMAKE_INSTALL_PREFIX
// underneath the tempInstallDirectory. The value of the project's
// CMAKE_INSTALL_PREFIX is sent in here as the value of the
// CPACK_INSTALL_PREFIX variable.
std::string dir;
if (this->GetOption("CPACK_INSTALL_PREFIX"))
{
dir += this->GetOption("CPACK_INSTALL_PREFIX");
}
mf->AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
if ( !cmsys::SystemTools::MakeDirectory(dir.c_str()))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< dir << std::endl);
return 0;
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf->AddDefinition)"
<< std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
<< std::endl);
}
else
{
mf->AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
if ( !cmsys::SystemTools::MakeDirectory(tempInstallDirectory.c_str()))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< tempInstallDirectory << std::endl);
return 0;
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Using non-DESTDIR install... (mf->AddDefinition)" << std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
<< "'" << std::endl);
}
if ( buildConfig && *buildConfig )
{
mf->AddDefinition("BUILD_TYPE", buildConfig);
}
std::string installComponentLowerCase
= cmSystemTools::LowerCase(installComponent);
if ( installComponentLowerCase != "all" )
{
mf->AddDefinition("CMAKE_INSTALL_COMPONENT",
installComponent.c_str());
}
// strip on TRUE, ON, 1, one or several file names, but not on
// FALSE, OFF, 0 and an empty string
if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES")))
{
mf->AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
}
int res = mf->ReadListFile(0, installFile.c_str());
if ( cmSystemTools::GetErrorOccuredFlag() || !res )
{
return 0;
}
}
}
}
return 1;
}
//----------------------------------------------------------------------
bool cmCPackGenerator::ReadListFile(const char* moduleName)
{
std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);
return this->MakefileMap->ReadListFile(0, fullPath.c_str());
}
//----------------------------------------------------------------------
void cmCPackGenerator::SetOptionIfNotSet(const char* op,
const char* value)
{
const char* def = this->MakefileMap->GetDefinition(op);
if ( def && *def )
{
return;
}
this->SetOption(op, value);
}
//----------------------------------------------------------------------
void cmCPackGenerator::SetOption(const char* op, const char* value)
{
if ( !op )
{
return;
}
if ( !value )
{
this->MakefileMap->RemoveDefinition(op);
return;
}
cmCPackLogger(cmCPackLog::LOG_DEBUG, this->GetNameOfClass()
<< "::SetOption(" << op << ", " << value << ")" << std::endl);
this->MakefileMap->AddDefinition(op, value);
}
//----------------------------------------------------------------------
int cmCPackGenerator::DoPackage()
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"Create package using " << this->Name.c_str() << std::endl);
if ( !this->PrepareNames() )
{
return 0;
}
if ( cmSystemTools::IsOn(
this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY")) )
{
const char* toplevelDirectory
= this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
if ( cmSystemTools::FileExists(toplevelDirectory) )
{
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove toplevel directory: "
<< toplevelDirectory << std::endl);
if ( !cmSystemTools::RemoveADirectory(toplevelDirectory) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem removing toplevel directory: "
<< toplevelDirectory
<< std::endl);
return 0;
}
}
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"About to install project " << std::endl);
if ( !this->InstallProject() )
{
return 0;
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Done install project " << std::endl);
const char* tempPackageFileName = this->GetOption(
"CPACK_TEMPORARY_PACKAGE_FILE_NAME");
const char* packageFileName = this->GetOption("CPACK_OUTPUT_FILE_PATH");
const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
cmsys::Glob gl;
std::string findExpr = tempDirectory;
findExpr += "/*";
gl.RecurseOn();
if ( !gl.FindFiles(findExpr) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find any files in the packaging tree" << std::endl);
return 0;
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Compress package" << std::endl);
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Compress files to: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)") << std::endl);
if ( cmSystemTools::FileExists(tempPackageFileName) )
{
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove old package file"
<< std::endl);
cmSystemTools::RemoveFile(tempPackageFileName);
}
if ( cmSystemTools::IsOn(this->GetOption(
"CPACK_INCLUDE_TOPLEVEL_DIRECTORY")) )
{
tempDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
}
// The files to be installed
std::vector<std::string> files = gl.GetFiles();
// For component installations, determine which files go into which
// components.
if (!this->Components.empty())
{
std::vector<std::string>::const_iterator it;
for ( it = files.begin(); it != files.end(); ++ it )
{
std::string fileN = cmSystemTools::RelativePath(tempDirectory,
it->c_str());
// Determine which component we are in.
std::string componentName = fileN.substr(0, fileN.find('/'));
// Strip off the component part of the path.
fileN = fileN.substr(fileN.find('/')+1, std::string::npos);
// Add this file to the list of files for the component.
this->Components[componentName].Files.push_back(fileN);
}
}
if ( !this->CompressFiles(tempPackageFileName,
tempDirectory, files) || cmSystemTools::GetErrorOccuredFlag())
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
<< std::endl);
return 0;
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Finalize package" << std::endl);
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Copy final package: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)" )
<< " to "
<< (packageFileName ? packageFileName : "(NULL)")
<< std::endl);
if ( !cmSystemTools::CopyFileIfDifferent(tempPackageFileName,
packageFileName) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the package: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)" )
<< " to "
<< (packageFileName ? packageFileName : "(NULL)")
<< std::endl);
return 0;
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Package "
<< (packageFileName ? packageFileName : "(NULL)")
<< " generated." << std::endl);
return 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::Initialize(const char* name, cmMakefile* mf,
const char* argv0)
{
this->MakefileMap = mf;
this->Name = name;
if ( !this->FindRunningCMake(argv0) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot initialize the generator" << std::endl);
return 0;
}
// set the running generator name
this->SetOption("CPACK_GENERATOR", this->Name.c_str());
// Load the project specific config file
const char* config =
this->GetOption("CPACK_PROJECT_CONFIG_FILE");
if(config)
{
mf->ReadListFile(config);
}
int result = this->InitializeInternal();
if (cmSystemTools::GetErrorOccuredFlag())
{
return 0;
}
// If a generator subclass did not already set this option in its
// InitializeInternal implementation, and the project did not already set
// it, the default value should be:
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/");
return result;
}
//----------------------------------------------------------------------
int cmCPackGenerator::InitializeInternal()
{
return 1;
}
//----------------------------------------------------------------------
bool cmCPackGenerator::IsSet(const char* name) const
{
return this->MakefileMap->IsSet(name);
}
//----------------------------------------------------------------------
const char* cmCPackGenerator::GetOption(const char* op)
{
const char* ret = this->MakefileMap->GetDefinition(op);
if(!ret)
{
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Warning, GetOption return NULL for: "
<< op
<< std::endl);
}
return ret;
}
//----------------------------------------------------------------------
int cmCPackGenerator::FindRunningCMake(const char* arg0)
{
int found = 0;
// Find our own executable.
std::vector<cmStdString> failures;
this->CPackSelf = arg0;
cmSystemTools::ConvertToUnixSlashes(this->CPackSelf);
failures.push_back(this->CPackSelf);
this->CPackSelf = cmSystemTools::FindProgram(this->CPackSelf.c_str());
if(!cmSystemTools::FileExists(this->CPackSelf.c_str()))
{
failures.push_back(this->CPackSelf);
this->CPackSelf = "/usr/local/bin/ctest";
}
if(!cmSystemTools::FileExists(this->CPackSelf.c_str()))
{
failures.push_back(this->CPackSelf);
cmOStringStream msg;
msg << "CPack can not find the command line program ctest.\n";
msg << " argv[0] = \"" << arg0 << "\"\n";
msg << " Attempted paths:\n";
std::vector<cmStdString>::iterator i;
for(i=failures.begin(); i != failures.end(); ++i)
{
msg << " \"" << i->c_str() << "\"\n";
}
cmCPackLogger(cmCPackLog::LOG_ERROR, msg.str().c_str()
<< std::endl);
return 0;
}
std::string dir;
std::string file;
if(cmSystemTools::SplitProgramPath(this->CPackSelf.c_str(),
dir, file, true))
{
this->CMakeSelf = dir += "/cmake";
this->CMakeSelf += cmSystemTools::GetExecutableExtension();
if(cmSystemTools::FileExists(this->CMakeSelf.c_str()))
{
found = 1;
}
}
if ( !found )
{
failures.push_back(this->CMakeSelf);
#ifdef CMAKE_BUILD_DIR
std::string intdir = ".";
#ifdef CMAKE_INTDIR
intdir = CMAKE_INTDIR;
#endif
this->CMakeSelf = CMAKE_BUILD_DIR;
this->CMakeSelf += "/bin/";
this->CMakeSelf += intdir;
this->CMakeSelf += "/cmake";
this->CMakeSelf += cmSystemTools::GetExecutableExtension();
#endif
if(!cmSystemTools::FileExists(this->CMakeSelf.c_str()))
{
failures.push_back(this->CMakeSelf);
cmOStringStream msg;
msg << "CPack can not find the command line program cmake.\n";
msg << " argv[0] = \"" << arg0 << "\"\n";
msg << " Attempted paths:\n";
std::vector<cmStdString>::iterator i;
for(i=failures.begin(); i != failures.end(); ++i)
{
msg << " \"" << i->c_str() << "\"\n";
}
cmCPackLogger(cmCPackLog::LOG_ERROR, msg.str().c_str()
<< std::endl);
return 0;
}
}
// do CMAKE_ROOT, look for the environment variable first
std::string cMakeRoot;
std::string modules;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT" << std::endl);
if (getenv("CMAKE_ROOT"))
{
cMakeRoot = getenv("CMAKE_ROOT");
modules = cMakeRoot + "/Modules/CMake.cmake";
}
if(modules.empty() || !cmSystemTools::FileExists(modules.c_str()))
{
// next try exe/..
cMakeRoot = cmSystemTools::GetProgramPath(this->CMakeSelf.c_str());
std::string::size_type slashPos = cMakeRoot.rfind("/");
if(slashPos != std::string::npos)
{
cMakeRoot = cMakeRoot.substr(0, slashPos);
}
// is there no Modules direcory there?
modules = cMakeRoot + "/Modules/CMake.cmake";
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< modules.c_str() << std::endl);
}
if (!cmSystemTools::FileExists(modules.c_str()))
{
// try exe/../share/cmake
cMakeRoot += CMAKE_DATA_DIR;
modules = cMakeRoot + "/Modules/CMake.cmake";
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< modules.c_str() << std::endl);
}
#ifdef CMAKE_ROOT_DIR
if (!cmSystemTools::FileExists(modules.c_str()))
{
// try compiled in root directory
cMakeRoot = CMAKE_ROOT_DIR;
modules = cMakeRoot + "/Modules/CMake.cmake";
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< modules.c_str() << std::endl);
}
#endif
#ifdef CMAKE_PREFIX
if (!cmSystemTools::FileExists(modules.c_str()))
{
// try compiled in install prefix
cMakeRoot = CMAKE_PREFIX CMAKE_DATA_DIR;
modules = cMakeRoot + "/Modules/CMake.cmake";
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< modules.c_str() << std::endl);
}
#endif
if (!cmSystemTools::FileExists(modules.c_str()))
{
// try
cMakeRoot = cmSystemTools::GetProgramPath(this->CMakeSelf.c_str());
cMakeRoot += CMAKE_DATA_DIR;
modules = cMakeRoot + "/Modules/CMake.cmake";
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< modules.c_str() << std::endl);
}
if(!cmSystemTools::FileExists(modules.c_str()))
{
// next try exe
cMakeRoot = cmSystemTools::GetProgramPath(this->CMakeSelf.c_str());
// is there no Modules direcory there?
modules = cMakeRoot + "/Modules/CMake.cmake";
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< modules.c_str() << std::endl);
}
if (!cmSystemTools::FileExists(modules.c_str()))
{
// couldn't find modules
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Could not find CMAKE_ROOT !!!" << std::endl
<< "CMake has most likely not been installed correctly." << std::endl
<<"Modules directory not found in" << std::endl
<< cMakeRoot.c_str()
<< std::endl);
return 0;
}
this->CMakeRoot = cMakeRoot;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
<< this->CMakeRoot.c_str() << std::endl);
this->SetOption("CMAKE_ROOT", this->CMakeRoot.c_str());
return 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::CompressFiles(const char* outFileName,
const char* toplevel, const std::vector<std::string>& files)
{
(void)outFileName;
(void)toplevel;
(void)files;
return 0;
}
//----------------------------------------------------------------------
const char* cmCPackGenerator::GetInstallPath()
{
if ( !this->InstallPath.empty() )
{
return this->InstallPath.c_str();
}
#if defined(_WIN32) && !defined(__CYGWIN__)
const char* prgfiles = cmsys::SystemTools::GetEnv("ProgramFiles");
const char* sysDrive = cmsys::SystemTools::GetEnv("SystemDrive");
if ( prgfiles )
{
this->InstallPath = prgfiles;
}
else if ( sysDrive )
{
this->InstallPath = sysDrive;
this->InstallPath += "/Program Files";
}
else
{
this->InstallPath = "c:/Program Files";
}
this->InstallPath += "/";
this->InstallPath += this->GetOption("CPACK_PACKAGE_NAME");
this->InstallPath += "-";
this->InstallPath += this->GetOption("CPACK_PACKAGE_VERSION");
#else
this->InstallPath = "/usr/local/";
#endif
return this->InstallPath.c_str();
}
//----------------------------------------------------------------------
const char* cmCPackGenerator::GetPackagingInstallPrefix()
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "GetPackagingInstallPrefix: '"
<< this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'" << std::endl);
return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
}
//----------------------------------------------------------------------
std::string cmCPackGenerator::FindTemplate(const char* name)
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for template: "
<< (name ? name : "(NULL)") << std::endl);
std::string ffile = this->MakefileMap->GetModulesFile(name);
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Found template: "
<< ffile.c_str() << std::endl);
return ffile;
}
//----------------------------------------------------------------------
bool cmCPackGenerator::ConfigureString(const std::string& inString,
std::string& outString)
{
this->MakefileMap->ConfigureString(inString,
outString, true, false);
return true;
}
//----------------------------------------------------------------------
bool cmCPackGenerator::ConfigureFile(const char* inName,
const char* outName, bool copyOnly /* = false */)
{
return this->MakefileMap->ConfigureFile(inName, outName,
copyOnly, true, false) == 1;
}
//----------------------------------------------------------------------
int cmCPackGenerator::CleanTemporaryDirectory()
{
std::string tempInstallDirectoryWithPostfix
= this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
const char* tempInstallDirectory = tempInstallDirectoryWithPostfix.c_str();
if(cmsys::SystemTools::FileExists(tempInstallDirectory))
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Clean temporary : "
<< tempInstallDirectory << std::endl);
if(!cmsys::SystemTools::RemoveADirectory(tempInstallDirectory))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem removing temporary directory: " <<
tempInstallDirectory
<< std::endl);
return 0;
}
}
return 1;
}
//----------------------------------------------------------------------
bool cmCPackGenerator::SupportsComponentInstallation() const
{
return false;
}
//----------------------------------------------------------------------
cmCPackInstallationType*
cmCPackGenerator::GetInstallationType(const char *projectName, const char *name)
{
(void) projectName;
bool hasInstallationType = this->InstallationTypes.count(name) != 0;
cmCPackInstallationType *installType = &this->InstallationTypes[name];
if (!hasInstallationType)
{
// Define the installation type
std::string macroPrefix = "CPACK_INSTALL_TYPE_"
+ cmsys::SystemTools::UpperCase(name);
installType->Name = name;
const char* displayName
= this->GetOption((macroPrefix + "_DISPLAY_NAME").c_str());
if (displayName && *displayName)
{
installType->DisplayName = displayName;
}
else
{
installType->DisplayName = installType->Name;
}
installType->Index = static_cast<unsigned>(
this->InstallationTypes.size());
}
return installType;
}
//----------------------------------------------------------------------
cmCPackComponent*
cmCPackGenerator::GetComponent(const char *projectName, const char *name)
{
bool hasComponent = this->Components.count(name) != 0;
cmCPackComponent *component = &this->Components[name];
if (!hasComponent)
{
// Define the component
std::string macroPrefix = "CPACK_COMPONENT_"
+ cmsys::SystemTools::UpperCase(name);
component->Name = name;
const char* displayName
= this->GetOption((macroPrefix + "_DISPLAY_NAME").c_str());
if (displayName && *displayName)
{
component->DisplayName = displayName;
}
else
{
component->DisplayName = component->Name;
}
component->IsHidden
= this->IsSet((macroPrefix + "_HIDDEN").c_str());
component->IsRequired
= this->IsSet((macroPrefix + "_REQUIRED").c_str());
component->IsDisabledByDefault
= this->IsSet((macroPrefix + "_DISABLED").c_str());
component->IsDownloaded
= this->IsSet((macroPrefix + "_DOWNLOADED").c_str())
|| cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
const char* archiveFile = this->GetOption((macroPrefix + "_ARCHIVE_FILE").c_str());
if (archiveFile && *archiveFile)
{
component->ArchiveFile = archiveFile;
}
const char* groupName = this->GetOption((macroPrefix + "_GROUP").c_str());
if (groupName && *groupName)
{
component->Group = GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
}
else
{
component->Group = 0;
}
const char* description
= this->GetOption((macroPrefix + "_DESCRIPTION").c_str());
if (description && *description)
{
component->Description = description;
}
// Determine the installation types.
const char *installTypes
= this->GetOption((macroPrefix + "_INSTALL_TYPES").c_str());
if (installTypes && *installTypes)
{
std::vector<std::string> installTypesVector;
cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
std::vector<std::string>::iterator installTypesIt;
for (installTypesIt = installTypesVector.begin();
installTypesIt != installTypesVector.end();
++installTypesIt)
{
component->InstallationTypes.push_back(
this->GetInstallationType(projectName, installTypesIt->c_str()));
}
}
// Determine the component dependencies.
const char *depends = this->GetOption((macroPrefix + "_DEPENDS").c_str());
if (depends && *depends)
{
std::vector<std::string> dependsVector;
cmSystemTools::ExpandListArgument(depends, dependsVector);
std::vector<std::string>::iterator dependIt;
for (dependIt = dependsVector.begin();
dependIt != dependsVector.end();
++dependIt)
{
cmCPackComponent *child = GetComponent(projectName, dependIt->c_str());
component->Dependencies.push_back(child);
child->ReverseDependencies.push_back(component);
}
}
}
return component;
}
//----------------------------------------------------------------------
cmCPackComponentGroup*
cmCPackGenerator::GetComponentGroup(const char *projectName, const char *name)
{
(void) projectName;
std::string macroPrefix = "CPACK_COMPONENT_GROUP_"
+ cmsys::SystemTools::UpperCase(name);
bool hasGroup = this->ComponentGroups.count(name) != 0;
cmCPackComponentGroup *group = &this->ComponentGroups[name];
if (!hasGroup)
{
// Define the group
group->Name = name;
const char* displayName
= this->GetOption((macroPrefix + "_DISPLAY_NAME").c_str());
if (displayName && *displayName)
{
group->DisplayName = displayName;
}
else
{
group->DisplayName = group->Name;
}
const char* description
= this->GetOption((macroPrefix + "_DESCRIPTION").c_str());
if (description && *description)
{
group->Description = description;
}
group->IsBold
= this->IsSet((macroPrefix + "_BOLD_TITLE").c_str());
group->IsExpandedByDefault
= this->IsSet((macroPrefix + "_EXPANDED").c_str());
const char* parentGroupName
= this->GetOption((macroPrefix + "_PARENT_GROUP").c_str());
if (parentGroupName && *parentGroupName)
{
group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
group->ParentGroup->Subgroups.push_back(group);
}
else
{
group->ParentGroup = 0;
}
}
return group;
}