1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmInstallExportGenerator.h"
17 #include "cmInstallTargetGenerator.h"
18 #include "cmGeneratedFileStream.h"
19 #include "cmMakefile.h"
20 #include "cmLocalGenerator.h"
21 #include "cmGlobalGenerator.h"
23 #include "cmInstallFilesGenerator.h"
25 #include "cmExportInstallFileGenerator.h"
26 #include "cmExportSet.h"
28 //----------------------------------------------------------------------------
29 cmInstallExportGenerator::cmInstallExportGenerator(
30 cmExportSet* exportSet,
31 const char* destination,
32 const char* file_permissions,
33 std::vector<std::string> const& configurations,
34 const char* component,
35 const char* filename, const char* name_space,
38 :cmInstallGenerator(destination, configurations, component)
40 ,FilePermissions(file_permissions)
42 ,Namespace(name_space)
46 this->EFGen = new cmExportInstallFileGenerator(this);
47 exportSet->AddInstallation(this);
50 //----------------------------------------------------------------------------
51 cmInstallExportGenerator::~cmInstallExportGenerator()
56 //----------------------------------------------------------------------------
57 void cmInstallExportGenerator::ComputeTempDir()
59 // Choose a temporary directory in which to generate the import
60 // files to be installed.
61 this->TempDir = this->Makefile->GetCurrentOutputDirectory();
62 this->TempDir += cmake::GetCMakeFilesDirectory();
63 this->TempDir += "/Export";
64 if(this->Destination.empty())
73 // Enforce a maximum length.
75 #if defined(_WIN32) || defined(__CYGWIN__)
76 std::string::size_type const max_total_len = 250;
78 std::string::size_type const max_total_len = 1000;
80 if(this->TempDir.size() < max_total_len)
82 // Keep the total path length below the limit.
83 std::string::size_type max_len = max_total_len - this->TempDir.size();
84 if(this->Destination.size() > max_len)
95 // Replace the destination path with a hash to keep it short.
97 cmSystemTools::ComputeStringMD5(this->Destination.c_str());
101 std::string dest = this->Destination;
102 // Avoid unix full paths.
107 // Avoid windows full paths by removing colons.
108 cmSystemTools::ReplaceString(dest, ":", "_");
109 // Avoid relative paths that go up the tree.
110 cmSystemTools::ReplaceString(dest, "../", "__/");
112 cmSystemTools::ReplaceString(dest, " ", "_");
113 this->TempDir += dest;
117 //----------------------------------------------------------------------------
118 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
121 if(ExportSet->GetTargetExports()->empty())
124 e << "INSTALL(EXPORT) given unknown export \""
125 << ExportSet->GetName() << "\"";
126 cmSystemTools::Error(e.str().c_str());
130 // Create the temporary directory in which to store the files.
131 this->ComputeTempDir();
132 cmSystemTools::MakeDirectory(this->TempDir.c_str());
134 // Construct a temporary location for the file.
135 this->MainImportFile = this->TempDir;
136 this->MainImportFile += "/";
137 this->MainImportFile += this->FileName;
139 // Generate the import file for this export set.
140 this->EFGen->SetExportFile(this->MainImportFile.c_str());
141 this->EFGen->SetNamespace(this->Namespace.c_str());
142 this->EFGen->SetExportOld(this->ExportOld);
143 if(this->ConfigurationTypes->empty())
145 if(this->ConfigurationName && *this->ConfigurationName)
147 this->EFGen->AddConfiguration(this->ConfigurationName);
151 this->EFGen->AddConfiguration("");
156 for(std::vector<std::string>::const_iterator
157 ci = this->ConfigurationTypes->begin();
158 ci != this->ConfigurationTypes->end(); ++ci)
160 this->EFGen->AddConfiguration(ci->c_str());
163 this->EFGen->GenerateImportFile();
165 // Perform the main install script generation.
166 this->cmInstallGenerator::GenerateScript(os);
169 //----------------------------------------------------------------------------
171 cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
172 Indent const& indent)
174 // Create the main install rules first.
175 this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
177 // Now create a configuration-specific install rule for the import
178 // file of each configuration.
179 std::vector<std::string> files;
180 for(std::map<cmStdString, cmStdString>::const_iterator
181 i = this->EFGen->GetConfigImportFiles().begin();
182 i != this->EFGen->GetConfigImportFiles().end(); ++i)
184 files.push_back(i->second);
185 std::string config_test = this->CreateConfigTest(i->first.c_str());
186 os << indent << "IF(" << config_test << ")\n";
187 this->AddInstallRule(os, cmInstallType_FILES, files, false,
188 this->FilePermissions.c_str(), 0, 0, 0,
190 os << indent << "ENDIF(" << config_test << ")\n";
195 //----------------------------------------------------------------------------
196 void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
197 Indent const& indent)
199 // Remove old per-configuration export files if the main changes.
200 std::string installedDir = "$ENV{DESTDIR}";
201 installedDir += this->GetInstallDestination();
203 std::string installedFile = installedDir;
204 installedFile += this->FileName;
205 os << indent << "IF(EXISTS \"" << installedFile << "\")\n";
206 Indent indentN = indent.Next();
207 Indent indentNN = indentN.Next();
208 Indent indentNNN = indentNN.Next();
209 os << indentN << "FILE(DIFFERENT EXPORT_FILE_CHANGED FILES\n"
210 << indentN << " \"" << installedFile << "\"\n"
211 << indentN << " \"" << this->MainImportFile << "\")\n";
212 os << indentN << "IF(EXPORT_FILE_CHANGED)\n";
213 os << indentNN << "FILE(GLOB OLD_CONFIG_FILES \"" << installedDir
214 << this->EFGen->GetConfigImportFileGlob() << "\")\n";
215 os << indentNN << "IF(OLD_CONFIG_FILES)\n";
216 os << indentNNN << "MESSAGE(STATUS \"Old export file \\\"" << installedFile
217 << "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n";
218 os << indentNNN << "FILE(REMOVE ${OLD_CONFIG_FILES})\n";
219 os << indentNN << "ENDIF(OLD_CONFIG_FILES)\n";
220 os << indentN << "ENDIF(EXPORT_FILE_CHANGED)\n";
221 os << indent << "ENDIF()\n";
223 // Install the main export file.
224 std::vector<std::string> files;
225 files.push_back(this->MainImportFile);
226 this->AddInstallRule(os, cmInstallType_FILES, files, false,
227 this->FilePermissions.c_str(), 0, 0, 0, indent);