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 "cmGetPropertyCommand.h"
16 #include "cmGlobalGenerator.h"
17 #include "cmLocalGenerator.h"
18 #include "cmSourceFile.h"
19 #include "cmPropertyDefinition.h"
21 //----------------------------------------------------------------------------
22 cmGetPropertyCommand::cmGetPropertyCommand()
24 this->InfoType = OutValue;
27 //----------------------------------------------------------------------------
28 bool cmGetPropertyCommand
29 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
33 this->SetError("called with incorrect number of arguments");
37 // The cmake variable in which to store the result.
38 this->Variable = args[0];
40 // Get the scope from which to get the property.
41 cmProperty::ScopeType scope;
42 if(args[1] == "GLOBAL")
44 scope = cmProperty::GLOBAL;
46 else if(args[1] == "DIRECTORY")
48 scope = cmProperty::DIRECTORY;
50 else if(args[1] == "TARGET")
52 scope = cmProperty::TARGET;
54 else if(args[1] == "SOURCE")
56 scope = cmProperty::SOURCE_FILE;
58 else if(args[1] == "TEST")
60 scope = cmProperty::TEST;
62 else if(args[1] == "VARIABLE")
64 scope = cmProperty::VARIABLE;
66 else if(args[1] == "CACHE")
68 scope = cmProperty::CACHE;
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());
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)
85 if(args[i] == "PROPERTY")
87 doing = DoingProperty;
89 else if(args[i] == "BRIEF_DOCS")
92 this->InfoType = OutBriefDoc;
94 else if(args[i] == "FULL_DOCS")
97 this->InfoType = OutFullDoc;
99 else if(args[i] == "SET")
102 this->InfoType = OutSet;
104 else if(args[i] == "DEFINED")
107 this->InfoType = OutDefined;
109 else if(doing == DoingName)
112 this->Name = args[i];
114 else if(doing == DoingProperty)
117 this->PropertyName = args[i];
122 e << "given invalid argument \"" << args[i] << "\".";
123 this->SetError(e.str().c_str());
128 // Make sure a property name was found.
129 if(this->PropertyName.empty())
131 this->SetError("not given a PROPERTY <name> argument.");
135 // Compute requested output.
136 if(this->InfoType == OutBriefDoc)
138 // Lookup brief documentation.
140 if(cmPropertyDefinition* def =
141 this->Makefile->GetCMakeInstance()->
142 GetPropertyDefinition(this->PropertyName.c_str(), scope))
144 output = def->GetShortDescription();
150 this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
152 else if(this->InfoType == OutFullDoc)
154 // Lookup full documentation.
156 if(cmPropertyDefinition* def =
157 this->Makefile->GetCMakeInstance()->
158 GetPropertyDefinition(this->PropertyName.c_str(), scope))
160 output = def->GetFullDescription();
166 this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
168 else if(this->InfoType == OutDefined)
170 // Lookup if the property is defined
171 if(this->Makefile->GetCMakeInstance()->
172 GetPropertyDefinition(this->PropertyName.c_str(), scope))
174 this->Makefile->AddDefinition(this->Variable.c_str(), "1");
178 this->Makefile->AddDefinition(this->Variable.c_str(), "0");
183 // Dispatch property getting.
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();
194 case cmProperty::CACHED_VARIABLE:
195 break; // should never happen
202 //----------------------------------------------------------------------------
203 bool cmGetPropertyCommand::StoreResult(const char* value)
205 if(this->InfoType == OutSet)
207 this->Makefile->AddDefinition(this->Variable.c_str(), value? "1":"0");
209 else // if(this->InfoType == OutValue)
213 this->Makefile->AddDefinition(this->Variable.c_str(), value);
217 this->Makefile->RemoveDefinition(this->Variable.c_str());
223 //----------------------------------------------------------------------------
224 bool cmGetPropertyCommand::HandleGlobalMode()
226 if(!this->Name.empty())
228 this->SetError("given name for GLOBAL scope.");
233 cmake* cm = this->Makefile->GetCMakeInstance();
234 return this->StoreResult(cm->GetProperty(this->PropertyName.c_str()));
237 //----------------------------------------------------------------------------
238 bool cmGetPropertyCommand::HandleDirectoryMode()
240 // Default to the current directory.
241 cmMakefile* mf = this->Makefile;
243 // Lookup the directory if given.
244 if(!this->Name.empty())
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()))
251 dir = this->Makefile->GetCurrentDirectory();
256 // The local generators are associated with collapsed paths.
257 dir = cmSystemTools::CollapseFullPath(dir.c_str());
259 // Lookup the generator.
260 if(cmLocalGenerator* lg =
261 (this->Makefile->GetLocalGenerator()
262 ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
264 // Use the makefile for the directory found.
265 mf = lg->GetMakefile();
269 // Could not find the directory.
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.");
279 return this->StoreResult(mf->GetProperty(this->PropertyName.c_str()));
282 //----------------------------------------------------------------------------
283 bool cmGetPropertyCommand::HandleTargetMode()
285 if(this->Name.empty())
287 this->SetError("not given name for TARGET scope.");
291 if(this->PropertyName == "ALIASED_TARGET")
293 if(this->Makefile->IsAlias(this->Name.c_str()))
295 if(cmTarget* target =
296 this->Makefile->FindTargetToUse(this->Name.c_str()))
298 return this->StoreResult(target->GetName());
303 if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
305 return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
310 e << "could not find TARGET " << this->Name
311 << ". Perhaps it has not yet been created.";
312 this->SetError(e.str().c_str());
317 //----------------------------------------------------------------------------
318 bool cmGetPropertyCommand::HandleSourceMode()
320 if(this->Name.empty())
322 this->SetError("not given name for SOURCE scope.");
326 // Get the source file.
327 if(cmSourceFile* sf =
328 this->Makefile->GetOrCreateSource(this->Name.c_str()))
331 this->StoreResult(sf->GetPropertyForUser(this->PropertyName.c_str()));
336 e << "given SOURCE name that could not be found or created: "
338 this->SetError(e.str().c_str());
343 //----------------------------------------------------------------------------
344 bool cmGetPropertyCommand::HandleTestMode()
346 if(this->Name.empty())
348 this->SetError("not given name for TEST scope.");
352 // Loop over all tests looking for matching names.
353 if(cmTest* test = this->Makefile->GetTest(this->Name.c_str()))
355 return this->StoreResult(test->GetProperty(this->PropertyName.c_str()));
358 // If not found it is an error.
360 e << "given TEST name that does not exist: " << this->Name;
361 this->SetError(e.str().c_str());
365 //----------------------------------------------------------------------------
366 bool cmGetPropertyCommand::HandleVariableMode()
368 if(!this->Name.empty())
370 this->SetError("given name for VARIABLE scope.");
374 return this->StoreResult
375 (this->Makefile->GetDefinition(this->PropertyName.c_str()));
378 //----------------------------------------------------------------------------
379 bool cmGetPropertyCommand::HandleCacheMode()
381 if(this->Name.empty())
383 this->SetError("not given name for CACHE scope.");
387 const char* value = 0;
388 cmCacheManager::CacheIterator it =
389 this->Makefile->GetCacheManager()->GetCacheIterator(this->Name.c_str());
392 value = it.GetProperty(this->PropertyName.c_str());
394 this->StoreResult(value);