From 8222bc867676a07f17b5d0d2ea9bff608151134b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 31 Oct 2021 17:44:48 +0200 Subject: [PATCH] Add support for generating compile_commands.json This file is used by some clang tools to find compile options. --- source/builtintools.cpp | 2 + source/compilecommandsgenerator.cpp | 65 +++++++++++++++++++++++++++++ source/compilecommandsgenerator.h | 31 ++++++++++++++ source/compilecommandsjson.cpp | 18 ++++++++ source/compilecommandsjson.h | 20 +++++++++ source/sourcepackage.cpp | 3 ++ 6 files changed, 139 insertions(+) create mode 100644 source/compilecommandsgenerator.cpp create mode 100644 source/compilecommandsgenerator.h create mode 100644 source/compilecommandsjson.cpp create mode 100644 source/compilecommandsjson.h diff --git a/source/builtintools.cpp b/source/builtintools.cpp index 63a6889..42ad33f 100644 --- a/source/builtintools.cpp +++ b/source/builtintools.cpp @@ -1,5 +1,6 @@ #include "builtintools.h" #include "copy.h" +#include "compilecommandsgenerator.h" #include "pkgconfiggenerator.h" #include "tar.h" #include "vcxprojectgenerator.h" @@ -10,4 +11,5 @@ BuiltinTools::BuiltinTools(Builder &builder) add_tool(new Tar(builder)); add_tool(new PkgConfigGenerator(builder)); add_tool(new VcxProjectGenerator(builder)); + add_tool(new CompileCommandsGenerator(builder)); } diff --git a/source/compilecommandsgenerator.cpp b/source/compilecommandsgenerator.cpp new file mode 100644 index 0000000..07ee15e --- /dev/null +++ b/source/compilecommandsgenerator.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#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 &, const string &) +{ + throw logic_error("Not implemented"); +} + +Task *CompileCommandsGenerator::run(const Target &target) const +{ + const CompileCommandsJson &cmds = dynamic_cast(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(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; +} diff --git a/source/compilecommandsgenerator.h b/source/compilecommandsgenerator.h new file mode 100644 index 0000000..ba74f11 --- /dev/null +++ b/source/compilecommandsgenerator.h @@ -0,0 +1,31 @@ +#ifndef COMPILECOMMANDSGENERATOR_H_ +#define COMPILECOMMANDSGENERATOR_H_ + +#include "internaltask.h" +#include "tool.h" + +class CompileCommandsJson; + +class CompileCommandsGenerator: public Tool +{ +private: + class Worker: public InternalTask::Worker + { + private: + const CompileCommandsJson ⌖ + + public: + Worker(const CompileCommandsJson &); + + private: + virtual void main(); + }; + +public: + CompileCommandsGenerator(Builder &); + + virtual Target *create_target(const std::list &, const std::string &); + virtual Task *run(const Target &) const; +}; + +#endif diff --git a/source/compilecommandsjson.cpp b/source/compilecommandsjson.cpp new file mode 100644 index 0000000..a8a1929 --- /dev/null +++ b/source/compilecommandsjson.cpp @@ -0,0 +1,18 @@ +#include "builder.h" +#include "package.h" +#include "compilecommandsjson.h" +#include "objectfile.h" + +CompileCommandsJson::CompileCommandsJson(Builder &b, const SourcePackage &p): + FileTarget(b, p, p.get_source_directory()/("compile_commands.json")) +{ + tool = &builder.get_toolchain().get_tool("CCJG"); +} + +void CompileCommandsJson::find_dependencies() +{ + 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()==package && dynamic_cast(i->second)) + i->second->prepare(); +} diff --git a/source/compilecommandsjson.h b/source/compilecommandsjson.h new file mode 100644 index 0000000..1d170c5 --- /dev/null +++ b/source/compilecommandsjson.h @@ -0,0 +1,20 @@ +#ifndef COMPILECOMMANDSJSON_H_ +#define COMPILECOMMANDSJSON_H_ + +#include "sourcepackage.h" +#include "filetarget.h" + +class CompileCommandsJson: public FileTarget +{ +private: + +public: + CompileCommandsJson(Builder &, const SourcePackage &); + + virtual const char *get_type() const { return "CompileCommandsJson"; } + +protected: + virtual void find_dependencies(); +}; + +#endif diff --git a/source/sourcepackage.cpp b/source/sourcepackage.cpp index c4061a4..1a23c47 100644 --- a/source/sourcepackage.cpp +++ b/source/sourcepackage.cpp @@ -9,6 +9,7 @@ #include "binarycomponent.h" #include "binarypackage.h" #include "builder.h" +#include "compilecommandsjson.h" #include "datapackcomponent.h" #include "file.h" #include "installcomponent.h" @@ -149,6 +150,8 @@ void SourcePackage::do_prepare() if(arch.get_system()=="windows") new VcxProjectFile(builder, *this); + + new CompileCommandsJson(builder, *this); } void SourcePackage::save_caches() -- 2.45.2