cmScriptGenerator.cxx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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(""),
  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 std::string& config,
  32. std::vector<std::string> const& configurationTypes)
  33. {
  34. this->ConfigurationName = config;
  35. this->ConfigurationTypes = &configurationTypes;
  36. this->GenerateScript(os);
  37. this->ConfigurationName = "";
  38. this->ConfigurationTypes = 0;
  39. }
  40. //----------------------------------------------------------------------------
  41. static void cmScriptGeneratorEncodeConfig(const std::string& config,
  42. std::string& result)
  43. {
  44. for(const char* c = config.c_str(); *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 std::string& config)
  69. {
  70. std::string result = "\"${";
  71. result += this->RuntimeConfigVariable;
  72. result += "}\" MATCHES \"^(";
  73. if(!config.empty())
  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&,
  132. const std::string&,
  133. Indent const&)
  134. {
  135. // No actions for this generator.
  136. }
  137. //----------------------------------------------------------------------------
  138. bool cmScriptGenerator::GeneratesForConfig(const std::string& config)
  139. {
  140. // If this is not a configuration-specific rule then we install.
  141. if(this->Configurations.empty())
  142. {
  143. return true;
  144. }
  145. // This is a configuration-specific rule. Check if the config
  146. // matches this rule.
  147. std::string config_upper = cmSystemTools::UpperCase(config);
  148. for(std::vector<std::string>::const_iterator i =
  149. this->Configurations.begin();
  150. i != this->Configurations.end(); ++i)
  151. {
  152. if(cmSystemTools::UpperCase(*i) == config_upper)
  153. {
  154. return true;
  155. }
  156. }
  157. return false;
  158. }
  159. //----------------------------------------------------------------------------
  160. void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
  161. Indent const& indent)
  162. {
  163. if(this->Configurations.empty())
  164. {
  165. // This rule is for all configurations.
  166. this->GenerateScriptActions(os, indent);
  167. }
  168. else
  169. {
  170. // Generate a per-configuration block.
  171. std::string config_test = this->CreateConfigTest(this->Configurations);
  172. os << indent << "if(" << config_test << ")\n";
  173. this->GenerateScriptActions(os, indent.Next());
  174. os << indent << "endif(" << config_test << ")\n";
  175. }
  176. }
  177. //----------------------------------------------------------------------------
  178. void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os,
  179. Indent const& indent)
  180. {
  181. if(this->ConfigurationTypes->empty())
  182. {
  183. // In a single-configuration generator there is only one action
  184. // and it applies if the runtime-requested configuration is among
  185. // the rule's allowed configurations. The configuration built in
  186. // the tree does not matter for this decision but will be used to
  187. // generate proper target file names into the code.
  188. this->GenerateScriptActionsOnce(os, indent);
  189. }
  190. else
  191. {
  192. // In a multi-configuration generator we produce a separate rule
  193. // in a block for each configuration that is built. We restrict
  194. // the list of configurations to those to which this rule applies.
  195. bool first = true;
  196. for(std::vector<std::string>::const_iterator i =
  197. this->ConfigurationTypes->begin();
  198. i != this->ConfigurationTypes->end(); ++i)
  199. {
  200. const char* config = i->c_str();
  201. if(this->GeneratesForConfig(config))
  202. {
  203. // Generate a per-configuration block.
  204. std::string config_test = this->CreateConfigTest(config);
  205. os << indent << (first? "if(" : "elseif(") << config_test << ")\n";
  206. this->GenerateScriptForConfig(os, config, indent.Next());
  207. first = false;
  208. }
  209. }
  210. if(!first)
  211. {
  212. if(this->NeedsScriptNoConfig())
  213. {
  214. os << indent << "else()\n";
  215. this->GenerateScriptNoConfig(os, indent.Next());
  216. }
  217. os << indent << "endif()\n";
  218. }
  219. }
  220. }