1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmScriptGenerator.cxx,v $
6 Date: $Date: 2009-03-16 14:39:51 $
7 Version: $Revision: 1.1 $
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 "cmScriptGenerator.h"
19 #include "cmSystemTools.h"
21 //----------------------------------------------------------------------------
23 ::cmScriptGenerator(const char* config_var
,
24 std::vector
<std::string
> const& configurations
):
25 RuntimeConfigVariable(config_var
),
26 Configurations(configurations
),
28 ConfigurationTypes(0),
29 ActionsPerConfig(false)
33 //----------------------------------------------------------------------------
35 ::~cmScriptGenerator()
39 //----------------------------------------------------------------------------
42 ::Generate(std::ostream
& os
, const char* config
,
43 std::vector
<std::string
> const& configurationTypes
)
45 this->ConfigurationName
= config
;
46 this->ConfigurationTypes
= &configurationTypes
;
47 this->GenerateScript(os
);
48 this->ConfigurationName
= 0;
49 this->ConfigurationTypes
= 0;
52 //----------------------------------------------------------------------------
53 static void cmScriptGeneratorEncodeConfig(const char* config
,
56 for(const char* c
= config
; *c
; ++c
)
58 if(*c
>= 'a' && *c
<= 'z')
61 result
+= *c
+ ('A' - 'a');
65 else if(*c
>= 'A' && *c
<= 'Z')
69 result
+= *c
+ ('a' - 'A');
79 //----------------------------------------------------------------------------
81 cmScriptGenerator::CreateConfigTest(const char* config
)
83 std::string result
= "\"${";
84 result
+= this->RuntimeConfigVariable
;
85 result
+= "}\" MATCHES \"^(";
88 cmScriptGeneratorEncodeConfig(config
, result
);
94 //----------------------------------------------------------------------------
96 cmScriptGenerator::CreateConfigTest(std::vector
<std::string
> const& configs
)
98 std::string result
= "\"${";
99 result
+= this->RuntimeConfigVariable
;
100 result
+= "}\" MATCHES \"^(";
101 const char* sep
= "";
102 for(std::vector
<std::string
>::const_iterator ci
= configs
.begin();
103 ci
!= configs
.end(); ++ci
)
107 cmScriptGeneratorEncodeConfig(ci
->c_str(), result
);
113 //----------------------------------------------------------------------------
114 void cmScriptGenerator::GenerateScript(std::ostream
& os
)
116 // Track indentation.
119 // Generate the script possibly with per-configuration code.
120 this->GenerateScriptConfigs(os
, indent
);
123 //----------------------------------------------------------------------------
124 void cmScriptGenerator::GenerateScriptConfigs(std::ostream
& os
,
125 Indent
const& indent
)
127 if(this->ActionsPerConfig
)
129 this->GenerateScriptActionsPerConfig(os
, indent
);
133 this->GenerateScriptActionsOnce(os
, indent
);
137 //----------------------------------------------------------------------------
138 void cmScriptGenerator::GenerateScriptActions(std::ostream
& os
,
139 Indent
const& indent
)
141 if(this->ActionsPerConfig
)
143 // This is reached for single-configuration build generators in a
144 // per-config script generator.
145 this->GenerateScriptForConfig(os
, this->ConfigurationName
, indent
);
149 //----------------------------------------------------------------------------
150 void cmScriptGenerator::GenerateScriptForConfig(std::ostream
&, const char*,
153 // No actions for this generator.
156 //----------------------------------------------------------------------------
157 bool cmScriptGenerator::GeneratesForConfig(const char* config
)
159 // If this is not a configuration-specific rule then we install.
160 if(this->Configurations
.empty())
165 // This is a configuration-specific rule. Check if the config
166 // matches this rule.
167 std::string config_upper
= cmSystemTools::UpperCase(config
?config
:"");
168 for(std::vector
<std::string
>::const_iterator i
=
169 this->Configurations
.begin();
170 i
!= this->Configurations
.end(); ++i
)
172 if(cmSystemTools::UpperCase(*i
) == config_upper
)
180 //----------------------------------------------------------------------------
181 void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream
& os
,
182 Indent
const& indent
)
184 if(this->Configurations
.empty())
186 // This rule is for all configurations.
187 this->GenerateScriptActions(os
, indent
);
191 // Generate a per-configuration block.
192 std::string config_test
= this->CreateConfigTest(this->Configurations
);
193 os
<< indent
<< "IF(" << config_test
<< ")\n";
194 this->GenerateScriptActions(os
, indent
.Next());
195 os
<< indent
<< "ENDIF(" << config_test
<< ")\n";
199 //----------------------------------------------------------------------------
200 void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream
& os
,
201 Indent
const& indent
)
203 if(this->ConfigurationTypes
->empty())
205 // In a single-configuration generator there is only one action
206 // and it applies if the runtime-requested configuration is among
207 // the rule's allowed configurations. The configuration built in
208 // the tree does not matter for this decision but will be used to
209 // generate proper target file names into the code.
210 this->GenerateScriptActionsOnce(os
, indent
);
214 // In a multi-configuration generator we produce a separate rule
215 // in a block for each configuration that is built. We restrict
216 // the list of configurations to those to which this rule applies.
217 for(std::vector
<std::string
>::const_iterator i
=
218 this->ConfigurationTypes
->begin();
219 i
!= this->ConfigurationTypes
->end(); ++i
)
221 const char* config
= i
->c_str();
222 if(this->GeneratesForConfig(config
))
224 // Generate a per-configuration block.
225 std::string config_test
= this->CreateConfigTest(config
);
226 os
<< indent
<< "IF(" << config_test
<< ")\n";
227 this->GenerateScriptForConfig(os
, config
, indent
.Next());
228 os
<< indent
<< "ENDIF(" << config_test
<< ")\n";