aboutsummaryrefslogtreecommitdiff
path: root/src/Ninja.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ninja.cpp')
-rw-r--r--src/Ninja.cpp121
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;
+ }
+}