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 "cmExportInstallFileGenerator.h"
14 #include "cmGeneratedFileStream.h"
15 #include "cmInstallExportGenerator.h"
16 #include "cmInstallTargetGenerator.h"
18 //----------------------------------------------------------------------------
19 cmExportInstallFileGenerator
20 ::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
21 InstallExportGenerator(iegen)
25 //----------------------------------------------------------------------------
26 std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
28 std::string glob = this->FileBase;
30 glob += this->FileExt;
34 //----------------------------------------------------------------------------
35 bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
37 // Create all the imported targets.
38 for(std::vector<cmTargetExport*>::const_iterator
39 tei = this->ExportSet->begin();
40 tei != this->ExportSet->end(); ++tei)
42 cmTargetExport* te = *tei;
43 if(this->ExportedTargets.insert(te->Target).second)
45 this->GenerateImportTargetCode(os, te->Target);
50 e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
51 << "includes target \"" << te->Target->GetName()
52 << "\" more than once in the export set.";
53 cmSystemTools::Error(e.str().c_str());
58 // Now load per-configuration properties for them.
59 os << "# Load information for each installed configuration.\n"
60 << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
61 << "FILE(GLOB CONFIG_FILES \"${_DIR}/"
62 << this->GetConfigImportFileGlob() << "\")\n"
63 << "FOREACH(f ${CONFIG_FILES})\n"
68 // Generate an import file for each configuration.
70 for(std::vector<std::string>::const_iterator
71 ci = this->Configurations.begin();
72 ci != this->Configurations.end(); ++ci)
74 if(!this->GenerateImportFileConfig(ci->c_str()))
82 //----------------------------------------------------------------------------
84 cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
86 // Skip configurations not enabled for this export.
87 if(!this->InstallExportGenerator->InstallsForConfig(config))
92 // Construct the name of the file to generate.
93 std::string fileName = this->FileDir;
95 fileName += this->FileBase;
99 fileName += cmSystemTools::LowerCase(config);
103 fileName += "noconfig";
105 fileName += this->FileExt;
107 // Open the output file to generate it.
108 cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
109 if(!exportFileStream)
111 std::string se = cmSystemTools::GetLastSystemError();
113 e << "cannot write to file \"" << fileName.c_str()
115 cmSystemTools::Error(e.str().c_str());
118 std::ostream& os = exportFileStream;
120 // Start with the import file header.
121 this->GenerateImportHeaderCode(os, config);
123 // Generate the per-config target information.
124 this->GenerateImportConfig(os, config);
126 // End with the import file footer.
127 this->GenerateImportFooterCode(os);
129 // Record this per-config import file.
130 this->ConfigImportFiles[config] = fileName;
135 //----------------------------------------------------------------------------
137 cmExportInstallFileGenerator
138 ::GenerateImportTargetsConfig(std::ostream& os,
139 const char* config, std::string const& suffix)
141 // Add code to compute the installation prefix relative to the
142 // import file location.
143 const char* installDest = this->InstallExportGenerator->GetDestination();
144 if(!cmSystemTools::FileIsFullPath(installDest))
146 std::string dest = installDest;
147 os << "# Compute the installation prefix relative to this file.\n"
148 << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
149 << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
153 "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
154 dest = cmSystemTools::GetFilenamePath(dest);
158 // Import location properties may reference this variable.
159 this->ImportPrefix = "${_IMPORT_PREFIX}/";
162 // Add each target in the set to the export.
163 for(std::vector<cmTargetExport*>::const_iterator
164 tei = this->ExportSet->begin();
165 tei != this->ExportSet->end(); ++tei)
167 // Collect import properties for this target.
168 cmTargetExport* te = *tei;
169 ImportPropertyMap properties;
170 std::set<std::string> importedLocations;
171 this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
172 properties, importedLocations);
173 this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
174 properties, importedLocations);
175 this->SetImportLocationProperty(config, suffix,
176 te->RuntimeGenerator, properties,
178 this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
179 properties, importedLocations);
180 this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
181 properties, importedLocations);
183 // If any file location was set for the target add it to the
185 if(!properties.empty())
187 // Get the rest of the target details.
188 this->SetImportDetailProperties(config, suffix,
189 te->Target, properties);
191 // TOOD: PUBLIC_HEADER_LOCATION
192 // This should wait until the build feature propagation stuff
193 // is done. Then this can be a propagated include directory.
194 // this->GenerateImportProperty(config, te->HeaderGenerator,
197 // Generate code in the export file.
198 this->GenerateImportPropertyCode(os, config, te->Target, properties);
199 this->GenerateImportedFileChecksCode(os, te->Target, properties,
204 this->GenerateImportedFileCheckLoop(os);
206 // Cleanup the import prefix variable.
207 if(!this->ImportPrefix.empty())
209 os << "# Cleanup temporary variables.\n"
210 << "SET(_IMPORT_PREFIX)\n"
215 //----------------------------------------------------------------------------
217 cmExportInstallFileGenerator
218 ::SetImportLocationProperty(const char* config, std::string const& suffix,
219 cmInstallTargetGenerator* itgen,
220 ImportPropertyMap& properties,
221 std::set<std::string>& importedLocations
224 // Skip rules that do not match this configuration.
225 if(!(itgen && itgen->InstallsForConfig(config)))
230 // Get the target to be installed.
231 cmTarget* target = itgen->GetTarget();
233 // Construct the installed location of the target.
234 std::string dest = itgen->GetDestination();
236 if(!cmSystemTools::FileIsFullPath(dest.c_str()))
238 // The target is installed relative to the installation prefix.
239 if(this->ImportPrefix.empty())
241 this->ComplainAboutImportPrefix(itgen);
243 value = this->ImportPrefix;
248 if(itgen->IsImportLibrary())
250 // Construct the property name.
251 std::string prop = "IMPORTED_IMPLIB";
254 // Append the installed file name.
255 value += itgen->GetInstallFilename(target, config,
256 cmInstallTargetGenerator::NameImplib);
258 // Store the property.
259 properties[prop] = value;
260 importedLocations.insert(prop);
264 // Construct the property name.
265 std::string prop = "IMPORTED_LOCATION";
268 // Append the installed file name.
269 if(target->IsFrameworkOnApple())
271 value += itgen->GetInstallFilename(target, config);
272 value += ".framework/";
273 value += itgen->GetInstallFilename(target, config);
275 else if(target->IsCFBundleOnApple())
277 const char *ext = target->GetProperty("BUNDLE_EXTENSION");
283 value += itgen->GetInstallFilename(target, config);
287 value += itgen->GetInstallFilename(target, config);
289 else if(target->IsAppBundleOnApple())
291 value += itgen->GetInstallFilename(target, config);
292 value += ".app/Contents/MacOS/";
293 value += itgen->GetInstallFilename(target, config);
297 value += itgen->GetInstallFilename(target, config,
298 cmInstallTargetGenerator::NameReal);
301 // Store the property.
302 properties[prop] = value;
303 importedLocations.insert(prop);
307 //----------------------------------------------------------------------------
309 cmExportInstallFileGenerator
310 ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
312 const char* installDest = this->InstallExportGenerator->GetDestination();
314 e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
315 << "DESTINATION \"" << installDest << "\" but the export "
316 << "references an installation of target \""
317 << itgen->GetTarget()->GetName() << "\" which has relative "
318 << "DESTINATION \"" << itgen->GetDestination() << "\".";
319 cmSystemTools::Error(e.str().c_str());
322 //----------------------------------------------------------------------------
324 cmExportInstallFileGenerator
325 ::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
328 e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
329 << "includes target \"" << depender->GetName()
330 << "\" which requires target \"" << dependee->GetName()
331 << "\" that is not in the export set.";
332 cmSystemTools::Error(e.str().c_str());