ENH: check in almost building VMS stuff with VMSBuild directory since the bootstrap...
[cmake.git] / Source / cmSetPropertyCommand.cxx
blob2b2df74ff09269b2a31cdecbf34b44ead9a0c96d
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSetPropertyCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-12 14:52:40 $
7 Version: $Revision: 1.11 $
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 "cmSetPropertyCommand.h"
18 #include "cmSetTargetPropertiesCommand.h"
19 #include "cmSetTestsPropertiesCommand.h"
20 #include "cmSetSourceFilesPropertiesCommand.h"
22 #include "cmCacheManager.h"
24 //----------------------------------------------------------------------------
25 cmSetPropertyCommand::cmSetPropertyCommand()
27 this->AppendMode = false;
28 this->Remove = true;
31 //----------------------------------------------------------------------------
32 bool cmSetPropertyCommand
33 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
35 if(args.size() < 2 )
37 this->SetError("called with incorrect number of arguments");
38 return false;
41 // Get the scope on which to set the property.
42 std::vector<std::string>::const_iterator arg = args.begin();
43 cmProperty::ScopeType scope;
44 if(*arg == "GLOBAL")
46 scope = cmProperty::GLOBAL;
48 else if(*arg == "DIRECTORY")
50 scope = cmProperty::DIRECTORY;
52 else if(*arg == "TARGET")
54 scope = cmProperty::TARGET;
56 else if(*arg == "SOURCE")
58 scope = cmProperty::SOURCE_FILE;
60 else if(*arg == "TEST")
62 scope = cmProperty::TEST;
64 else if(*arg == "CACHE")
66 scope = cmProperty::CACHE;
68 else
70 cmOStringStream e;
71 e << "given invalid scope " << *arg << ". "
72 << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, CACHE.";
73 this->SetError(e.str().c_str());
74 return false;
77 // Parse the rest of the arguments up to the values.
78 enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
79 Doing doing = DoingNames;
80 const char* sep = "";
81 for(++arg; arg != args.end(); ++arg)
83 if(*arg == "PROPERTY")
85 doing = DoingProperty;
87 else if(*arg == "APPEND")
89 doing = DoingNone;
90 this->AppendMode = true;
92 else if(doing == DoingNames)
94 this->Names.insert(*arg);
96 else if(doing == DoingProperty)
98 this->PropertyName = *arg;
99 doing = DoingValues;
101 else if(doing == DoingValues)
103 this->PropertyValue += sep;
104 sep = ";";
105 this->PropertyValue += *arg;
106 this->Remove = false;
108 else
110 cmOStringStream e;
111 e << "given invalid argument \"" << *arg << "\".";
112 this->SetError(e.str().c_str());
113 return false;
117 // Make sure a property name was found.
118 if(this->PropertyName.empty())
120 this->SetError("not given a PROPERTY <name> argument.");
121 return false;
124 // Dispatch property setting.
125 switch(scope)
127 case cmProperty::GLOBAL: return this->HandleGlobalMode();
128 case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
129 case cmProperty::TARGET: return this->HandleTargetMode();
130 case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
131 case cmProperty::TEST: return this->HandleTestMode();
132 case cmProperty::CACHE: return this->HandleCacheMode();
134 case cmProperty::VARIABLE:
135 case cmProperty::CACHED_VARIABLE:
136 break; // should never happen
138 return true;
141 //----------------------------------------------------------------------------
142 bool cmSetPropertyCommand::HandleGlobalMode()
144 if(!this->Names.empty())
146 this->SetError("given names for GLOBAL scope.");
147 return false;
150 // Set or append the property.
151 cmake* cm = this->Makefile->GetCMakeInstance();
152 const char* name = this->PropertyName.c_str();
153 const char *value = this->PropertyValue.c_str();
154 if (this->Remove)
156 value = 0;
158 if(this->AppendMode)
160 cm->AppendProperty(name, value);
162 else
164 cm->SetProperty(name, value);
167 return true;
170 //----------------------------------------------------------------------------
171 bool cmSetPropertyCommand::HandleDirectoryMode()
173 if(this->Names.size() > 1)
175 this->SetError("allows at most one name for DIRECTORY scope.");
176 return false;
179 // Default to the current directory.
180 cmMakefile* mf = this->Makefile;
182 // Lookup the directory if given.
183 if(!this->Names.empty())
185 // Construct the directory name. Interpret relative paths with
186 // respect to the current directory.
187 std::string dir = *this->Names.begin();
188 if(!cmSystemTools::FileIsFullPath(dir.c_str()))
190 dir = this->Makefile->GetCurrentDirectory();
191 dir += "/";
192 dir += *this->Names.begin();
195 // The local generators are associated with collapsed paths.
196 dir = cmSystemTools::CollapseFullPath(dir.c_str());
198 // Lookup the generator.
199 if(cmLocalGenerator* lg =
200 (this->Makefile->GetLocalGenerator()
201 ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
203 // Use the makefile for the directory found.
204 mf = lg->GetMakefile();
206 else
208 // Could not find the directory.
209 this->SetError
210 ("DIRECTORY scope provided but requested directory was not found. "
211 "This could be because the directory argument was invalid or, "
212 "it is valid but has not been processed yet.");
213 return false;
217 // Set or append the property.
218 const char* name = this->PropertyName.c_str();
219 const char *value = this->PropertyValue.c_str();
220 if (this->Remove)
222 value = 0;
224 if(this->AppendMode)
226 mf->AppendProperty(name, value);
228 else
230 mf->SetProperty(name, value);
233 return true;
236 //----------------------------------------------------------------------------
237 bool cmSetPropertyCommand::HandleTargetMode()
239 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
240 ni != this->Names.end(); ++ni)
242 if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
244 // Handle the current target.
245 if(!this->HandleTarget(target))
247 return false;
250 else
252 cmOStringStream e;
253 e << "could not find TARGET " << *ni
254 << ". Perhaps it has not yet been created.";
255 this->SetError(e.str().c_str());
256 return false;
259 return true;
262 //----------------------------------------------------------------------------
263 bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
265 // Set or append the property.
266 const char* name = this->PropertyName.c_str();
267 const char *value = this->PropertyValue.c_str();
268 if (this->Remove)
270 value = 0;
272 if(this->AppendMode)
274 target->AppendProperty(name, value);
276 else
278 target->SetProperty(name, value);
281 // Check the resulting value.
282 target->CheckProperty(name, this->Makefile);
284 return true;
287 //----------------------------------------------------------------------------
288 bool cmSetPropertyCommand::HandleSourceMode()
290 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
291 ni != this->Names.end(); ++ni)
293 // Get the source file.
294 if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
296 if(!this->HandleSource(sf))
298 return false;
301 else
303 cmOStringStream e;
304 e << "given SOURCE name that could not be found or created: " << *ni;
305 this->SetError(e.str().c_str());
306 return false;
309 return true;
312 //----------------------------------------------------------------------------
313 bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
315 // Set or append the property.
316 const char* name = this->PropertyName.c_str();
317 const char *value = this->PropertyValue.c_str();
318 if (this->Remove)
320 value = 0;
323 if(this->AppendMode)
325 sf->AppendProperty(name, value);
327 else
329 sf->SetProperty(name, value);
331 return true;
334 //----------------------------------------------------------------------------
335 bool cmSetPropertyCommand::HandleTestMode()
337 // Look for tests with all names given.
338 std::set<cmStdString>::iterator next;
339 for(std::set<cmStdString>::iterator ni = this->Names.begin();
340 ni != this->Names.end(); ni = next)
342 next = ni;
343 ++next;
344 if(cmTest* test = this->Makefile->GetTest(ni->c_str()))
346 if(this->HandleTest(test))
348 this->Names.erase(ni);
350 else
352 return false;
357 // Names that are still left were not found.
358 if(!this->Names.empty())
360 cmOStringStream e;
361 e << "given TEST names that do not exist:\n";
362 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
363 ni != this->Names.end(); ++ni)
365 e << " " << *ni << "\n";
367 this->SetError(e.str().c_str());
368 return false;
370 return true;
373 //----------------------------------------------------------------------------
374 bool cmSetPropertyCommand::HandleTest(cmTest* test)
376 // Set or append the property.
377 const char* name = this->PropertyName.c_str();
378 const char *value = this->PropertyValue.c_str();
379 if (this->Remove)
381 value = 0;
383 if(this->AppendMode)
385 test->AppendProperty(name, value);
387 else
389 test->SetProperty(name, value);
392 return true;
395 //----------------------------------------------------------------------------
396 bool cmSetPropertyCommand::HandleCacheMode()
398 if(this->PropertyName == "ADVANCED")
400 if(!this->Remove &&
401 !cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
402 !cmSystemTools::IsOff(this->PropertyValue.c_str()))
404 cmOStringStream e;
405 e << "given non-boolean value \"" << this->PropertyValue
406 << "\" for CACHE property \"ADVANCED\". ";
407 this->SetError(e.str().c_str());
408 return false;
411 else if(this->PropertyName == "TYPE")
413 if(!cmCacheManager::IsType(this->PropertyValue.c_str()))
415 cmOStringStream e;
416 e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\"";
417 this->SetError(e.str().c_str());
418 return false;
421 else if(this->PropertyName != "HELPSTRING" &&
422 this->PropertyName != "STRINGS" &&
423 this->PropertyName != "VALUE")
425 cmOStringStream e;
426 e << "given invalid CACHE property " << this->PropertyName << ". "
427 << "Settable CACHE properties are: "
428 << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE.";
429 this->SetError(e.str().c_str());
430 return false;
433 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
434 ni != this->Names.end(); ++ni)
436 // Get the source file.
437 cmMakefile* mf = this->GetMakefile();
438 cmake* cm = mf->GetCMakeInstance();
439 cmCacheManager::CacheIterator it =
440 cm->GetCacheManager()->GetCacheIterator(ni->c_str());
441 if(!it.IsAtEnd())
443 if(!this->HandleCacheEntry(it))
445 return false;
448 else
450 cmOStringStream e;
451 e << "could not find CACHE variable " << *ni
452 << ". Perhaps it has not yet been created.";
453 this->SetError(e.str().c_str());
454 return false;
457 return true;
460 //----------------------------------------------------------------------------
461 bool cmSetPropertyCommand::HandleCacheEntry(cmCacheManager::CacheIterator& it)
463 // Set or append the property.
464 const char* name = this->PropertyName.c_str();
465 const char* value = this->PropertyValue.c_str();
466 if (this->Remove)
468 value = 0;
470 if(this->AppendMode)
472 it.AppendProperty(name, value);
474 else
476 it.SetProperty(name, value);
479 return true;