1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSetPropertyCommand.cxx,v $
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;
31 //----------------------------------------------------------------------------
32 bool cmSetPropertyCommand
33 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
37 this->SetError("called with incorrect number of arguments");
41 // Get the scope on which to set the property.
42 std::vector
<std::string
>::const_iterator arg
= args
.begin();
43 cmProperty::ScopeType scope
;
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
;
71 e
<< "given invalid scope " << *arg
<< ". "
72 << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, CACHE.";
73 this->SetError(e
.str().c_str());
77 // Parse the rest of the arguments up to the values.
78 enum Doing
{ DoingNone
, DoingNames
, DoingProperty
, DoingValues
};
79 Doing doing
= DoingNames
;
81 for(++arg
; arg
!= args
.end(); ++arg
)
83 if(*arg
== "PROPERTY")
85 doing
= DoingProperty
;
87 else if(*arg
== "APPEND")
90 this->AppendMode
= true;
92 else if(doing
== DoingNames
)
94 this->Names
.insert(*arg
);
96 else if(doing
== DoingProperty
)
98 this->PropertyName
= *arg
;
101 else if(doing
== DoingValues
)
103 this->PropertyValue
+= sep
;
105 this->PropertyValue
+= *arg
;
106 this->Remove
= false;
111 e
<< "given invalid argument \"" << *arg
<< "\".";
112 this->SetError(e
.str().c_str());
117 // Make sure a property name was found.
118 if(this->PropertyName
.empty())
120 this->SetError("not given a PROPERTY <name> argument.");
124 // Dispatch property setting.
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
141 //----------------------------------------------------------------------------
142 bool cmSetPropertyCommand::HandleGlobalMode()
144 if(!this->Names
.empty())
146 this->SetError("given names for GLOBAL scope.");
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();
160 cm
->AppendProperty(name
, value
);
164 cm
->SetProperty(name
, value
);
170 //----------------------------------------------------------------------------
171 bool cmSetPropertyCommand::HandleDirectoryMode()
173 if(this->Names
.size() > 1)
175 this->SetError("allows at most one name for DIRECTORY scope.");
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();
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();
208 // Could not find the directory.
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.");
217 // Set or append the property.
218 const char* name
= this->PropertyName
.c_str();
219 const char *value
= this->PropertyValue
.c_str();
226 mf
->AppendProperty(name
, value
);
230 mf
->SetProperty(name
, value
);
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
))
253 e
<< "could not find TARGET " << *ni
254 << ". Perhaps it has not yet been created.";
255 this->SetError(e
.str().c_str());
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();
274 target
->AppendProperty(name
, value
);
278 target
->SetProperty(name
, value
);
281 // Check the resulting value.
282 target
->CheckProperty(name
, this->Makefile
);
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
))
304 e
<< "given SOURCE name that could not be found or created: " << *ni
;
305 this->SetError(e
.str().c_str());
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();
325 sf
->AppendProperty(name
, value
);
329 sf
->SetProperty(name
, value
);
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
)
344 if(cmTest
* test
= this->Makefile
->GetTest(ni
->c_str()))
346 if(this->HandleTest(test
))
348 this->Names
.erase(ni
);
357 // Names that are still left were not found.
358 if(!this->Names
.empty())
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());
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();
385 test
->AppendProperty(name
, value
);
389 test
->SetProperty(name
, value
);
395 //----------------------------------------------------------------------------
396 bool cmSetPropertyCommand::HandleCacheMode()
398 if(this->PropertyName
== "ADVANCED")
401 !cmSystemTools::IsOn(this->PropertyValue
.c_str()) &&
402 !cmSystemTools::IsOff(this->PropertyValue
.c_str()))
405 e
<< "given non-boolean value \"" << this->PropertyValue
406 << "\" for CACHE property \"ADVANCED\". ";
407 this->SetError(e
.str().c_str());
411 else if(this->PropertyName
== "TYPE")
413 if(!cmCacheManager::IsType(this->PropertyValue
.c_str()))
416 e
<< "given invalid CACHE entry TYPE \"" << this->PropertyValue
<< "\"";
417 this->SetError(e
.str().c_str());
421 else if(this->PropertyName
!= "HELPSTRING" &&
422 this->PropertyName
!= "STRINGS" &&
423 this->PropertyName
!= "VALUE")
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());
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());
443 if(!this->HandleCacheEntry(it
))
451 e
<< "could not find CACHE variable " << *ni
452 << ". Perhaps it has not yet been created.";
453 this->SetError(e
.str().c_str());
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();
472 it
.AppendProperty(name
, value
);
476 it
.SetProperty(name
, value
);