packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmGetPropertyCommand.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 "cmGetPropertyCommand.h"
13
14 #include "cmake.h"
15 #include "cmTest.h"
16 #include "cmGlobalGenerator.h"
17 #include "cmLocalGenerator.h"
18 #include "cmSourceFile.h"
19 #include "cmPropertyDefinition.h"
20
21 //----------------------------------------------------------------------------
22 cmGetPropertyCommand::cmGetPropertyCommand()
23 {
24   this->InfoType = OutValue;
25 }
26
27 //----------------------------------------------------------------------------
28 bool cmGetPropertyCommand
29 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
30 {
31   if(args.size() < 3 )
32     {
33     this->SetError("called with incorrect number of arguments");
34     return false;
35     }
36
37   // The cmake variable in which to store the result.
38   this->Variable = args[0];
39
40   // Get the scope from which to get the property.
41   cmProperty::ScopeType scope;
42   if(args[1] == "GLOBAL")
43     {
44     scope = cmProperty::GLOBAL;
45     }
46   else if(args[1] == "DIRECTORY")
47     {
48     scope = cmProperty::DIRECTORY;
49     }
50   else if(args[1] == "TARGET")
51     {
52     scope = cmProperty::TARGET;
53     }
54   else if(args[1] == "SOURCE")
55     {
56     scope = cmProperty::SOURCE_FILE;
57     }
58   else if(args[1] == "TEST")
59     {
60     scope = cmProperty::TEST;
61     }
62   else if(args[1] == "VARIABLE")
63     {
64     scope = cmProperty::VARIABLE;
65     }
66   else if(args[1] == "CACHE")
67     {
68     scope = cmProperty::CACHE;
69     }
70   else
71     {
72     cmOStringStream e;
73     e << "given invalid scope " << args[1] << ".  "
74       << "Valid scopes are "
75       << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE.";
76     this->SetError(e.str().c_str());
77     return false;
78     }
79
80   // Parse remaining arguments.
81   enum Doing { DoingNone, DoingName, DoingProperty, DoingType };
82   Doing doing = DoingName;
83   for(unsigned int i=2; i < args.size(); ++i)
84     {
85     if(args[i] == "PROPERTY")
86       {
87       doing = DoingProperty;
88       }
89     else if(args[i] == "BRIEF_DOCS")
90       {
91       doing = DoingNone;
92       this->InfoType = OutBriefDoc;
93       }
94     else if(args[i] == "FULL_DOCS")
95       {
96       doing = DoingNone;
97       this->InfoType = OutFullDoc;
98       }
99     else if(args[i] == "SET")
100       {
101       doing = DoingNone;
102       this->InfoType = OutSet;
103       }
104     else if(args[i] == "DEFINED")
105       {
106       doing = DoingNone;
107       this->InfoType = OutDefined;
108       }
109     else if(doing == DoingName)
110       {
111       doing = DoingNone;
112       this->Name = args[i];
113       }
114     else if(doing == DoingProperty)
115       {
116       doing = DoingNone;
117       this->PropertyName = args[i];
118       }
119     else
120       {
121       cmOStringStream e;
122       e << "given invalid argument \"" << args[i] << "\".";
123       this->SetError(e.str().c_str());
124       return false;
125       }
126     }
127
128   // Make sure a property name was found.
129   if(this->PropertyName.empty())
130     {
131     this->SetError("not given a PROPERTY <name> argument.");
132     return false;
133     }
134
135   // Compute requested output.
136   if(this->InfoType == OutBriefDoc)
137     {
138     // Lookup brief documentation.
139     std::string output;
140     if(cmPropertyDefinition* def =
141        this->Makefile->GetCMakeInstance()->
142        GetPropertyDefinition(this->PropertyName.c_str(), scope))
143       {
144       output = def->GetShortDescription();
145       }
146     else
147       {
148       output = "NOTFOUND";
149       }
150     this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
151     }
152   else if(this->InfoType == OutFullDoc)
153     {
154     // Lookup full documentation.
155     std::string output;
156     if(cmPropertyDefinition* def =
157        this->Makefile->GetCMakeInstance()->
158        GetPropertyDefinition(this->PropertyName.c_str(), scope))
159       {
160       output = def->GetFullDescription();
161       }
162     else
163       {
164       output = "NOTFOUND";
165       }
166     this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
167     }
168   else if(this->InfoType == OutDefined)
169     {
170     // Lookup if the property is defined
171     if(this->Makefile->GetCMakeInstance()->
172        GetPropertyDefinition(this->PropertyName.c_str(), scope))
173       {
174       this->Makefile->AddDefinition(this->Variable.c_str(), "1");
175       }
176     else
177       {
178       this->Makefile->AddDefinition(this->Variable.c_str(), "0");
179       }
180     }
181   else
182     {
183     // Dispatch property getting.
184     switch(scope)
185       {
186       case cmProperty::GLOBAL:      return this->HandleGlobalMode();
187       case cmProperty::DIRECTORY:   return this->HandleDirectoryMode();
188       case cmProperty::TARGET:      return this->HandleTargetMode();
189       case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
190       case cmProperty::TEST:        return this->HandleTestMode();
191       case cmProperty::VARIABLE:    return this->HandleVariableMode();
192       case cmProperty::CACHE:       return this->HandleCacheMode();
193
194       case cmProperty::CACHED_VARIABLE:
195         break; // should never happen
196       }
197     }
198
199   return true;
200 }
201
202 //----------------------------------------------------------------------------
203 bool cmGetPropertyCommand::StoreResult(const char* value)
204 {
205   if(this->InfoType == OutSet)
206     {
207     this->Makefile->AddDefinition(this->Variable.c_str(), value? "1":"0");
208     }
209   else // if(this->InfoType == OutValue)
210     {
211     if(value)
212       {
213       this->Makefile->AddDefinition(this->Variable.c_str(), value);
214       }
215     else
216       {
217       this->Makefile->RemoveDefinition(this->Variable.c_str());
218       }
219     }
220   return true;
221 }
222
223 //----------------------------------------------------------------------------
224 bool cmGetPropertyCommand::HandleGlobalMode()
225 {
226   if(!this->Name.empty())
227     {
228     this->SetError("given name for GLOBAL scope.");
229     return false;
230     }
231
232   // Get the property.
233   cmake* cm = this->Makefile->GetCMakeInstance();
234   return this->StoreResult(cm->GetProperty(this->PropertyName.c_str()));
235 }
236
237 //----------------------------------------------------------------------------
238 bool cmGetPropertyCommand::HandleDirectoryMode()
239 {
240   // Default to the current directory.
241   cmMakefile* mf = this->Makefile;
242
243   // Lookup the directory if given.
244   if(!this->Name.empty())
245     {
246     // Construct the directory name.  Interpret relative paths with
247     // respect to the current directory.
248     std::string dir = this->Name;
249     if(!cmSystemTools::FileIsFullPath(dir.c_str()))
250       {
251       dir = this->Makefile->GetCurrentDirectory();
252       dir += "/";
253       dir += this->Name;
254       }
255
256     // The local generators are associated with collapsed paths.
257     dir = cmSystemTools::CollapseFullPath(dir.c_str());
258
259     // Lookup the generator.
260     if(cmLocalGenerator* lg =
261        (this->Makefile->GetLocalGenerator()
262         ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
263       {
264       // Use the makefile for the directory found.
265       mf = lg->GetMakefile();
266       }
267     else
268       {
269       // Could not find the directory.
270       this->SetError
271         ("DIRECTORY scope provided but requested directory was not found. "
272          "This could be because the directory argument was invalid or, "
273          "it is valid but has not been processed yet.");
274       return false;
275       }
276     }
277
278   // Get the property.
279   return this->StoreResult(mf->GetProperty(this->PropertyName.c_str()));
280 }
281
282 //----------------------------------------------------------------------------
283 bool cmGetPropertyCommand::HandleTargetMode()
284 {
285   if(this->Name.empty())
286     {
287     this->SetError("not given name for TARGET scope.");
288     return false;
289     }
290
291   if(this->PropertyName == "ALIASED_TARGET")
292     {
293     if(this->Makefile->IsAlias(this->Name.c_str()))
294       {
295       if(cmTarget* target =
296                           this->Makefile->FindTargetToUse(this->Name.c_str()))
297         {
298         return this->StoreResult(target->GetName());
299         }
300       }
301     return false;
302     }
303   if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
304     {
305     return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
306     }
307   else
308     {
309     cmOStringStream e;
310     e << "could not find TARGET " << this->Name
311       << ".  Perhaps it has not yet been created.";
312     this->SetError(e.str().c_str());
313     return false;
314     }
315 }
316
317 //----------------------------------------------------------------------------
318 bool cmGetPropertyCommand::HandleSourceMode()
319 {
320   if(this->Name.empty())
321     {
322     this->SetError("not given name for SOURCE scope.");
323     return false;
324     }
325
326   // Get the source file.
327   if(cmSourceFile* sf =
328      this->Makefile->GetOrCreateSource(this->Name.c_str()))
329     {
330     return
331       this->StoreResult(sf->GetPropertyForUser(this->PropertyName.c_str()));
332     }
333   else
334     {
335     cmOStringStream e;
336     e << "given SOURCE name that could not be found or created: "
337       << this->Name;
338     this->SetError(e.str().c_str());
339     return false;
340     }
341 }
342
343 //----------------------------------------------------------------------------
344 bool cmGetPropertyCommand::HandleTestMode()
345 {
346   if(this->Name.empty())
347     {
348     this->SetError("not given name for TEST scope.");
349     return false;
350     }
351
352   // Loop over all tests looking for matching names.
353   if(cmTest* test = this->Makefile->GetTest(this->Name.c_str()))
354     {
355     return this->StoreResult(test->GetProperty(this->PropertyName.c_str()));
356     }
357
358   // If not found it is an error.
359   cmOStringStream e;
360   e << "given TEST name that does not exist: " << this->Name;
361   this->SetError(e.str().c_str());
362   return false;
363 }
364
365 //----------------------------------------------------------------------------
366 bool cmGetPropertyCommand::HandleVariableMode()
367 {
368   if(!this->Name.empty())
369     {
370     this->SetError("given name for VARIABLE scope.");
371     return false;
372     }
373
374   return this->StoreResult
375     (this->Makefile->GetDefinition(this->PropertyName.c_str()));
376 }
377
378 //----------------------------------------------------------------------------
379 bool cmGetPropertyCommand::HandleCacheMode()
380 {
381   if(this->Name.empty())
382     {
383     this->SetError("not given name for CACHE scope.");
384     return false;
385     }
386
387   const char* value = 0;
388   cmCacheManager::CacheIterator it =
389     this->Makefile->GetCacheManager()->GetCacheIterator(this->Name.c_str());
390   if(!it.IsAtEnd())
391     {
392     value = it.GetProperty(this->PropertyName.c_str());
393     }
394   this->StoreResult(value);
395   return true;
396 }