1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmExportFileGenerator.cxx,v $
6 Date: $Date: 2008/02/01 13:56:00 $
7 Version: $Revision: 1.10 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmExportFileGenerator.h"
19 #include "cmGeneratedFileStream.h"
20 #include "cmMakefile.h"
21 #include "cmSystemTools.h"
24 #include <cmsys/auto_ptr.hxx>
26 //----------------------------------------------------------------------------
27 cmExportFileGenerator::cmExportFileGenerator()
29 this->AppendMode
= false;
32 //----------------------------------------------------------------------------
33 void cmExportFileGenerator::AddConfiguration(const char* config
)
35 this->Configurations
.push_back(config
);
38 //----------------------------------------------------------------------------
39 void cmExportFileGenerator::SetExportFile(const char* mainFile
)
41 this->MainImportFile
= mainFile
;
43 cmSystemTools::GetFilenamePath(this->MainImportFile
);
45 cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile
);
47 cmSystemTools::GetFilenameLastExtension(this->MainImportFile
);
50 //----------------------------------------------------------------------------
51 bool cmExportFileGenerator::GenerateImportFile()
53 // Open the output file to generate it.
54 cmsys::auto_ptr
<std::ofstream
> foutPtr
;
58 cmsys::auto_ptr
<std::ofstream
>
59 ap(new std::ofstream(this->MainImportFile
.c_str(), std::ios::app
));
64 // Generate atomically and with copy-if-different.
65 cmsys::auto_ptr
<cmGeneratedFileStream
>
66 ap(new cmGeneratedFileStream(this->MainImportFile
.c_str(), true));
67 ap
->SetCopyIfDifferent(true);
70 if(!foutPtr
.get() || !*foutPtr
)
72 std::string se
= cmSystemTools::GetLastSystemError();
74 e
<< "cannot write to file \"" << this->MainImportFile
76 cmSystemTools::Error(e
.str().c_str());
79 std::ostream
& os
= *foutPtr
;
81 // Start with the import file header.
82 this->GenerateImportHeaderCode(os
);
84 // Create all the imported targets.
85 bool result
= this->GenerateMainFile(os
);
87 // End with the import file footer.
88 this->GenerateImportFooterCode(os
);
93 //----------------------------------------------------------------------------
94 void cmExportFileGenerator::GenerateImportConfig(std::ostream
& os
,
97 // Construct the property configuration suffix.
98 std::string suffix
= "_";
101 suffix
+= cmSystemTools::UpperCase(config
);
105 suffix
+= "NOCONFIG";
108 // Generate the per-config target information.
109 this->GenerateImportTargetsConfig(os
, config
, suffix
);
112 //----------------------------------------------------------------------------
114 cmExportFileGenerator
115 ::SetImportDetailProperties(const char* config
, std::string
const& suffix
,
116 cmTarget
* target
, ImportPropertyMap
& properties
)
118 // Get the makefile in which to lookup target information.
119 cmMakefile
* mf
= target
->GetMakefile();
121 // Add the soname for unix shared libraries.
122 if(target
->GetType() == cmTarget::SHARED_LIBRARY
||
123 target
->GetType() == cmTarget::MODULE_LIBRARY
)
125 // Check whether this is a DLL platform.
127 (mf
->IsOn("WIN32") || mf
->IsOn("CYGWIN") || mf
->IsOn("MINGW"));
130 std::string soname
= target
->GetSOName(config
);
131 std::string prop
= "IMPORTED_SONAME";
133 properties
[prop
] = soname
;
137 // Add the transitive link dependencies for this configuration.
138 if(cmTargetLinkInterface
const* interface
=
139 target
->GetLinkInterface(config
))
141 // This target provides a link interface, so use it.
142 this->SetImportLinkProperty(suffix
, target
,
143 "IMPORTED_LINK_INTERFACE_LIBRARIES",
144 interface
->Libraries
, properties
);
145 this->SetImportLinkProperty(suffix
, target
,
146 "IMPORTED_LINK_DEPENDENT_LIBRARIES",
147 interface
->SharedDeps
, properties
);
149 else if(target
->GetType() == cmTarget::STATIC_LIBRARY
||
150 target
->GetType() == cmTarget::SHARED_LIBRARY
)
152 // The default link interface for static and shared libraries is
153 // their link implementation library list.
154 this->SetImportLinkProperties(config
, suffix
, target
, properties
);
158 //----------------------------------------------------------------------------
160 cmExportFileGenerator
161 ::SetImportLinkProperties(const char* config
, std::string
const& suffix
,
162 cmTarget
* target
, ImportPropertyMap
& properties
)
164 // Compute which library configuration to link.
165 cmTarget::LinkLibraryType linkType
= cmTarget::OPTIMIZED
;
166 if(config
&& cmSystemTools::UpperCase(config
) == "DEBUG")
168 linkType
= cmTarget::DEBUG
;
171 // Construct the list of libs linked for this configuration.
172 std::vector
<std::string
> actual_libs
;
173 cmTarget::LinkLibraryVectorType
const& libs
=
174 target
->GetOriginalLinkLibraries();
175 for(cmTarget::LinkLibraryVectorType::const_iterator li
= libs
.begin();
176 li
!= libs
.end(); ++li
)
178 // Skip entries that will resolve to the target itself, are empty,
179 // or are not meant for this configuration.
180 if(li
->first
== target
->GetName() || li
->first
.empty() ||
181 !(li
->second
== cmTarget::GENERAL
|| li
->second
== linkType
))
187 actual_libs
.push_back(li
->first
);
190 // Store the entries in the property.
191 this->SetImportLinkProperty(suffix
, target
,
192 "IMPORTED_LINK_INTERFACE_LIBRARIES",
193 actual_libs
, properties
);
196 //----------------------------------------------------------------------------
198 cmExportFileGenerator
199 ::SetImportLinkProperty(std::string
const& suffix
,
201 const char* propName
,
202 std::vector
<std::string
> const& libs
,
203 ImportPropertyMap
& properties
)
205 // Skip the property if there are no libraries.
211 // Get the makefile in which to lookup target information.
212 cmMakefile
* mf
= target
->GetMakefile();
214 // Construct the property value.
215 std::string link_libs
;
216 const char* sep
= "";
217 for(std::vector
<std::string
>::const_iterator li
= libs
.begin();
218 li
!= libs
.end(); ++li
)
220 // Separate this from the previous entry.
224 // Append this entry.
225 if(cmTarget
* tgt
= mf
->FindTargetToUse(li
->c_str()))
228 if(tgt
->IsImported())
230 // The target is imported (and therefore is not in the
231 // export). Append the raw name.
234 else if(this->ExportedTargets
.find(tgt
) != this->ExportedTargets
.end())
236 // The target is in the export. Append it with the export
238 link_libs
+= this->Namespace
;
243 // The target is not in the export.
244 if(!this->AppendMode
)
246 // We are not appending, so all exported targets should be
247 // known here. This is probably user-error.
248 this->ComplainAboutMissingTarget(target
, tgt
);
250 // Assume the target will be exported by another command.
251 // Append it with the export namespace.
252 link_libs
+= this->Namespace
;
258 // Append the raw name.
263 // Store the property.
264 std::string prop
= propName
;
266 properties
[prop
] = link_libs
;
269 //----------------------------------------------------------------------------
270 void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream
& os
,
273 os
<< "#----------------------------------------------------------------\n"
274 << "# Generated CMake target import file";
277 os
<< " for configuration \"" << config
<< "\".\n";
283 os
<< "#----------------------------------------------------------------\n"
285 this->GenerateImportVersionCode(os
);
288 //----------------------------------------------------------------------------
289 void cmExportFileGenerator::GenerateImportFooterCode(std::ostream
& os
)
291 os
<< "# Commands beyond this point should not need to know the version.\n"
292 << "SET(CMAKE_IMPORT_FILE_VERSION)\n";
295 //----------------------------------------------------------------------------
296 void cmExportFileGenerator::GenerateImportVersionCode(std::ostream
& os
)
298 // Store an import file format version. This will let us change the
299 // format later while still allowing old import files to work.
300 os
<< "# Commands may need to know the format version.\n"
301 << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
305 //----------------------------------------------------------------------------
307 cmExportFileGenerator
308 ::GenerateImportTargetCode(std::ostream
& os
, cmTarget
* target
)
310 // Construct the imported target name.
311 std::string targetName
= this->Namespace
;
312 targetName
+= target
->GetName();
314 // Create the imported target.
315 os
<< "# Create imported target " << targetName
<< "\n";
316 switch(target
->GetType())
318 case cmTarget::EXECUTABLE
:
319 os
<< "ADD_EXECUTABLE(" << targetName
<< " IMPORTED)\n";
321 case cmTarget::STATIC_LIBRARY
:
322 os
<< "ADD_LIBRARY(" << targetName
<< " STATIC IMPORTED)\n";
324 case cmTarget::SHARED_LIBRARY
:
325 os
<< "ADD_LIBRARY(" << targetName
<< " SHARED IMPORTED)\n";
327 case cmTarget::MODULE_LIBRARY
:
328 os
<< "ADD_LIBRARY(" << targetName
<< " MODULE IMPORTED)\n";
330 default: // should never happen
334 // Mark the imported executable if it has exports.
335 if(target
->IsExecutableWithExports())
337 os
<< "SET_PROPERTY(TARGET " << targetName
338 << " PROPERTY ENABLE_EXPORTS 1)\n";
341 // Mark the imported library if it is a framework.
342 if(target
->IsFrameworkOnApple())
344 os
<< "SET_PROPERTY(TARGET " << targetName
345 << " PROPERTY FRAMEWORK 1)\n";
348 // Mark the imported executable if it is an application bundle.
349 if(target
->IsAppBundleOnApple())
351 os
<< "SET_PROPERTY(TARGET " << targetName
352 << " PROPERTY MACOSX_BUNDLE 1)\n";
357 //----------------------------------------------------------------------------
359 cmExportFileGenerator
360 ::GenerateImportPropertyCode(std::ostream
& os
, const char* config
,
362 ImportPropertyMap
const& properties
)
364 // Construct the imported target name.
365 std::string targetName
= this->Namespace
;
366 targetName
+= target
->GetName();
368 // Set the import properties.
369 os
<< "# Import target \"" << targetName
<< "\" for configuration \""
371 os
<< "SET_PROPERTY(TARGET " << targetName
372 << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
373 if(config
&& *config
)
375 os
<< cmSystemTools::UpperCase(config
);
382 os
<< "SET_TARGET_PROPERTIES(" << targetName
<< " PROPERTIES\n";
383 for(ImportPropertyMap::const_iterator pi
= properties
.begin();
384 pi
!= properties
.end(); ++pi
)
386 os
<< " " << pi
->first
<< " \"" << pi
->second
<< "\"\n";