From 69528ba012ac2238f63464fb84e7623f3088603a Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 19 Jun 2021 18:00:48 +0200 Subject: Add compilation database generation. --- TODO | 3 -- libcppbuild.cc | 37 +++++++++++++++++++++ task.h | 2 ++ task_cc.cc | 103 +++++++++++++++++++++++++++++++++++---------------------- task_cc.h | 3 ++ 5 files changed, 106 insertions(+), 42 deletions(-) diff --git a/TODO b/TODO index 34fe79a..2715747 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,6 @@ Glob convenience methods std::string glob = getFilesInDir(...); -Generate compilation database -https://clang.llvm.org/docs/JSONCompilationDatabase.html - Add support for pre/post build hooks with conditions Add shell script targets to be able to generate soucre files that can diff --git a/libcppbuild.cc b/libcppbuild.cc index 9fcc4d4..8d5231f 100644 --- a/libcppbuild.cc +++ b/libcppbuild.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -179,6 +180,9 @@ int main(int argc, char* argv[]) std::max(1u, std::thread::hardware_concurrency() * 2 - 1); settings.verbose = 0; + bool write_compilation_database{false}; + std::string compilation_database; + dg::Options opt; opt.add("jobs", required_argument, 'j', @@ -210,6 +214,14 @@ int main(int argc, char* argv[]) return 0; }); + opt.add("database", required_argument, 'd', + "Write compilation database json file.", + [&]() { + write_compilation_database = true; + compilation_database = optarg; + return 0; + }); + opt.add("help", no_argument, 'h', "Print this help text.", [&]() { @@ -246,6 +258,31 @@ int main(int argc, char* argv[]) } } + if(write_compilation_database) + { + std::ofstream istr(compilation_database); + istr << "["; + bool first{true}; + for(auto task : tasks) + { + auto s = task->toJSON(); + if(!s.empty()) + { + if(!first) + { + istr << ",\n"; + } + else + { + istr << "\n"; + } + first = false; + istr << s; + } + } + istr << "\n]\n"; + } + for(auto task : tasks) { if(task->registerDepTasks(tasks)) diff --git a/task.h b/task.h index f7a4758..9c2d622 100644 --- a/task.h +++ b/task.h @@ -31,6 +31,8 @@ public: virtual std::vector depends() const = 0; virtual std::string target() const = 0; + virtual std::string toJSON() const { return {}; }; + protected: std::atomic task_state{State::Unknown}; virtual int runInner() { return 0; }; diff --git a/task_cc.cc b/task_cc.cc index b5cc768..6c7e3b7 100644 --- a/task_cc.cc +++ b/task_cc.cc @@ -175,44 +175,7 @@ int TaskCC::runInner() return 1; } - std::string comp = compiler(); - auto compiler_flags = flags(); - - std::vector args; - args.push_back("-MMD"); - - if(std::filesystem::path(config.target).extension() == ".so") - { - // Add -fPIC arg to all contained object files - args.push_back("-fPIC"); - } - - args.push_back("-c"); - args.push_back(std::string(sourceFile)); - args.push_back("-o"); - args.push_back(std::string(targetFile)); - - for(const auto& flag : compiler_flags) - { - // Is arg an added include path? - if(flag.substr(0, 2) == "-I") - { - std::string include_path = flag.substr(2); - include_path.erase(0, include_path.find_first_not_of(' ')); - std::filesystem::path path(include_path); - - // Is it relative? - if(path.is_relative()) - { - path = (sourceDir / path).lexically_normal(); - std::string new_include_path = "-I" + path.string(); - args.push_back(new_include_path); - continue; - } - } - - args.push_back(flag); - } + auto args = getCompilerArgs(); { // Write flags to file. std::ofstream flagsStream(flagsFile); @@ -225,7 +188,8 @@ int TaskCC::runInner() sourceFile.lexically_normal().string() << " => " << targetFile.lexically_normal().string() << "\n"; } - return execute(comp, args, settings.verbose > 0); + + return execute(compiler(), args, settings.verbose > 0); } int TaskCC::clean() @@ -261,6 +225,24 @@ std::string TaskCC::target() const return targetFile; } +std::string TaskCC::toJSON() const +{ + std::string json; + json += "\t{\n"; + json += "\t\t\"directory\": \"" + sourceDir.string() + "\",\n"; + json += "\t\t\"file\": \"" + sourceFile.lexically_normal().string() + "\",\n"; + json += "\t\t\"output\": \"" + targetFile.string() + "\",\n"; + json += "\t\t\"arguments\": [ \"" + compiler() + "\""; + auto args = getCompilerArgs(); + for(const auto& arg : args) + { + json += ", \"" + arg + "\""; + } + json += " ]\n"; + json += "\t}"; + return json; +} + std::vector TaskCC::flags() const { if(std::string(sourceFile.extension()) == ".c") @@ -292,3 +274,46 @@ std::string TaskCC::compiler() const } return "/usr/bin/g++"; } + +std::vector TaskCC::getCompilerArgs() const +{ + auto compiler_flags = flags(); + + std::vector args; + args.push_back("-MMD"); + + if(std::filesystem::path(config.target).extension() == ".so") + { + // Add -fPIC arg to all contained object files + args.push_back("-fPIC"); + } + + args.push_back("-c"); + args.push_back(std::string(sourceFile)); + args.push_back("-o"); + args.push_back(std::string(targetFile)); + + for(const auto& flag : compiler_flags) + { + // Is arg an added include path? + if(flag.substr(0, 2) == "-I") + { + std::string include_path = flag.substr(2); + include_path.erase(0, include_path.find_first_not_of(' ')); + std::filesystem::path path(include_path); + + // Is it relative? + if(path.is_relative()) + { + path = (sourceDir / path).lexically_normal(); + std::string new_include_path = "-I" + path.string(); + args.push_back(new_include_path); + continue; + } + } + + args.push_back(flag); + } + + return args; +} diff --git a/task_cc.h b/task_cc.h index 538188f..48910c3 100644 --- a/task_cc.h +++ b/task_cc.h @@ -28,10 +28,13 @@ public: std::string target() const override; + std::string toJSON() const override; + private: std::vector flags() const; std::string flagsString() const; std::string compiler() const; + std::vector getCompilerArgs() const; std::filesystem::path sourceFile; std::filesystem::path targetFile; -- cgit v1.2.3