1
0

cmScriptGenerator.cxx 7.1 KB

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