packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmExportBuildFileGenerator.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 "cmExportBuildFileGenerator.h"
13
14 #include "cmExportCommand.h"
15
16 //----------------------------------------------------------------------------
17 cmExportBuildFileGenerator::cmExportBuildFileGenerator()
18 {
19   this->ExportCommand = 0;
20 }
21
22 //----------------------------------------------------------------------------
23 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
24 {
25   std::vector<cmTarget*> allTargets;
26   {
27   std::string expectedTargets;
28   std::string sep;
29   for(std::vector<cmTarget*>::const_iterator
30         tei = this->Exports->begin();
31       tei != this->Exports->end(); ++tei)
32     {
33     expectedTargets += sep + this->Namespace + (*tei)->GetExportName();
34     sep = " ";
35     cmTarget* te = *tei;
36     if(this->ExportedTargets.insert(te).second)
37       {
38       allTargets.push_back(te);
39       }
40     else
41       {
42       if(this->ExportCommand && this->ExportCommand->ErrorMessage.empty())
43         {
44         cmOStringStream e;
45         e << "given target \"" << te->GetName() << "\" more than once.";
46         this->ExportCommand->ErrorMessage = e.str();
47         }
48       return false;
49       }
50     }
51
52   this->GenerateExpectedTargetsCode(os, expectedTargets);
53   }
54
55   std::vector<std::string> missingTargets;
56
57   // Create all the imported targets.
58   for(std::vector<cmTarget*>::const_iterator
59         tei = allTargets.begin();
60       tei != allTargets.end(); ++tei)
61     {
62     cmTarget* te = *tei;
63     this->GenerateImportTargetCode(os, te);
64
65     te->AppendBuildInterfaceIncludes();
66
67     ImportPropertyMap properties;
68
69     this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
70                                     cmGeneratorExpression::BuildInterface,
71                                     properties, missingTargets);
72     this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
73                                     cmGeneratorExpression::BuildInterface,
74                                     properties, missingTargets);
75     this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", te,
76                                     cmGeneratorExpression::BuildInterface,
77                                     properties, missingTargets);
78     this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
79                                   te, properties);
80     const bool newCMP0022Behavior =
81                               te->GetPolicyStatusCMP0022() != cmPolicies::WARN
82                            && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
83     if (newCMP0022Behavior)
84       {
85       this->PopulateInterfaceLinkLibrariesProperty(te,
86                                     cmGeneratorExpression::BuildInterface,
87                                     properties, missingTargets);
88       }
89     this->PopulateCompatibleInterfaceProperties(te, properties);
90
91     this->GenerateInterfaceProperties(te, os, properties);
92     }
93
94   // Generate import file content for each configuration.
95   for(std::vector<std::string>::const_iterator
96         ci = this->Configurations.begin();
97       ci != this->Configurations.end(); ++ci)
98     {
99     this->GenerateImportConfig(os, ci->c_str(), missingTargets);
100     }
101
102   this->GenerateMissingTargetsCheckCode(os, missingTargets);
103
104   return true;
105 }
106
107 //----------------------------------------------------------------------------
108 void
109 cmExportBuildFileGenerator
110 ::GenerateImportTargetsConfig(std::ostream& os,
111                               const char* config, std::string const& suffix,
112                             std::vector<std::string> &missingTargets)
113 {
114   for(std::vector<cmTarget*>::const_iterator
115         tei = this->Exports->begin();
116       tei != this->Exports->end(); ++tei)
117     {
118     // Collect import properties for this target.
119     cmTarget* target = *tei;
120     ImportPropertyMap properties;
121     this->SetImportLocationProperty(config, suffix, target, properties);
122     if(!properties.empty())
123       {
124       // Get the rest of the target details.
125       this->SetImportDetailProperties(config, suffix,
126                                       target, properties, missingTargets);
127       this->SetImportLinkInterface(config, suffix,
128                                    cmGeneratorExpression::BuildInterface,
129                                    target, properties, missingTargets);
130
131
132       // TOOD: PUBLIC_HEADER_LOCATION
133       // This should wait until the build feature propagation stuff
134       // is done.  Then this can be a propagated include directory.
135       // this->GenerateImportProperty(config, te->HeaderGenerator,
136       //                              properties);
137
138       // Generate code in the export file.
139       this->GenerateImportPropertyCode(os, config, target, properties);
140       }
141     }
142 }
143
144 //----------------------------------------------------------------------------
145 void
146 cmExportBuildFileGenerator
147 ::SetImportLocationProperty(const char* config, std::string const& suffix,
148                             cmTarget* target, ImportPropertyMap& properties)
149 {
150   // Get the makefile in which to lookup target information.
151   cmMakefile* mf = target->GetMakefile();
152
153   // Add the main target file.
154   {
155   std::string prop = "IMPORTED_LOCATION";
156   prop += suffix;
157   std::string value;
158   if(target->IsAppBundleOnApple())
159     {
160     value = target->GetFullPath(config, false);
161     }
162   else
163     {
164     value = target->GetFullPath(config, false, true);
165     }
166   properties[prop] = value;
167   }
168
169   // Check whether this is a DLL platform.
170   bool dll_platform =
171     (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
172
173   // Add the import library for windows DLLs.
174   if(dll_platform &&
175      (target->GetType() == cmTarget::SHARED_LIBRARY ||
176       target->IsExecutableWithExports()) &&
177      mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
178     {
179     std::string prop = "IMPORTED_IMPLIB";
180     prop += suffix;
181     std::string value = target->GetFullPath(config, true);
182     target->GetImplibGNUtoMS(value, value,
183                              "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
184     properties[prop] = value;
185     }
186 }
187
188 //----------------------------------------------------------------------------
189 void
190 cmExportBuildFileGenerator::HandleMissingTarget(
191   std::string& link_libs, std::vector<std::string>&,
192   cmMakefile*, cmTarget* depender, cmTarget* dependee)
193 {
194   // The target is not in the export.
195   if(!this->AppendMode)
196     {
197     // We are not appending, so all exported targets should be
198     // known here.  This is probably user-error.
199     this->ComplainAboutMissingTarget(depender, dependee);
200     }
201   // Assume the target will be exported by another command.
202   // Append it with the export namespace.
203   link_libs += this->Namespace;
204   link_libs += dependee->GetExportName();
205 }
206
207 //----------------------------------------------------------------------------
208 void
209 cmExportBuildFileGenerator
210 ::ComplainAboutMissingTarget(cmTarget* depender,
211                              cmTarget* dependee)
212 {
213   if(!this->ExportCommand || !this->ExportCommand->ErrorMessage.empty())
214     {
215     return;
216     }
217
218   cmOStringStream e;
219   e << "called with target \"" << depender->GetName()
220     << "\" which requires target \"" << dependee->GetName()
221     << "\" that is not in the export list.\n"
222     << "If the required target is not easy to reference in this call, "
223     << "consider using the APPEND option with multiple separate calls.";
224   this->ExportCommand->ErrorMessage = e.str();
225 }
226
227 std::string
228 cmExportBuildFileGenerator::InstallNameDir(cmTarget* target,
229                                            const std::string& config)
230 {
231   std::string install_name_dir;
232
233   cmMakefile* mf = target->GetMakefile();
234   if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
235     {
236     install_name_dir =
237       target->GetInstallNameDirForBuildTree(config.c_str());
238     }
239
240   return install_name_dir;
241 }