cmScriptGenerator.cxx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmScriptGenerator.h"
  11. #include "cmSystemTools.h"
  12. //----------------------------------------------------------------------------
  13. cmScriptGenerator
  14. ::cmScriptGenerator(const std::string& config_var,
  15. std::vector<std::string> const& configurations):
  16. RuntimeConfigVariable(config_var),
  17. Configurations(configurations),
  18. ConfigurationName(0),
  19. ConfigurationTypes(0),
  20. ActionsPerConfig(false)
  21. {
  22. }
  23. //----------------------------------------------------------------------------
  24. cmScriptGenerator
  25. ::~cmScriptGenerator()
  26. {
  27. }
  28. //----------------------------------------------------------------------------
  29. void
  30. cmScriptGenerator
  31. ::Generate(std::ostream& os, const char* config,
  32. std::vector<std::string> const& configurationTypes)
  33. {
  34. this->ConfigurationName = config;
  35. this->ConfigurationTypes = &configurationTypes;
  36. this->GenerateScript(os);
  37. this->ConfigurationName = 0;
  38. this->ConfigurationTypes = 0;
  39. }
  40. //----------------------------------------------------------------------------
  41. static void cmScriptGeneratorEncodeConfig(const char* config,
  42. std::string& result)
  43. {
  44. for(const char* c = config; *c; ++c)
  45. {
  46. if(*c >= 'a' && *c <= 'z')
  47. {
  48. result += "[";
  49. result += static_cast<char>(*c + 'A' - 'a');
  50. result += *c;
  51. result += "]";
  52. }
  53. else if(*c >= 'A' && *c <= 'Z')
  54. {
  55. result += "[";
  56. result += *c;
  57. result += static_cast<char>(*c + 'a' - 'A');
  58. result += "]";
  59. }
  60. else
  61. {
  62. result += *c;
  63. }
  64. }
  65. }
  66. //----------------------------------------------------------------------------
  67. std::string
  68. cmScriptGenerator::CreateConfigTest(const char* config)
  69. {
  70. std::string result = "\"${";
  71. result += this->RuntimeConfigVariable;
  72. result += "}\" MATCHES \"^(";
  73. if(config && *config)
  74. {
  75. cmScriptGeneratorEncodeConfig(config, result);
  76. }
  77. result += ")$\"";
  78. return result;
  79. }
  80. //----------------------------------------------------------------------------
  81. std::string
  82. cmScriptGenerator::CreateConfigTest(std::vector<std::string> const& configs)
  83. {
  84. std::string result = "\"${";
  85. result += this->RuntimeConfigVariable;
  86. result += "}\" MATCHES \"^(";
  87. const char* sep = "";
  88. for(std::vector<std::string>::const_iterator ci = configs.begin();
  89. ci != configs.end(); ++ci)
  90. {
  91. result += sep;
  92. sep = "|";
  93. cmScriptGeneratorEncodeConfig(ci->c_str(), result);
  94. }
  95. result += ")$\"";
  96. return result;
  97. }
  98. //----------------------------------------------------------------------------
  99. void cmScriptGenerator::GenerateScript(std::ostream& os)
  100. {
  101. // Track indentation.
  102. Indent indent;
  103. // Generate the script possibly with per-configuration code.
  104. this->GenerateScriptConfigs(os, indent);
  105. }
  106. //----------------------------------------------------------------------------
  107. void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os,
  108. Indent const& indent)
  109. {
  110. if(this->ActionsPerConfig)
  111. {
  112. this->GenerateScriptActionsPerConfig(os, indent);
  113. }
  114. else
  115. {
  116. this->GenerateScriptActionsOnce(os, indent);
  117. }
  118. }
  119. //----------------------------------------------------------------------------
  120. void cmScriptGenerator::GenerateScriptActions(std::ostream& os,
  121. Indent const& indent)
  122. {
  123. if(this->ActionsPerConfig)
  124. {
  125. // This is reached for single-configuration build generators in a
  126. // per-config script generator.
  127. this->GenerateScriptForConfig(os, this->ConfigurationName, indent);
  128. }
  129. }
  130. //----------------------------------------------------------------------------
  131. void cmScriptGenerator::GenerateScriptForConfig(std::ostream&, const char*,
  132. Indent const&)
  133. {
  134. // No actions for this generator.
  135. }
  136. //----------------------------------------------------------------------------
  137. bool cmScriptGenerator::GeneratesForConfig(const char* config)
  138. {
  139. // If this is not a configuration-specific rule then we install.
  140. if(this->Configurations.empty())
  141. {
  142. return true;
  143. }
  144. // This is a configuration-specific rule. Check if the config
  145. // matches this rule.
  146. std::string config_upper = cmSystemTools::UpperCase(config?config:"");
  147. for(std::vector<std::string>::const_iterator i =
  148. this->Configurations.begin();
  149. i != this->Configurations.end(); ++i)
  150. {
  151. if(cmSystemTools::UpperCase(*i) == config_upper)
  152. {
  153. return true;
  154. }
  155. }
  156. return false;
  157. }
  158. //----------------------------------------------------------------------------
  159. void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
  160. Indent const& indent)
  161. {
  162. if(this->Configurations.empty())
  163. {
  164. // This rule is for all configurations.
  165. this->GenerateScriptActions(os, indent);
  166. }
  167. else
  168. {
  169. // Generate a per-configuration block.
  170. std::string config_test = this->CreateConfigTest(this->Configurations);
  171. os << indent << "if(" << config_test << ")\n";
  172. this->GenerateScriptActions(os, indent.Next());
  173. os << indent << "endif(" << config_test << ")\n";
  174. }
  175. }
  176. //----------------------------------------------------------------------------
  177. void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os,
  178. Indent const& indent)
  179. {
  180. if(this->ConfigurationTypes->empty())
  181. {
  182. // In a single-configuration generator there is only one action
  183. // and it applies if the runtime-requested configuration is among
  184. // the rule's allowed configurations. The configuration built in
  185. // the tree does not matter for this decision but will be used to
  186. // generate proper target file names into the code.
  187. this->GenerateScriptActionsOnce(os, indent);
  188. }
  189. else
  190. {
  191. // In a multi-configuration generator we produce a separate rule
  192. // in a block for each configuration that is built. We restrict
  193. // the list of configurations to those to which this rule applies.
  194. bool first = true;
  195. for(std::vector<std::string>::const_iterator i =
  196. this->ConfigurationTypes->begin();
  197. i != this->ConfigurationTypes->end(); ++i)
  198. {
  199. const char* config = i->c_str();
  200. if(this->GeneratesForConfig(config))
  201. {
  202. // Generate a per-configuration block.
  203. std::string config_test = this->CreateConfigTest(config);
  204. os << indent << (first? "if(" : "elseif(") << config_test << ")\n";
  205. this->GenerateScriptForConfig(os, config, indent.Next());
  206. first = false;
  207. }
  208. }
  209. if(!first)
  210. {
  211. if(this->NeedsScriptNoConfig())
  212. {
  213. os << indent << "else()\n";
  214. this->GenerateScriptNoConfig(os, indent.Next());
  215. }
  216. os << indent << "endif()\n";
  217. }
  218. }
  219. }