Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmInstallExportGenerator.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
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"
13
14 #include <stdio.h>
15
16 #include "cmake.h"
17 #include "cmInstallTargetGenerator.h"
18 #include "cmGeneratedFileStream.h"
19 #include "cmMakefile.h"
20 #include "cmLocalGenerator.h"
21 #include "cmGlobalGenerator.h"
22
23 #include "cmInstallFilesGenerator.h"
24
25 #include "cmExportInstallFileGenerator.h"
26
27 //----------------------------------------------------------------------------
28 cmInstallExportGenerator::cmInstallExportGenerator(
29   const char* name,
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,
35   cmMakefile* mf)
36   :cmInstallGenerator(destination, configurations, component)
37   ,Name(name)
38   ,FilePermissions(file_permissions)
39   ,FileName(filename)
40   ,Namespace(name_space)
41   ,Makefile(mf)
42 {
43   this->EFGen = new cmExportInstallFileGenerator(this);
44 }
45
46 //----------------------------------------------------------------------------
47 cmInstallExportGenerator::~cmInstallExportGenerator()
48 {
49   delete this->EFGen;
50 }
51
52 //----------------------------------------------------------------------------
53 void cmInstallExportGenerator::ComputeTempDir()
54 {
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())
61     {
62     return;
63     }
64   else
65     {
66     this->TempDir += "/";
67     }
68
69   // Enforce a maximum length.
70   bool useMD5 = false;
71 #if defined(_WIN32) || defined(__CYGWIN__)
72   std::string::size_type const max_total_len = 250;
73 #else
74   std::string::size_type const max_total_len = 1000;
75 #endif
76   if(this->TempDir.size() < max_total_len)
77     {
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)
81       {
82       useMD5 = true;
83       }
84     }
85   else
86     {
87     useMD5 = true;
88     }
89   if(useMD5)
90     {
91     // Replace the destination path with a hash to keep it short.
92     this->TempDir +=
93       cmSystemTools::ComputeStringMD5(this->Destination.c_str());
94     }
95   else
96     {
97     std::string dest = this->Destination;
98     // Avoid unix full paths.
99     if(dest[0] == '/')
100       {
101       dest[0] = '_';
102       }
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, "../", "__/");
107     // Avoid spaces.
108     cmSystemTools::ReplaceString(dest, " ", "_");
109     this->TempDir += dest;
110     }
111 }
112
113 //----------------------------------------------------------------------------
114 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
115 {
116   // Get the export set requested.
117   ExportSet const* exportSet =
118     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
119     ->GetExportSet(this->Name.c_str());
120
121   // Skip empty sets.
122   if(!exportSet)
123     {
124     cmOStringStream e;
125     e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
126     cmSystemTools::Error(e.str().c_str());
127     return;
128     }
129
130   // Create the temporary directory in which to store the files.
131   this->ComputeTempDir();
132   cmSystemTools::MakeDirectory(this->TempDir.c_str());
133
134   // Construct a temporary location for the file.
135   this->MainImportFile = this->TempDir;
136   this->MainImportFile += "/";
137   this->MainImportFile += this->FileName;
138
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())
145     {
146     if(this->ConfigurationName && *this->ConfigurationName)
147       {
148       this->EFGen->AddConfiguration(this->ConfigurationName);
149       }
150     else
151       {
152       this->EFGen->AddConfiguration("");
153       }
154     }
155   else
156     {
157     for(std::vector<std::string>::const_iterator
158           ci = this->ConfigurationTypes->begin();
159         ci != this->ConfigurationTypes->end(); ++ci)
160       {
161       this->EFGen->AddConfiguration(ci->c_str());
162       }
163     }
164   this->EFGen->GenerateImportFile();
165
166   // Perform the main install script generation.
167   this->cmInstallGenerator::GenerateScript(os);
168 }
169
170 //----------------------------------------------------------------------------
171 void
172 cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
173                                                 Indent const& indent)
174 {
175   // Create the main install rules first.
176   this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
177
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)
184     {
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,
190                          indent.Next());
191     os << indent << "ENDIF(" << config_test << ")\n";
192     files.clear();
193     }
194 }
195
196 //----------------------------------------------------------------------------
197 void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
198                                                      Indent const& indent)
199 {
200   // Remove old per-configuration export files if the main changes.
201   std::string installedDir = "$ENV{DESTDIR}";
202   installedDir += this->GetInstallDestination();
203   installedDir += "/";
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";
223
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);
229 }