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"
27 //----------------------------------------------------------------------------
28 cmInstallExportGenerator::cmInstallExportGenerator(
30 const char* destination,
31 const char* file_permissions,
32 std::vector<std::string> const& configurations,
33 const char* component,
34 const char* filename, const char* name_space,
36 :cmInstallGenerator(destination, configurations, component)
38 ,FilePermissions(file_permissions)
40 ,Namespace(name_space)
43 this->EFGen = new cmExportInstallFileGenerator(this);
46 //----------------------------------------------------------------------------
47 cmInstallExportGenerator::~cmInstallExportGenerator()
52 //----------------------------------------------------------------------------
53 void cmInstallExportGenerator::ComputeTempDir()
55 // Choose a temporary directory in which to generate the import
56 // files to be installed.
57 this->TempDir = this->Makefile->GetCurrentOutputDirectory();
58 this->TempDir += cmake::GetCMakeFilesDirectory();
59 this->TempDir += "/Export";
60 if(this->Destination.empty())
69 // Enforce a maximum length.
71 #if defined(_WIN32) || defined(__CYGWIN__)
72 std::string::size_type const max_total_len = 250;
74 std::string::size_type const max_total_len = 1000;
76 if(this->TempDir.size() < max_total_len)
78 // Keep the total path length below the limit.
79 std::string::size_type max_len = max_total_len - this->TempDir.size();
80 if(this->Destination.size() > max_len)
91 // Replace the destination path with a hash to keep it short.
93 cmSystemTools::ComputeStringMD5(this->Destination.c_str());
97 std::string dest = this->Destination;
98 // Avoid unix full paths.
103 // Avoid windows full paths by removing colons.
104 cmSystemTools::ReplaceString(dest, ":", "_");
105 // Avoid relative paths that go up the tree.
106 cmSystemTools::ReplaceString(dest, "../", "__/");
108 cmSystemTools::ReplaceString(dest, " ", "_");
109 this->TempDir += dest;
113 //----------------------------------------------------------------------------
114 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
116 // Get the export set requested.
117 ExportSet const* exportSet =
118 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
119 ->GetExportSet(this->Name.c_str());
125 e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
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->SetName(this->Name.c_str());
141 this->EFGen->SetExportSet(exportSet);
142 this->EFGen->SetExportFile(this->MainImportFile.c_str());
143 this->EFGen->SetNamespace(this->Namespace.c_str());
144 if(this->ConfigurationTypes->empty())
146 if(this->ConfigurationName && *this->ConfigurationName)
148 this->EFGen->AddConfiguration(this->ConfigurationName);
152 this->EFGen->AddConfiguration("");
157 for(std::vector<std::string>::const_iterator
158 ci = this->ConfigurationTypes->begin();
159 ci != this->ConfigurationTypes->end(); ++ci)
161 this->EFGen->AddConfiguration(ci->c_str());
164 this->EFGen->GenerateImportFile();
166 // Perform the main install script generation.
167 this->cmInstallGenerator::GenerateScript(os);
170 //----------------------------------------------------------------------------
172 cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
173 Indent const& indent)
175 // Create the main install rules first.
176 this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
178 // Now create a configuration-specific install rule for the import
179 // file of each configuration.
180 std::vector<std::string> files;
181 for(std::map<cmStdString, cmStdString>::const_iterator
182 i = this->EFGen->GetConfigImportFiles().begin();
183 i != this->EFGen->GetConfigImportFiles().end(); ++i)
185 files.push_back(i->second);
186 std::string config_test = this->CreateConfigTest(i->first.c_str());
187 os << indent << "IF(" << config_test << ")\n";
188 this->AddInstallRule(os, cmInstallType_FILES, files, false,
189 this->FilePermissions.c_str(), 0, 0, 0,
191 os << indent << "ENDIF(" << config_test << ")\n";
196 //----------------------------------------------------------------------------
197 void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
198 Indent const& indent)
200 // Remove old per-configuration export files if the main changes.
201 std::string installedDir = "$ENV{DESTDIR}";
202 installedDir += this->GetInstallDestination();
204 std::string installedFile = installedDir;
205 installedFile += this->FileName;
206 os << indent << "IF(EXISTS \"" << installedFile << "\")\n";
207 Indent indentN = indent.Next();
208 Indent indentNN = indentN.Next();
209 Indent indentNNN = indentNN.Next();
210 os << indentN << "FILE(DIFFERENT EXPORT_FILE_CHANGED FILES\n"
211 << indentN << " \"" << installedFile << "\"\n"
212 << indentN << " \"" << this->MainImportFile << "\")\n";
213 os << indentN << "IF(EXPORT_FILE_CHANGED)\n";
214 os << indentNN << "FILE(GLOB OLD_CONFIG_FILES \"" << installedDir
215 << this->EFGen->GetConfigImportFileGlob() << "\")\n";
216 os << indentNN << "IF(OLD_CONFIG_FILES)\n";
217 os << indentNNN << "MESSAGE(STATUS \"Old export file \\\"" << installedFile
218 << "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n";
219 os << indentNNN << "FILE(REMOVE ${OLD_CONFIG_FILES})\n";
220 os << indentNN << "ENDIF(OLD_CONFIG_FILES)\n";
221 os << indentN << "ENDIF(EXPORT_FILE_CHANGED)\n";
222 os << indent << "ENDIF()\n";
224 // Install the main export file.
225 std::vector<std::string> files;
226 files.push_back(this->MainImportFile);
227 this->AddInstallRule(os, cmInstallType_FILES, files, false,
228 this->FilePermissions.c_str(), 0, 0, 0, indent);