--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/objectfile.h>
+#include <msp/builder/sourcefile.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+#include "compilecommandsgenerator.h"
+#include "compilecommandsjson.h"
+
+using namespace std;
+using namespace Msp;
+
+CompileCommandsGenerator::CompileCommandsGenerator(Builder &b):
+ Tool(b, "CCJG")
+{
+ set_run_internal(_run);
+}
+
+Target *CompileCommandsGenerator::create_target(const vector<Target *> &, const string &)
+{
+ throw logic_error("Not implemented");
+}
+
+bool CompileCommandsGenerator::_run(const CompileCommandsJson &cmds)
+{
+ Builder &builder = cmds.get_package()->get_builder();
+ const SourcePackage &spkg = *cmds.get_package();
+ string work_dir = c_escape(spkg.get_source_directory().str());
+
+ IO::BufferedFile out(cmds.get_path().str(), IO::M_WRITE);
+ IO::print(out, "[");
+
+ bool first = true;
+ for(const auto &kvp: builder.get_build_graph().get_targets())
+ if(kvp.second->is_buildable() && kvp.second->get_package()==&spkg)
+ if(ObjectFile *obj = dynamic_cast<ObjectFile *>(kvp.second))
+ {
+ FS::Path src_path = obj->get_source().get_path();
+ Task *task = kvp.second->build();
+ if(!first)
+ out.put(',');
+ IO::print(out, "\n\t{\n");
+ IO::print(out, "\t\t\"file\": \"%s\"\n", src_path);
+ IO::print(out, "\t\t\"command\": \"%s\"\n", c_escape(task->get_command()));
+ IO::print(out, "\t\t\"directory\": \"%s\"\n", work_dir);
+ IO::print(out, "\t}");
+ delete task;
+ first = false;
+ }
+
+ IO::print(out, "\n]\n");
+
+ return true;
+}