1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmSetPropertyCommand.cxx,v $
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;
29 //----------------------------------------------------------------------------
30 bool cmSetPropertyCommand
31 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
35 this->SetError("called with incorrect number of arguments");
39 // Get the scope on which to set the property.
40 std::vector
<std::string
>::const_iterator arg
= args
.begin();
41 cmProperty::ScopeType scope
;
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
;
65 e
<< "given invalid scope " << *arg
<< ". "
66 << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST.";
67 this->SetError(e
.str().c_str());
71 // Parse the rest of the arguments up to the values.
72 enum Doing
{ DoingNone
, DoingNames
, DoingProperty
, DoingValues
};
73 Doing doing
= DoingNames
;
75 for(++arg
; arg
!= args
.end(); ++arg
)
77 if(*arg
== "PROPERTY")
79 doing
= DoingProperty
;
81 else if(*arg
== "APPEND")
84 this->AppendMode
= true;
86 else if(doing
== DoingNames
)
88 this->Names
.insert(*arg
);
90 else if(doing
== DoingProperty
)
92 this->PropertyName
= *arg
;
95 else if(doing
== DoingValues
)
97 this->PropertyValue
+= sep
;
99 this->PropertyValue
+= *arg
;
100 this->Remove
= false;
105 e
<< "given invalid argument \"" << *arg
<< "\".";
106 this->SetError(e
.str().c_str());
111 // Make sure a property name was found.
112 if(this->PropertyName
.empty())
114 this->SetError("not given a PROPERTY <name> argument.");
118 // Dispatch property setting.
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
134 //----------------------------------------------------------------------------
135 bool cmSetPropertyCommand::HandleGlobalMode()
137 if(!this->Names
.empty())
139 this->SetError("given names for GLOBAL scope.");
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();
153 cm
->AppendProperty(name
, value
);
157 cm
->SetProperty(name
, value
);
163 //----------------------------------------------------------------------------
164 bool cmSetPropertyCommand::HandleDirectoryMode()
166 if(this->Names
.size() > 1)
168 this->SetError("allows at most one name for DIRECTORY scope.");
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();
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();
201 // Could not find the directory.
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.");
210 // Set or append the property.
211 const char* name
= this->PropertyName
.c_str();
212 const char *value
= this->PropertyValue
.c_str();
219 mf
->AppendProperty(name
, value
);
223 mf
->SetProperty(name
, value
);
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
))
246 e
<< "could not find TARGET " << *ni
247 << ". Perhaps it has not yet been created.";
248 this->SetError(e
.str().c_str());
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();
267 target
->AppendProperty(name
, value
);
271 target
->SetProperty(name
, value
);
274 // Check the resulting value.
275 target
->CheckProperty(name
, this->Makefile
);
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
))
297 e
<< "given SOURCE name that could not be found or created: " << *ni
;
298 this->SetError(e
.str().c_str());
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();
318 sf
->AppendProperty(name
, value
);
322 sf
->SetProperty(name
, value
);
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
)
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
);
351 // Names that are still left were not found.
352 if(!this->Names
.empty())
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());
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();
379 test
->AppendProperty(name
, value
);
383 test
->SetProperty(name
, value
);