diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Ninja.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/Ninja.cpp b/src/Ninja.cpp new file mode 100644 index 0000000..7b3212e --- /dev/null +++ b/src/Ninja.cpp @@ -0,0 +1,121 @@ +#include "../include/ninja/Ninja.hpp" +#include <cassert> + +namespace ninja +{ + static std::string joinArgs(const std::vector<NinjaArg> &args) + { + std::string result; + for(const NinjaArg &arg : args) + { + if(!result.empty()) + result += ' '; + result += '\''; + if(arg.type == NinjaArg::Type::VARIABLE) + result += "$"; + result += arg.arg; + result += '\''; + } + return result; + } + + NinjaRule::NinjaRule(NinjaBuildFile *_buildFile, const std::string &_name, const std::string &_command) : + buildFile(_buildFile), + name(_name), + command(_command) + { + assert(buildFile); + } + + NinjaBuildFile::~NinjaBuildFile() + { + for(auto &rule : rules) + { + delete rule.second; + } + } + + void NinjaRule::build(const std::string &in, const std::string &out, const std::vector<ninja::NinjaArgValue> &additionalArgs) + { + buildFile->build(this, in, out, additionalArgs); + } + + void NinjaBuildFile::defineGlobalVariable(const std::string &name, const std::string &value) + { + auto it = globalVariables.find(name); + if(it != globalVariables.end()) + throw NinjaException(NinjaError::VARIABLE_ALREADY_DEFINED, "Global variable already defined: " + name); + globalVariables[name] = value; + } + + NinjaRule* NinjaBuildFile::createRule(const std::string &name, const std::vector<NinjaArg> &commandArgs) + { + auto it = rules.find(name); + if(it != rules.end()) + throw NinjaException(NinjaError::RULE_ALREADY_DEFINED, "Rule already defined: " + name); + + NinjaRule *rule = new NinjaRule(this, name, joinArgs(commandArgs)); + rules[name] = rule; + return rule; + } + + void NinjaBuildFile::build(const NinjaRule *rule, const std::string &in, const std::string &out, const std::vector<ninja::NinjaArgValue> &additionalArgs) + { + for(const NinjaBuild &build : builds) + { + if(build.rule == rule) + throw NinjaException(NinjaError::RULE_AREADY_BUILT, "Rule already built: " + rule->name); + } + builds.push_back({ rule, in, out, additionalArgs }); + } + + std::string NinjaBuildFile::generate() const + { + std::string result; + for(const auto &globalVar : globalVariables) + { + result += globalVar.first; + result += " = "; + result += globalVar.second; + result += '\n'; + } + + if(!globalVariables.empty()) + result += '\n'; + + for(const auto &rule : rules) + { + result += "rule "; + result += rule.first; + result += "\n command = "; + result += rule.second->command; + if(!rule.second->depFile.empty()) + { + result += "\n depfile = "; + result += rule.second->depFile; + } + result += "\n\n"; + } + + // TODO: enclose all names with quotes to escape whitespace? + for(const NinjaBuild &build : builds) + { + result += "build "; + result += build.out; + result += ": "; + result += build.rule->name; + result += ' '; + result += build.in; + for(const NinjaArgValue &additionalArg : build.additionalArgs) + { + result += "\n "; + result += additionalArg.arg.name; + result += " = "; + result += additionalArg.value; + + } + result += "\n\n"; + } + return result; + } +} |