STYLE: Nightly Date Stamp
[cmake.git] / Source / cmSetPropertyCommand.cxx
blobaadbda707a63bbc74d3f97eb68151a0755bd0de8
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSetPropertyCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008-08-19 15:43:51 $
7 Version: $Revision: 1.8 $
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 //----------------------------------------------------------------------------
23 cmSetPropertyCommand::cmSetPropertyCommand()
25 this->AppendMode = false;
26 this->Remove = true;
29 //----------------------------------------------------------------------------
30 bool cmSetPropertyCommand
31 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
33 if(args.size() < 2 )
35 this->SetError("called with incorrect number of arguments");
36 return false;
39 // Get the scope on which to set the property.
40 std::vector<std::string>::const_iterator arg = args.begin();
41 cmProperty::ScopeType scope;
42 if(*arg == "GLOBAL")
44 scope = cmProperty::GLOBAL;
46 else if(*arg == "DIRECTORY")
48 scope = cmProperty::DIRECTORY;
50 else if(*arg == "TARGET")
52 scope = cmProperty::TARGET;
54 else if(*arg == "SOURCE")
56 scope = cmProperty::SOURCE_FILE;
58 else if(*arg == "TEST")
60 scope = cmProperty::TEST;
62 else
64 cmOStringStream e;
65 e << "given invalid scope " << *arg << ". "
66 << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST.";
67 this->SetError(e.str().c_str());
68 return false;
71 // Parse the rest of the arguments up to the values.
72 enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
73 Doing doing = DoingNames;
74 const char* sep = "";
75 for(++arg; arg != args.end(); ++arg)
77 if(*arg == "PROPERTY")
79 doing = DoingProperty;
81 else if(*arg == "APPEND")
83 doing = DoingNone;
84 this->AppendMode = true;
86 else if(doing == DoingNames)
88 this->Names.insert(*arg);
90 else if(doing == DoingProperty)
92 this->PropertyName = *arg;
93 doing = DoingValues;
95 else if(doing == DoingValues)
97 this->PropertyValue += sep;
98 sep = ";";
99 this->PropertyValue += *arg;
100 this->Remove = false;
102 else
104 cmOStringStream e;
105 e << "given invalid argument \"" << *arg << "\".";
106 this->SetError(e.str().c_str());
107 return false;
111 // Make sure a property name was found.
112 if(this->PropertyName.empty())
114 this->SetError("not given a PROPERTY <name> argument.");
115 return false;
118 // Dispatch property setting.
119 switch(scope)
121 case cmProperty::GLOBAL: return this->HandleGlobalMode();
122 case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
123 case cmProperty::TARGET: return this->HandleTargetMode();
124 case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
125 case cmProperty::TEST: return this->HandleTestMode();
127 case cmProperty::VARIABLE:
128 case cmProperty::CACHED_VARIABLE:
129 break; // should never happen
131 return true;
134 //----------------------------------------------------------------------------
135 bool cmSetPropertyCommand::HandleGlobalMode()
137 if(!this->Names.empty())
139 this->SetError("given names for GLOBAL scope.");
140 return false;
143 // Set or append the property.
144 cmake* cm = this->Makefile->GetCMakeInstance();
145 const char* name = this->PropertyName.c_str();
146 const char *value = this->PropertyValue.c_str();
147 if (this->Remove)
149 value = 0;
151 if(this->AppendMode)
153 cm->AppendProperty(name, value);
155 else
157 cm->SetProperty(name, value);
160 return true;
163 //----------------------------------------------------------------------------
164 bool cmSetPropertyCommand::HandleDirectoryMode()
166 if(this->Names.size() > 1)
168 this->SetError("allows at most one name for DIRECTORY scope.");
169 return false;
172 // Default to the current directory.
173 cmMakefile* mf = this->Makefile;
175 // Lookup the directory if given.
176 if(!this->Names.empty())
178 // Construct the directory name. Interpret relative paths with
179 // respect to the current directory.
180 std::string dir = *this->Names.begin();
181 if(!cmSystemTools::FileIsFullPath(dir.c_str()))
183 dir = this->Makefile->GetCurrentDirectory();
184 dir += "/";
185 dir += *this->Names.begin();
188 // The local generators are associated with collapsed paths.
189 dir = cmSystemTools::CollapseFullPath(dir.c_str());
191 // Lookup the generator.
192 if(cmLocalGenerator* lg =
193 (this->Makefile->GetLocalGenerator()
194 ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
196 // Use the makefile for the directory found.
197 mf = lg->GetMakefile();
199 else
201 // Could not find the directory.
202 this->SetError
203 ("DIRECTORY scope provided but requested directory was not found. "
204 "This could be because the directory argument was invalid or, "
205 "it is valid but has not been processed yet.");
206 return false;
210 // Set or append the property.
211 const char* name = this->PropertyName.c_str();
212 const char *value = this->PropertyValue.c_str();
213 if (this->Remove)
215 value = 0;
217 if(this->AppendMode)
219 mf->AppendProperty(name, value);
221 else
223 mf->SetProperty(name, value);
226 return true;
229 //----------------------------------------------------------------------------
230 bool cmSetPropertyCommand::HandleTargetMode()
232 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
233 ni != this->Names.end(); ++ni)
235 if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
237 // Handle the current target.
238 if(!this->HandleTarget(target))
240 return false;
243 else
245 cmOStringStream e;
246 e << "could not find TARGET " << *ni
247 << ". Perhaps it has not yet been created.";
248 this->SetError(e.str().c_str());
249 return false;
252 return true;
255 //----------------------------------------------------------------------------
256 bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
258 // Set or append the property.
259 const char* name = this->PropertyName.c_str();
260 const char *value = this->PropertyValue.c_str();
261 if (this->Remove)
263 value = 0;
265 if(this->AppendMode)
267 target->AppendProperty(name, value);
269 else
271 target->SetProperty(name, value);
274 // Check the resulting value.
275 target->CheckProperty(name, this->Makefile);
277 return true;
280 //----------------------------------------------------------------------------
281 bool cmSetPropertyCommand::HandleSourceMode()
283 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
284 ni != this->Names.end(); ++ni)
286 // Get the source file.
287 if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
289 if(!this->HandleSource(sf))
291 return false;
294 else
296 cmOStringStream e;
297 e << "given SOURCE name that could not be found or created: " << *ni;
298 this->SetError(e.str().c_str());
299 return false;
302 return true;
305 //----------------------------------------------------------------------------
306 bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
308 // Set or append the property.
309 const char* name = this->PropertyName.c_str();
310 const char *value = this->PropertyValue.c_str();
311 if (this->Remove)
313 value = 0;
316 if(this->AppendMode)
318 sf->AppendProperty(name, value);
320 else
322 sf->SetProperty(name, value);
324 return true;
327 //----------------------------------------------------------------------------
328 bool cmSetPropertyCommand::HandleTestMode()
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 std::set<cmStdString>::iterator ni =
337 this->Names.find(test->GetName());
338 if(ni != this->Names.end())
340 if(this->HandleTest(test))
342 this->Names.erase(ni);
344 else
346 return false;
351 // Names that are still left were not found.
352 if(!this->Names.empty())
354 cmOStringStream e;
355 e << "given TEST names that do not exist:\n";
356 for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
357 ni != this->Names.end(); ++ni)
359 e << " " << *ni << "\n";
361 this->SetError(e.str().c_str());
362 return false;
364 return true;
367 //----------------------------------------------------------------------------
368 bool cmSetPropertyCommand::HandleTest(cmTest* test)
370 // Set or append the property.
371 const char* name = this->PropertyName.c_str();
372 const char *value = this->PropertyValue.c_str();
373 if (this->Remove)
375 value = 0;
377 if(this->AppendMode)
379 test->AppendProperty(name, value);
381 else
383 test->SetProperty(name, value);
386 return true;