]> git.tdb.fi Git - builder.git/blobdiff - source/compilecommandsgenerator.cpp
Add support for generating compile_commands.json
[builder.git] / source / compilecommandsgenerator.cpp
diff --git a/source/compilecommandsgenerator.cpp b/source/compilecommandsgenerator.cpp
new file mode 100644 (file)
index 0000000..07ee15e
--- /dev/null
@@ -0,0 +1,65 @@
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "compilecommandsgenerator.h"
+#include "compilecommandsjson.h"
+#include "objectfile.h"
+#include "sourcefile.h"
+
+using namespace std;
+using namespace Msp;
+
+CompileCommandsGenerator::CompileCommandsGenerator(Builder &b):
+       Tool(b, "CCJG")
+{ }
+
+Target *CompileCommandsGenerator::create_target(const list<Target *> &, const string &)
+{
+       throw logic_error("Not implemented");
+}
+
+Task *CompileCommandsGenerator::run(const Target &target) const
+{
+       const CompileCommandsJson &cmds = dynamic_cast<const CompileCommandsJson &>(target);
+       Worker *worker = new Worker(cmds);
+       return new InternalTask(worker);
+}
+
+
+CompileCommandsGenerator::Worker::Worker(const CompileCommandsJson &t):
+       target(t)
+{ }
+
+void CompileCommandsGenerator::Worker::main()
+{
+       Builder &builder = target.get_package()->get_builder();
+       const SourcePackage &spkg = *target.get_package();
+       string work_dir = c_escape(spkg.get_source_directory().str());
+
+       IO::BufferedFile out(target.get_path().str(), IO::M_WRITE);
+       IO::print(out, "[");
+
+       bool first = true;
+       const BuildGraph::TargetMap &targets = builder.get_build_graph().get_targets();
+       for(BuildGraph::TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
+               if(i->second->is_buildable() && i->second->get_package()==&spkg)
+                       if(ObjectFile *obj = dynamic_cast<ObjectFile *>(i->second))
+                       {
+                               FS::Path src_path = obj->get_source().get_path();
+                               Task *task = i->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");
+
+       status = Task::SUCCESS;
+}