Imported Upstream version 2.8.12.2
[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 #include "cmExportSet.h"
27
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,
36   bool exportOld,
37   cmMakefile* mf)
38   :cmInstallGenerator(destination, configurations, component)
39   ,ExportSet(exportSet)
40   ,FilePermissions(file_permissions)
41   ,FileName(filename)
42   ,Namespace(name_space)
43   ,ExportOld(exportOld)
44   ,Makefile(mf)
45 {
46   this->EFGen = new cmExportInstallFileGenerator(this);
47   exportSet->AddInstallation(this);
48 }
49
50 //----------------------------------------------------------------------------
51 cmInstallExportGenerator::~cmInstallExportGenerator()
52 {
53   delete this->EFGen;
54 }
55
56 //----------------------------------------------------------------------------
57 void cmInstallExportGenerator::ComputeTempDir()
58 {
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())
65     {
66     return;
67     }
68   else
69     {
70     this->TempDir += "/";
71     }
72
73   // Enforce a maximum length.
74   bool useMD5 = false;
75 #if defined(_WIN32) || defined(__CYGWIN__)
76   std::string::size_type const max_total_len = 250;
77 #else
78   std::string::size_type const max_total_len = 1000;
79 #endif
80   if(this->TempDir.size() < max_total_len)
81     {
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)
85       {
86       useMD5 = true;
87       }
88     }
89   else
90     {
91     useMD5 = true;
92     }
93   if(useMD5)
94     {
95     // Replace the destination path with a hash to keep it short.
96     this->TempDir +=
97       cmSystemTools::ComputeStringMD5(this->Destination.c_str());
98     }
99   else
100     {
101     std::string dest = this->Destination;
102     // Avoid unix full paths.
103     if(dest[0] == '/')
104       {
105       dest[0] = '_';
106       }
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, "../", "__/");
111     // Avoid spaces.
112     cmSystemTools::ReplaceString(dest, " ", "_");
113     this->TempDir += dest;
114     }
115 }
116
117 //----------------------------------------------------------------------------
118 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
119 {
120   // Skip empty sets.
121   if(ExportSet->GetTargetExports()->empty())
122     {
123     cmOStringStream e;
124     e << "INSTALL(EXPORT) given unknown export \""
125       << ExportSet->GetName() << "\"";
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->SetExportFile(this->MainImportFile.c_str());
141   this->EFGen->SetNamespace(this->Namespace.c_str());
142   this->EFGen->SetExportOld(this->ExportOld);
143   if(this->ConfigurationTypes->empty())
144     {
145     if(this->ConfigurationName && *this->ConfigurationName)
146       {
147       this->EFGen->AddConfiguration(this->ConfigurationName);
148       }
149     else
150       {
151       this->EFGen->AddConfiguration("");
152       }
153     }
154   else
155     {
156     for(std::vector<std::string>::const_iterator
157           ci = this->ConfigurationTypes->begin();
158         ci != this->ConfigurationTypes->end(); ++ci)
159       {
160       this->EFGen->AddConfiguration(ci->c_str());
161       }
162     }
163   this->EFGen->GenerateImportFile();
164
165   // Perform the main install script generation.
166   this->cmInstallGenerator::GenerateScript(os);
167 }
168
169 //----------------------------------------------------------------------------
170 void
171 cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
172                                                 Indent const& indent)
173 {
174   // Create the main install rules first.
175   this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
176
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)
183     {
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,
189                          indent.Next());
190     os << indent << "ENDIF(" << config_test << ")\n";
191     files.clear();
192     }
193 }
194
195 //----------------------------------------------------------------------------
196 void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
197                                                      Indent const& indent)
198 {
199   // Remove old per-configuration export files if the main changes.
200   std::string installedDir = "$ENV{DESTDIR}";
201   installedDir += this->GetInstallDestination();
202   installedDir += "/";
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";
222
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);
228 }