| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmBuildDatabase.h"
- #include <utility>
- #include <cm/memory>
- #include <cm/string_view>
- #include <cmext/string_view>
- #include <cm3p/json/reader.h>
- #include <cm3p/json/value.h>
- #include <cm3p/json/writer.h>
- #include "cmsys/FStream.hxx"
- #include "cmGeneratedFileStream.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- cmBuildDatabase::cmBuildDatabase() = default;
- cmBuildDatabase::cmBuildDatabase(cmBuildDatabase const&) = default;
- cmBuildDatabase::~cmBuildDatabase() = default;
- void cmBuildDatabase::Write(std::string const& path) const
- {
- Json::Value mcdb = Json::objectValue;
- mcdb["version"] = 1;
- mcdb["revision"] = 0;
- Json::Value& sets = mcdb["sets"] = Json::arrayValue;
- for (auto const& Set_ : this->Sets) {
- Json::Value set = Json::objectValue;
- set["name"] = Set_.Name;
- set["family-name"] = Set_.FamilyName;
- Json::Value& visible_sets = set["visible-sets"] = Json::arrayValue;
- for (auto const& VisibleSet : Set_.VisibleSets) {
- visible_sets.append(VisibleSet);
- }
- Json::Value& tus = set["translation-units"] = Json::arrayValue;
- for (auto const& TranslationUnit_ : Set_.TranslationUnits) {
- Json::Value tu = Json::objectValue;
- if (!TranslationUnit_.WorkDirectory.empty()) {
- tu["work-directory"] = TranslationUnit_.WorkDirectory;
- }
- tu["source"] = TranslationUnit_.Source;
- if (TranslationUnit_.Object) {
- tu["object"] = *TranslationUnit_.Object;
- }
- tu["private"] = TranslationUnit_.Private;
- Json::Value& reqs = tu["requires"] = Json::arrayValue;
- for (auto const& Require : TranslationUnit_.Requires) {
- reqs.append(Require);
- }
- Json::Value& provides = tu["provides"] = Json::objectValue;
- for (auto const& Provide : TranslationUnit_.Provides) {
- provides[Provide.first] = Provide.second;
- }
- Json::Value& baseline_arguments = tu["baseline-arguments"] =
- Json::arrayValue;
- for (auto const& BaselineArgument : TranslationUnit_.BaselineArguments) {
- baseline_arguments.append(BaselineArgument);
- }
- Json::Value& local_arguments = tu["local-arguments"] = Json::arrayValue;
- for (auto const& LocalArgument : TranslationUnit_.LocalArguments) {
- local_arguments.append(LocalArgument);
- }
- Json::Value& arguments = tu["arguments"] = Json::arrayValue;
- for (auto const& Argument : TranslationUnit_.Arguments) {
- arguments.append(Argument);
- }
- tus.append(tu);
- }
- sets.append(set);
- }
- cmGeneratedFileStream mcdbf(path);
- mcdbf << mcdb;
- }
- static bool ParseFilename(Json::Value const& val, std::string& result)
- {
- if (val.isString()) {
- result = val.asString();
- } else {
- return false;
- }
- return true;
- }
- #define PARSE_BLOB(val, res) \
- do { \
- if (!ParseFilename(val, res)) { \
- cmSystemTools::Error(cmStrCat("-E cmake_module_compile_db failed to ", \
- "parse ", path, ": invalid blob")); \
- return {}; \
- } \
- } while (0)
- #define PARSE_FILENAME(val, res, make_full) \
- do { \
- if (!ParseFilename(val, res)) { \
- cmSystemTools::Error(cmStrCat("-E cmake_module_compile_db failed to ", \
- "parse ", path, ": invalid filename")); \
- return {}; \
- } \
- \
- if (make_full && work_directory && !work_directory->empty() && \
- !cmSystemTools::FileIsFullPath(res)) { \
- res = cmStrCat(*work_directory, '/', res); \
- } \
- } while (0)
- std::unique_ptr<cmBuildDatabase> cmBuildDatabase::Load(std::string const& path)
- {
- Json::Value mcdb;
- {
- cmsys::ifstream mcdbf(path.c_str(), std::ios::in | std::ios::binary);
- Json::Reader reader;
- if (!reader.parse(mcdbf, mcdb, false)) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- reader.getFormattedErrorMessages()));
- return {};
- }
- }
- Json::Value const& version = mcdb["version"];
- if (version.asUInt() > 1) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": version ", version.asString()));
- return {};
- }
- auto db = cm::make_unique<cmBuildDatabase>();
- Json::Value const& sets = mcdb["sets"];
- if (sets.isArray()) {
- for (auto const& set : sets) {
- Set Set_;
- Json::Value const& name = set["name"];
- if (!name.isString()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": name is not a string"));
- return {};
- }
- Set_.Name = name.asString();
- Json::Value const& family_name = set["family-name"];
- if (!family_name.isString()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": family-name is not a string"));
- return {};
- }
- Set_.FamilyName = family_name.asString();
- Json::Value const& visible_sets = set["visible-sets"];
- if (!visible_sets.isArray()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": visible-sets is not an array"));
- return {};
- }
- for (auto const& visible_set : visible_sets) {
- if (!visible_set.isString()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": a visible-sets item is not a string"));
- return {};
- }
- Set_.VisibleSets.emplace_back(visible_set.asString());
- }
- Json::Value const& translation_units = set["translation-units"];
- if (!translation_units.isArray()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": translation-units is not an array"));
- return {};
- }
- for (auto const& translation_unit : translation_units) {
- if (!translation_unit.isObject()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": a translation-units item is not an object"));
- return {};
- }
- TranslationUnit TranslationUnit_;
- cm::optional<std::string> work_directory;
- Json::Value const& workdir = translation_unit["work-directory"];
- if (workdir.isString()) {
- PARSE_BLOB(workdir, TranslationUnit_.WorkDirectory);
- work_directory = TranslationUnit_.WorkDirectory;
- } else if (!workdir.isNull()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": work-directory is not a string"));
- return {};
- }
- Json::Value const& source = translation_unit["source"];
- PARSE_FILENAME(source, TranslationUnit_.Source, true);
- if (translation_unit.isMember("object")) {
- Json::Value const& object = translation_unit["object"];
- if (!object.isNull()) {
- TranslationUnit_.Object = "";
- PARSE_FILENAME(object, *TranslationUnit_.Object, false);
- }
- }
- if (translation_unit.isMember("private")) {
- Json::Value const& priv = translation_unit["private"];
- if (!priv.isBool()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": private is not a boolean"));
- return {};
- }
- TranslationUnit_.Private = priv.asBool();
- }
- if (translation_unit.isMember("requires")) {
- Json::Value const& reqs = translation_unit["requires"];
- if (!reqs.isArray()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": requires is not an array"));
- return {};
- }
- for (auto const& require : reqs) {
- if (!require.isString()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": a requires item is not a string"));
- return {};
- }
- TranslationUnit_.Requires.emplace_back(require.asString());
- }
- }
- if (translation_unit.isMember("provides")) {
- Json::Value const& provides = translation_unit["provides"];
- if (!provides.isObject()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": provides is not an object"));
- return {};
- }
- for (auto i = provides.begin(); i != provides.end(); ++i) {
- if (!i->isString()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": a provides value is not a string"));
- return {};
- }
- TranslationUnit_.Provides[i.key().asString()] = i->asString();
- }
- }
- if (translation_unit.isMember("baseline-arguments")) {
- Json::Value const& baseline_arguments =
- translation_unit["baseline-arguments"];
- if (!baseline_arguments.isArray()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": baseline_arguments is not an array"));
- return {};
- }
- for (auto const& baseline_argument : baseline_arguments) {
- if (baseline_argument.isString()) {
- TranslationUnit_.BaselineArguments.emplace_back(
- baseline_argument.asString());
- } else {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": a baseline argument is not a string"));
- return {};
- }
- }
- }
- if (translation_unit.isMember("local-arguments")) {
- Json::Value const& local_arguments =
- translation_unit["local-arguments"];
- if (!local_arguments.isArray()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": local_arguments is not an array"));
- return {};
- }
- for (auto const& local_argument : local_arguments) {
- if (local_argument.isString()) {
- TranslationUnit_.LocalArguments.emplace_back(
- local_argument.asString());
- } else {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": a local argument is not a string"));
- return {};
- }
- }
- }
- if (translation_unit.isMember("arguments")) {
- Json::Value const& arguments = translation_unit["arguments"];
- if (!arguments.isArray()) {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": arguments is not an array"));
- return {};
- }
- for (auto const& argument : arguments) {
- if (argument.isString()) {
- TranslationUnit_.Arguments.emplace_back(argument.asString());
- } else {
- cmSystemTools::Error(
- cmStrCat("-E cmake_module_compile_db failed to parse ", path,
- ": an argument is not a string"));
- return {};
- }
- }
- }
- Set_.TranslationUnits.emplace_back(std::move(TranslationUnit_));
- }
- db->Sets.emplace_back(std::move(Set_));
- }
- }
- return db;
- }
- cmBuildDatabase cmBuildDatabase::Merge(
- std::vector<cmBuildDatabase> const& components)
- {
- cmBuildDatabase db;
- for (auto const& component : components) {
- db.Sets.insert(db.Sets.end(), component.Sets.begin(),
- component.Sets.end());
- }
- return db;
- }
|