diff options
author | Brad King <brad.king@kitware.com> | 2009-03-16 10:39:56 -0400 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2009-03-16 10:39:56 -0400 |
commit | e67f5138b80b3b04844f3f5c0a3c69796266f9e6 (patch) | |
tree | 918dfffdd191602494e888ce72e3afaf797fbe9f /Source/cmScriptGenerator.cxx | |
parent | e30835345abd1d05891c383506cadbc08ec51ccf (diff) | |
download | cmake-e67f5138b80b3b04844f3f5c0a3c69796266f9e6.tar.gz |
ENH: Refactor cmInstallGenerator for re-use
A new cmScriptGenerator base class factors out the non-install-specific
part of cmInstallGenerator. This will be useful for other generators
that want per-configuration functionality.
Diffstat (limited to 'Source/cmScriptGenerator.cxx')
-rw-r--r-- | Source/cmScriptGenerator.cxx | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx new file mode 100644 index 0000000000..c3a521a4a2 --- /dev/null +++ b/Source/cmScriptGenerator.cxx @@ -0,0 +1,232 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "cmScriptGenerator.h" + +#include "cmSystemTools.h" + +//---------------------------------------------------------------------------- +cmScriptGenerator +::cmScriptGenerator(const char* config_var, + std::vector<std::string> const& configurations): + RuntimeConfigVariable(config_var), + Configurations(configurations), + ConfigurationName(0), + ConfigurationTypes(0), + ActionsPerConfig(false) +{ +} + +//---------------------------------------------------------------------------- +cmScriptGenerator +::~cmScriptGenerator() +{ +} + +//---------------------------------------------------------------------------- +void +cmScriptGenerator +::Generate(std::ostream& os, const char* config, + std::vector<std::string> const& configurationTypes) +{ + this->ConfigurationName = config; + this->ConfigurationTypes = &configurationTypes; + this->GenerateScript(os); + this->ConfigurationName = 0; + this->ConfigurationTypes = 0; +} + +//---------------------------------------------------------------------------- +static void cmScriptGeneratorEncodeConfig(const char* config, + std::string& result) +{ + for(const char* c = config; *c; ++c) + { + if(*c >= 'a' && *c <= 'z') + { + result += "["; + result += *c + ('A' - 'a'); + result += *c; + result += "]"; + } + else if(*c >= 'A' && *c <= 'Z') + { + result += "["; + result += *c; + result += *c + ('a' - 'A'); + result += "]"; + } + else + { + result += *c; + } + } +} + +//---------------------------------------------------------------------------- +std::string +cmScriptGenerator::CreateConfigTest(const char* config) +{ + std::string result = "\"${"; + result += this->RuntimeConfigVariable; + result += "}\" MATCHES \"^("; + if(config && *config) + { + cmScriptGeneratorEncodeConfig(config, result); + } + result += ")$\""; + return result; +} + +//---------------------------------------------------------------------------- +std::string +cmScriptGenerator::CreateConfigTest(std::vector<std::string> const& configs) +{ + std::string result = "\"${"; + result += this->RuntimeConfigVariable; + result += "}\" MATCHES \"^("; + const char* sep = ""; + for(std::vector<std::string>::const_iterator ci = configs.begin(); + ci != configs.end(); ++ci) + { + result += sep; + sep = "|"; + cmScriptGeneratorEncodeConfig(ci->c_str(), result); + } + result += ")$\""; + return result; +} + +//---------------------------------------------------------------------------- +void cmScriptGenerator::GenerateScript(std::ostream& os) +{ + // Track indentation. + Indent indent; + + // Generate the script possibly with per-configuration code. + this->GenerateScriptConfigs(os, indent); +} + +//---------------------------------------------------------------------------- +void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, + Indent const& indent) +{ + if(this->ActionsPerConfig) + { + this->GenerateScriptActionsPerConfig(os, indent); + } + else + { + this->GenerateScriptActionsOnce(os, indent); + } +} + +//---------------------------------------------------------------------------- +void cmScriptGenerator::GenerateScriptActions(std::ostream& os, + Indent const& indent) +{ + if(this->ActionsPerConfig) + { + // This is reached for single-configuration build generators in a + // per-config script generator. + this->GenerateScriptForConfig(os, this->ConfigurationName, indent); + } +} + +//---------------------------------------------------------------------------- +void cmScriptGenerator::GenerateScriptForConfig(std::ostream&, const char*, + Indent const&) +{ + // No actions for this generator. +} + +//---------------------------------------------------------------------------- +bool cmScriptGenerator::GeneratesForConfig(const char* config) +{ + // If this is not a configuration-specific rule then we install. + if(this->Configurations.empty()) + { + return true; + } + + // This is a configuration-specific rule. Check if the config + // matches this rule. + std::string config_upper = cmSystemTools::UpperCase(config?config:""); + for(std::vector<std::string>::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) + { + if(cmSystemTools::UpperCase(*i) == config_upper) + { + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os, + Indent const& indent) +{ + if(this->Configurations.empty()) + { + // This rule is for all configurations. + this->GenerateScriptActions(os, indent); + } + else + { + // Generate a per-configuration block. + std::string config_test = this->CreateConfigTest(this->Configurations); + os << indent << "IF(" << config_test << ")\n"; + this->GenerateScriptActions(os, indent.Next()); + os << indent << "ENDIF(" << config_test << ")\n"; + } +} + +//---------------------------------------------------------------------------- +void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os, + Indent const& indent) +{ + if(this->ConfigurationTypes->empty()) + { + // In a single-configuration generator there is only one action + // and it applies if the runtime-requested configuration is among + // the rule's allowed configurations. The configuration built in + // the tree does not matter for this decision but will be used to + // generate proper target file names into the code. + this->GenerateScriptActionsOnce(os, indent); + } + else + { + // In a multi-configuration generator we produce a separate rule + // in a block for each configuration that is built. We restrict + // the list of configurations to those to which this rule applies. + for(std::vector<std::string>::const_iterator i = + this->ConfigurationTypes->begin(); + i != this->ConfigurationTypes->end(); ++i) + { + const char* config = i->c_str(); + if(this->GeneratesForConfig(config)) + { + // Generate a per-configuration block. + std::string config_test = this->CreateConfigTest(config); + os << indent << "IF(" << config_test << ")\n"; + this->GenerateScriptForConfig(os, config, indent.Next()); + os << indent << "ENDIF(" << config_test << ")\n"; + } + } + } +} |