BUG: Fix find_* search order with path suffixes
[cmake.git] / Source / cmGetPropertyCommand.cxx
bloba81eb1bda2826a636d9083612aa969c365f83792
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGetPropertyCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008-04-01 19:22:30 $
7 Version: $Revision: 1.9 $
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 "cmGetPropertyCommand.h"
19 #include "cmake.h"
20 #include "cmTest.h"
21 #include "cmPropertyDefinition.h"
23 //----------------------------------------------------------------------------
24 cmGetPropertyCommand::cmGetPropertyCommand()
26 this->InfoType = OutValue;
29 //----------------------------------------------------------------------------
30 bool cmGetPropertyCommand
31 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
33 if(args.size() < 3 )
35 this->SetError("called with incorrect number of arguments");
36 return false;
39 // The cmake variable in which to store the result.
40 this->Variable = args[0];
42 // Get the scope from which to get the property.
43 cmProperty::ScopeType scope;
44 if(args[1] == "GLOBAL")
46 scope = cmProperty::GLOBAL;
48 else if(args[1] == "DIRECTORY")
50 scope = cmProperty::DIRECTORY;
52 else if(args[1] == "TARGET")
54 scope = cmProperty::TARGET;
56 else if(args[1] == "SOURCE")
58 scope = cmProperty::SOURCE_FILE;
60 else if(args[1] == "TEST")
62 scope = cmProperty::TEST;
64 else if(args[1] == "VARIABLE")
66 scope = cmProperty::VARIABLE;
68 else
70 cmOStringStream e;
71 e << "given invalid scope " << args[1] << ". "
72 << "Valid scopes are "
73 << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE.";
74 this->SetError(e.str().c_str());
75 return false;
78 // Parse remaining arguments.
79 enum Doing { DoingNone, DoingName, DoingProperty, DoingType };
80 Doing doing = DoingName;
81 for(unsigned int i=2; i < args.size(); ++i)
83 if(args[i] == "PROPERTY")
85 doing = DoingProperty;
87 else if(args[i] == "BRIEF_DOCS")
89 doing = DoingNone;
90 this->InfoType = OutBriefDoc;
92 else if(args[i] == "FULL_DOCS")
94 doing = DoingNone;
95 this->InfoType = OutFullDoc;
97 else if(args[i] == "SET")
99 doing = DoingNone;
100 this->InfoType = OutSet;
102 else if(args[i] == "DEFINED")
104 doing = DoingNone;
105 this->InfoType = OutDefined;
107 else if(doing == DoingName)
109 doing = DoingNone;
110 this->Name = args[i];
112 else if(doing == DoingProperty)
114 doing = DoingNone;
115 this->PropertyName = args[i];
117 else
119 cmOStringStream e;
120 e << "given invalid argument \"" << args[i] << "\".";
121 this->SetError(e.str().c_str());
122 return false;
126 // Make sure a property name was found.
127 if(this->PropertyName.empty())
129 this->SetError("not given a PROPERTY <name> argument.");
130 return false;
133 // Compute requested output.
134 if(this->InfoType == OutBriefDoc)
136 // Lookup brief documentation.
137 std::string output;
138 if(cmPropertyDefinition* def =
139 this->Makefile->GetCMakeInstance()->
140 GetPropertyDefinition(this->PropertyName.c_str(), scope))
142 output = def->GetShortDescription();
144 else
146 output = "NOTFOUND";
148 this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
150 else if(this->InfoType == OutFullDoc)
152 // Lookup full documentation.
153 std::string output;
154 if(cmPropertyDefinition* def =
155 this->Makefile->GetCMakeInstance()->
156 GetPropertyDefinition(this->PropertyName.c_str(), scope))
158 output = def->GetFullDescription();
160 else
162 output = "NOTFOUND";
164 this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
166 else if(this->InfoType == OutDefined)
168 // Lookup if the property is defined
169 if(this->Makefile->GetCMakeInstance()->
170 GetPropertyDefinition(this->PropertyName.c_str(), scope))
172 this->Makefile->AddDefinition(this->Variable.c_str(), "1");
174 else
176 this->Makefile->AddDefinition(this->Variable.c_str(), "0");
179 else
181 // Dispatch property getting.
182 switch(scope)
184 case cmProperty::GLOBAL: return this->HandleGlobalMode();
185 case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
186 case cmProperty::TARGET: return this->HandleTargetMode();
187 case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
188 case cmProperty::TEST: return this->HandleTestMode();
189 case cmProperty::VARIABLE: return this->HandleVariableMode();
191 case cmProperty::CACHED_VARIABLE:
192 break; // should never happen
196 return true;
199 //----------------------------------------------------------------------------
200 bool cmGetPropertyCommand::StoreResult(const char* value)
202 if(this->InfoType == OutSet)
204 this->Makefile->AddDefinition(this->Variable.c_str(), value? "1":"0");
206 else // if(this->InfoType == OutValue)
208 this->Makefile->AddDefinition(this->Variable.c_str(), value);
210 return true;
213 //----------------------------------------------------------------------------
214 bool cmGetPropertyCommand::HandleGlobalMode()
216 if(!this->Name.empty())
218 this->SetError("given name for GLOBAL scope.");
219 return false;
222 // Get the property.
223 cmake* cm = this->Makefile->GetCMakeInstance();
224 return this->StoreResult(cm->GetProperty(this->PropertyName.c_str()));
227 //----------------------------------------------------------------------------
228 bool cmGetPropertyCommand::HandleDirectoryMode()
230 // Default to the current directory.
231 cmMakefile* mf = this->Makefile;
233 // Lookup the directory if given.
234 if(!this->Name.empty())
236 // Construct the directory name. Interpret relative paths with
237 // respect to the current directory.
238 std::string dir = this->Name;
239 if(!cmSystemTools::FileIsFullPath(dir.c_str()))
241 dir = this->Makefile->GetCurrentDirectory();
242 dir += "/";
243 dir += this->Name;
246 // The local generators are associated with collapsed paths.
247 dir = cmSystemTools::CollapseFullPath(dir.c_str());
249 // Lookup the generator.
250 if(cmLocalGenerator* lg =
251 (this->Makefile->GetLocalGenerator()
252 ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
254 // Use the makefile for the directory found.
255 mf = lg->GetMakefile();
257 else
259 // Could not find the directory.
260 this->SetError
261 ("DIRECTORY scope provided but requested directory was not found. "
262 "This could be because the directory argument was invalid or, "
263 "it is valid but has not been processed yet.");
264 return false;
268 // Get the property.
269 return this->StoreResult(mf->GetProperty(this->PropertyName.c_str()));
272 //----------------------------------------------------------------------------
273 bool cmGetPropertyCommand::HandleTargetMode()
275 if(this->Name.empty())
277 this->SetError("not given name for TARGET scope.");
278 return false;
281 if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
283 return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
285 else
287 cmOStringStream e;
288 e << "could not find TARGET " << this->Name
289 << ". Perhaps it has not yet been created.";
290 this->SetError(e.str().c_str());
291 return false;
295 //----------------------------------------------------------------------------
296 bool cmGetPropertyCommand::HandleSourceMode()
298 if(this->Name.empty())
300 this->SetError("not given name for SOURCE scope.");
301 return false;
304 // Get the source file.
305 if(cmSourceFile* sf =
306 this->Makefile->GetOrCreateSource(this->Name.c_str()))
308 return
309 this->StoreResult(sf->GetPropertyForUser(this->PropertyName.c_str()));
311 else
313 cmOStringStream e;
314 e << "given SOURCE name that could not be found or created: "
315 << this->Name;
316 this->SetError(e.str().c_str());
317 return false;
321 //----------------------------------------------------------------------------
322 bool cmGetPropertyCommand::HandleTestMode()
324 if(this->Name.empty())
326 this->SetError("not given name for TEST scope.");
327 return false;
330 // Loop over all tests looking for matching names.
331 std::vector<cmTest*> const& tests = *this->Makefile->GetTests();
332 for(std::vector<cmTest*>::const_iterator ti = tests.begin();
333 ti != tests.end(); ++ti)
335 cmTest* test = *ti;
336 if(test->GetName() == this->Name)
338 return this->StoreResult(test->GetProperty(this->PropertyName.c_str()));
342 // If not found it is an error.
343 cmOStringStream e;
344 e << "given TEST name that does not exist: " << this->Name;
345 this->SetError(e.str().c_str());
346 return false;
349 //----------------------------------------------------------------------------
350 bool cmGetPropertyCommand::HandleVariableMode()
352 if(!this->Name.empty())
354 this->SetError("given name for VARIABLE scope.");
355 return false;
358 return this->StoreResult
359 (this->Makefile->GetDefinition(this->PropertyName.c_str()));