From d349f3e01c89d0d6d2fca9e8dced1612e5f8d782 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Fri, 5 May 2023 20:28:49 +0200 Subject: [PATCH 1/6] Updated remove_compile_flags option --- src/common/compilation_database.cc | 104 ++++++++++++++++++ src/common/compilation_database.h | 78 +++++++++++++ src/common/generators/generators.cc | 23 +--- src/common/generators/generators.h | 16 +-- src/config/config.h | 2 + src/config/yaml_decoders.cc | 1 + src/config/yaml_emitters.cc | 1 + src/main.cc | 54 +++++---- tests/CMakeLists.txt | 5 +- tests/test_cases.cc | 37 +++---- tests/test_cases.h | 4 +- tests/test_compilation_database.cc | 86 +++++++++++++++ .../test_compilation_database_data/config.yml | 7 ++ .../config_bad.yml | 5 + 14 files changed, 343 insertions(+), 80 deletions(-) create mode 100644 src/common/compilation_database.cc create mode 100644 src/common/compilation_database.h create mode 100644 tests/test_compilation_database.cc create mode 100644 tests/test_compilation_database_data/config.yml create mode 100644 tests/test_compilation_database_data/config_bad.yml diff --git a/src/common/compilation_database.cc b/src/common/compilation_database.cc new file mode 100644 index 00000000..83772bae --- /dev/null +++ b/src/common/compilation_database.cc @@ -0,0 +1,104 @@ +/** + * src/common/compilation_database.cc + * + * Copyright (c) 2021-2023 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "compilation_database.h" + +namespace clanguml::common { + +std::unique_ptr +compilation_database::auto_detect_from_directory( + const clanguml::config::config &cfg) +{ + std::string error_message; + auto res = clang::tooling::CompilationDatabase::autoDetectFromDirectory( + cfg.compilation_database_dir(), error_message); + + if (!error_message.empty()) + throw compilation_database_error(error_message); + + return std::make_unique(std::move(res), cfg); +} + +compilation_database::compilation_database( + std::unique_ptr base, + const clanguml::config::config &cfg) + : base_{std::move(base)} + , config_{cfg} +{ +} + +const clanguml::config::config &compilation_database::config() const +{ + return config_; +} + +const clang::tooling::CompilationDatabase &compilation_database::base() const +{ + return *base_; +} + +std::vector compilation_database::getAllFiles() const +{ + return base().getAllFiles(); +} + +std::vector +compilation_database::getCompileCommands(clang::StringRef FilePath) const +{ + auto commands = base().getCompileCommands(FilePath); + + adjust_compilation_database(commands); + + return commands; +} + +std::vector +compilation_database::getAllCompileCommands() const +{ + auto commands = base().getAllCompileCommands(); + + adjust_compilation_database(commands); + + return commands; +} + +void compilation_database::adjust_compilation_database( + std::vector &commands) const +{ + if (config().add_compile_flags && !config().add_compile_flags().empty()) { + for (auto &compile_command : commands) { + compile_command.CommandLine.insert( + // Add flags after argv[0] + compile_command.CommandLine.begin() + 1, + config().add_compile_flags().begin(), + config().add_compile_flags().end()); + } + } + + if (config().remove_compile_flags && + !config().remove_compile_flags().empty()) { + for (auto &compile_command : commands) { + for (const auto &flag : config().remove_compile_flags()) { + util::erase_if(compile_command.CommandLine, + [&flag](const auto &arg) { return flag == arg; }); + } + } + } +} + +} // namespace clanguml::common \ No newline at end of file diff --git a/src/common/compilation_database.h b/src/common/compilation_database.h new file mode 100644 index 00000000..7a98f27c --- /dev/null +++ b/src/common/compilation_database.h @@ -0,0 +1,78 @@ +/** + * src/common/compilation_database.h + * + * Copyright (c) 2021-2023 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "common/model/enums.h" +#include "common/model/namespace.h" +#include "common/model/template_parameter.h" +#include "config/config.h" +#include "types.h" +#include "util/util.h" + +#include +#include +#include + +#include +#include +#include + +namespace clanguml::common { + +class compilation_database_error : public std::runtime_error { + using std::runtime_error::runtime_error; +}; + +class compilation_database : public clang::tooling::CompilationDatabase { +public: + compilation_database( + std::unique_ptr base, + const clanguml::config::config &cfg); + + ~compilation_database() override = default; + + static std::unique_ptr auto_detect_from_directory( + const clanguml::config::config &cfg); + + std::vector getCompileCommands( + clang::StringRef FilePath) const override; + + std::vector getAllFiles() const override; + + std::vector + getAllCompileCommands() const override; + + const clanguml::config::config &config() const; + + const clang::tooling::CompilationDatabase &base() const; + +private: + void adjust_compilation_database( + std::vector &commands) const; + + // Actual instance of the compilation database is stored in here + // The inheritance is just to keep the interface + std::unique_ptr base_; + + // Reference to the clang-uml config + const clanguml::config::config &config_; +}; + +using compilation_database_ptr = std::unique_ptr; + +} // namespace clanguml::common \ No newline at end of file diff --git a/src/common/generators/generators.cc b/src/common/generators/generators.cc index 1a650717..45419224 100644 --- a/src/common/generators/generators.cc +++ b/src/common/generators/generators.cc @@ -79,7 +79,7 @@ void generate_diagram_select_generator(const std::string &od, template void generate_diagram_impl(const std::string &od, const std::string &name, std::shared_ptr diagram, - const clang::tooling::CompilationDatabase &db, + const common::compilation_database &db, const std::vector &translation_units, const std::vector &generators, bool verbose) @@ -107,7 +107,7 @@ void generate_diagram_impl(const std::string &od, const std::string &name, void generate_diagram(const std::string &od, const std::string &name, std::shared_ptr diagram, - const clang::tooling::CompilationDatabase &db, + const common::compilation_database &db, const std::vector &translation_units, const std::vector &generators, bool verbose) @@ -139,9 +139,9 @@ void generate_diagram(const std::string &od, const std::string &name, } void generate_diagrams(const std::vector &diagram_names, - clanguml::config::config &config, const std::string &od, - const std::unique_ptr &db, - const int verbose, const unsigned int thread_count, + config::config &config, const std::string &od, + const common::compilation_database_ptr &db, const int verbose, + const unsigned int thread_count, const std::vector &generators, const std::map> &translation_units_map) @@ -184,17 +184,4 @@ void generate_diagrams(const std::vector &diagram_names, } } -void adjust_compilation_database(const clanguml::config::config &config, - clang::tooling::CompilationDatabase &db) -{ - if (config.add_compile_flags && !config.add_compile_flags().empty()) { - for (auto &compile_command : db.getAllCompileCommands()) { - compile_command.CommandLine.insert( - compile_command.CommandLine.begin() + 1, - config.add_compile_flags().begin(), - config.add_compile_flags().end()); - } - } -} - } // namespace clanguml::common::generators \ No newline at end of file diff --git a/src/common/generators/generators.h b/src/common/generators/generators.h index e85d2f8f..557319d9 100644 --- a/src/common/generators/generators.h +++ b/src/common/generators/generators.h @@ -20,6 +20,7 @@ #include "class_diagram/generators/json/class_diagram_generator.h" #include "class_diagram/generators/plantuml/class_diagram_generator.h" #include "cli/cli_handler.h" +#include "common/compilation_database.h" #include "common/generators/generators.h" #include "common/model/diagram_filter.h" #include "config/config.h" @@ -33,7 +34,6 @@ #include "version.h" #include -#include #include #include @@ -139,9 +139,6 @@ void find_translation_units_for_diagrams( const std::vector &compilation_database_files, std::map> &translation_units_map); -void adjust_compilation_database(const clanguml::config::config &config, - clang::tooling::CompilationDatabase &db); - template class diagram_ast_consumer : public clang::ASTConsumer { @@ -229,10 +226,9 @@ private: template -std::unique_ptr generate( - const clang::tooling::CompilationDatabase &db, const std::string &name, - DiagramConfig &config, const std::vector &translation_units, - bool /*verbose*/ = false) +std::unique_ptr generate(const common::compilation_database &db, + const std::string &name, DiagramConfig &config, + const std::vector &translation_units, bool /*verbose*/ = false) { LOG_INFO("Generating diagram {}", name); @@ -262,14 +258,14 @@ std::unique_ptr generate( void generate_diagram(const std::string &od, const std::string &name, std::shared_ptr diagram, - const clang::tooling::CompilationDatabase &db, + const common::compilation_database &db, const std::vector &translation_units, const std::vector &generators, bool verbose); void generate_diagrams(const std::vector &diagram_names, clanguml::config::config &config, const std::string &od, - const std::unique_ptr &db, int verbose, + const common::compilation_database_ptr &db, int verbose, unsigned int thread_count, const std::vector &generators, const std::map> diff --git a/src/config/config.h b/src/config/config.h index dcb8427a..807d80ef 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -226,6 +226,8 @@ struct config : public inheritable_diagram_options { option compilation_database_dir{ "compilation_database_dir", "."}; option> add_compile_flags{"add_compile_flags"}; + option> remove_compile_flags{ + "remove_compile_flags"}; option output_directory{"output_directory"}; option> diagram_templates{ diff --git a/src/config/yaml_decoders.cc b/src/config/yaml_decoders.cc index 2cca89eb..5c0479ee 100644 --- a/src/config/yaml_decoders.cc +++ b/src/config/yaml_decoders.cc @@ -588,6 +588,7 @@ template <> struct convert { get_option(node, rhs.output_directory); get_option(node, rhs.compilation_database_dir); get_option(node, rhs.add_compile_flags); + get_option(node, rhs.remove_compile_flags); get_option(node, rhs.include_relations_also_as_members); get_option(node, rhs.puml); get_option(node, rhs.generate_method_arguments); diff --git a/src/config/yaml_emitters.cc b/src/config/yaml_emitters.cc index 66a0b38e..a69589d0 100644 --- a/src/config/yaml_emitters.cc +++ b/src/config/yaml_emitters.cc @@ -188,6 +188,7 @@ YAML::Emitter &operator<<(YAML::Emitter &out, const config &c) out << c.compilation_database_dir; out << c.output_directory; out << c.add_compile_flags; + out << c.remove_compile_flags; out << dynamic_cast(c); diff --git a/src/main.cc b/src/main.cc index e6acb353..825911a7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -17,6 +17,7 @@ */ #include "cli/cli_handler.h" +#include "common/compilation_database.h" #include "common/generators/generators.h" #include "include_diagram/generators/plantuml/include_diagram_generator.h" #include "util/util.h" @@ -53,38 +54,33 @@ int main(int argc, const char *argv[]) if (res == cli::cli_flow_t::kError) return 1; - std::string err{}; - auto db = clang::tooling::CompilationDatabase::autoDetectFromDirectory( - cli.config.compilation_database_dir(), err); + try { + const auto db = + clanguml::common::compilation_database::auto_detect_from_directory( + cli.config); - if (!err.empty()) { - LOG_ERROR("Failed to load compilation database from {}", - cli.config.compilation_database_dir()); + const auto compilation_database_files = db->getAllFiles(); + + std::map /*translation units*/> + translation_units_map; + + // We have to generate the translation units list for each diagram + // before scheduling tasks, because std::filesystem::current_path cannot + // be trusted with multiple threads + clanguml::common::generators::find_translation_units_for_diagrams( + cli.diagram_names, cli.config, compilation_database_files, + translation_units_map); + + clanguml::common::generators::generate_diagrams(cli.diagram_names, + cli.config, cli.effective_output_directory, db, cli.verbose, + cli.thread_count, cli.generators, translation_units_map); + } + catch (clanguml::common::compilation_database_error &e) { + LOG_ERROR("Failed to load compilation database from {} due to: {}", + cli.config.compilation_database_dir(), e.what()); return 1; } - const auto compilation_database_files = db->getAllFiles(); - - std::map /*translation units*/> - translation_units_map; - - // We have to generate the translation units list for each diagram before - // scheduling tasks, because std::filesystem::current_path cannot be trusted - // with multiple threads - clanguml::common::generators::find_translation_units_for_diagrams( - cli.diagram_names, cli.config, compilation_database_files, - translation_units_map); - - // - // Inject any additional compilation flags from the config to the - // compilation database - // - clanguml::common::generators::adjust_compilation_database(cli.config, *db); - - clanguml::common::generators::generate_diagrams(cli.diagram_names, - cli.config, cli.effective_output_directory, db, cli.verbose, - cli.thread_count, cli.generators, translation_units_map); - return 0; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4c17b96e..bd41026d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,9 @@ file(GLOB_RECURSE TEST_CASE_SOURCES t*/*.cc t*/*.c t*/src/*.c) file(GLOB_RECURSE TEST_CASE_CONFIGS t*/.clang-uml) -file(GLOB_RECURSE TEST_CONFIG_YMLS test_config_data/*.yml) +file(GLOB_RECURSE TEST_CONFIG_YMLS test_config_data/*.yml + test_compilation_database_data/*.yml + test_compilation_database_data/*.json) set(TEST_CASES_REQUIRING_CXX20 t00056 t00058 t00059) @@ -36,6 +38,7 @@ set(TEST_CASES test_util test_model test_cases + test_compilation_database test_decorator_parser test_config test_cli_handler diff --git a/tests/test_cases.cc b/tests/test_cases.cc index 980272a7..ed337623 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -19,6 +19,7 @@ #include "test_cases.h" #include "cli/cli_handler.h" +#include "common/compilation_database.h" #include "common/generators/generators.h" #include @@ -33,32 +34,28 @@ void inject_diagram_options(std::shared_ptr diagram) diagram->generate_links.set(links_config); } -std::pair> +std::pair load_config(const std::string &test_name) { - auto config = clanguml::config::load(test_name + "/.clang-uml", true); + std::pair + res; + + res.first = clanguml::config::load(test_name + "/.clang-uml", true); LOG_DBG("Loading compilation database from {}", - config.compilation_database_dir()); + res.first.compilation_database_dir()); - std::string err{}; - auto compilation_database = - clang::tooling::CompilationDatabase::autoDetectFromDirectory( - config.compilation_database_dir(), err); + res.second = + clanguml::common::compilation_database::auto_detect_from_directory( + res.first); - if (!err.empty()) { - LOG_ERROR("Failed to load compilation database from {}", - config.compilation_database_dir()); - throw std::runtime_error{err}; - } - - return std::make_pair(std::move(config), std::move(compilation_database)); + return res; } namespace detail { template -auto generate_diagram_impl(clang::tooling::CompilationDatabase &db, +auto generate_diagram_impl(clanguml::common::compilation_database &db, std::shared_ptr diagram) { using diagram_config = DiagramConfig; @@ -117,7 +114,7 @@ auto generate_diagram_json( } std::unique_ptr generate_class_diagram( - clang::tooling::CompilationDatabase &db, + clanguml::common::compilation_database &db, std::shared_ptr diagram) { return detail::generate_diagram_impl( @@ -125,7 +122,7 @@ std::unique_ptr generate_class_diagram( } std::unique_ptr -generate_sequence_diagram(clang::tooling::CompilationDatabase &db, +generate_sequence_diagram(clanguml::common::compilation_database &db, std::shared_ptr diagram) { return detail::generate_diagram_impl( @@ -133,7 +130,7 @@ generate_sequence_diagram(clang::tooling::CompilationDatabase &db, } std::unique_ptr -generate_package_diagram(clang::tooling::CompilationDatabase &db, +generate_package_diagram(clanguml::common::compilation_database &db, std::shared_ptr diagram) { return detail::generate_diagram_impl( @@ -141,7 +138,7 @@ generate_package_diagram(clang::tooling::CompilationDatabase &db, } std::unique_ptr -generate_include_diagram(clang::tooling::CompilationDatabase &db, +generate_include_diagram(clanguml::common::compilation_database &db, std::shared_ptr diagram) { return detail::generate_diagram_impl( diff --git a/tests/test_cases.h b/tests/test_cases.h index 93073628..4ebd5bdb 100644 --- a/tests/test_cases.h +++ b/tests/test_cases.h @@ -23,6 +23,7 @@ #include "class_diagram/model/diagram.h" #include "class_diagram/visitor/translation_unit_visitor.h" #include "common/clang_utils.h" +#include "common/compilation_database.h" #include "config/config.h" #include "include_diagram/generators/plantuml/include_diagram_generator.h" #include "include_diagram/visitor/translation_unit_visitor.h" @@ -54,8 +55,7 @@ using Catch::Matchers::VectorContains; using namespace clanguml::util; -std::pair> +std::pair load_config(const std::string &test_name); std::string generate_sequence_puml( diff --git a/tests/test_compilation_database.cc b/tests/test_compilation_database.cc new file mode 100644 index 00000000..b1ed87a9 --- /dev/null +++ b/tests/test_compilation_database.cc @@ -0,0 +1,86 @@ +/** + * tests/test_compilation_database.cc + * + * Copyright (c) 2021-2023 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define CATCH_CONFIG_MAIN + +#include "common/compilation_database.h" + +#include "util/util.h" + +#include "catch.h" +#include +#include + +std::shared_ptr make_sstream_logger(std::ostream &ostr) +{ + auto oss_sink = std::make_shared(ostr); + return std::make_shared( + "clanguml-logger", std::move(oss_sink)); +} + +TEST_CASE("Test compilation_database should work", "[unit-test]") +{ + using clanguml::common::compilation_database; + using clanguml::common::compilation_database_ptr; + using clanguml::common::model::access_t; + using clanguml::common::model::relationship_t; + using clanguml::util::contains; + + auto cfg = + clanguml::config::load("./test_compilation_database_data/config.yml"); + + try { + const auto db = + clanguml::common::compilation_database::auto_detect_from_directory( + cfg); + + auto all_files = db->getAllFiles(); + + REQUIRE(all_files.size() == 3); + REQUIRE(all_files.at(0) == + "src/class_diagram/generators/json/class_diagram_generator.cc"); + REQUIRE(all_files.at(1) == + "src/class_diagram/generators/plantuml/" + "class_diagram_generator.cc"); + REQUIRE(all_files.at(2) == "src/class_diagram/model/class.cc"); + + auto ccs = db->getAllCompileCommands(); + + REQUIRE(contains(ccs.at(0).CommandLine, "-Wno-error")); + REQUIRE(contains(ccs.at(0).CommandLine, "-Wno-unknown-warning-option")); + REQUIRE( + !contains(ccs.at(0).CommandLine, "-Wno-deprecated-declarations")); + } + catch (clanguml::common::compilation_database_error &e) { + REQUIRE(false); + } +} + +TEST_CASE("Test compilation_database should throw", "[unit-test]") +{ + using clanguml::common::compilation_database; + using clanguml::common::compilation_database_error; + using clanguml::common::compilation_database_ptr; + using clanguml::util::contains; + + auto cfg = clanguml::config::load( + "./test_compilation_database_data/config_bad.yml"); + + REQUIRE_THROWS_AS( + clanguml::common::compilation_database::auto_detect_from_directory(cfg), + compilation_database_error); +} \ No newline at end of file diff --git a/tests/test_compilation_database_data/config.yml b/tests/test_compilation_database_data/config.yml new file mode 100644 index 00000000..22bef806 --- /dev/null +++ b/tests/test_compilation_database_data/config.yml @@ -0,0 +1,7 @@ +compilation_database_dir: . +output_directory: . +add_compile_flags: [-Wno-unknown-warning-option, -Wno-error] +remove_compile_flags: [-Wno-deprecated-declarations] +diagrams: + class_main: + type: class \ No newline at end of file diff --git a/tests/test_compilation_database_data/config_bad.yml b/tests/test_compilation_database_data/config_bad.yml new file mode 100644 index 00000000..d842062a --- /dev/null +++ b/tests/test_compilation_database_data/config_bad.yml @@ -0,0 +1,5 @@ +compilation_database_dir: /tmp/no_such_directory___ +output_directory: . +diagrams: + class_main: + type: class \ No newline at end of file From 5e78377cf3f794d951411e4ce7e74305138e7adb Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Fri, 5 May 2023 22:40:31 +0200 Subject: [PATCH 2/6] Added add_compile_flag and remove_compile_flag options to cli_handler (#130) --- CHANGELOG.md | 1 + src/cli/cli_handler.cc | 20 ++++++++++++++++++++ src/cli/cli_handler.h | 2 ++ tests/test_cli_handler.cc | 27 +++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1534e4a0..f0ec5981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG + * Fixed add_compile_flags and added remove_compile_flags config options (#130) * Added rendering of template specialization fields and methods (#128) * Improved template specialization/instantiation matching based on deduced context diff --git a/src/cli/cli_handler.cc b/src/cli/cli_handler.cc index b6c10240..08220881 100644 --- a/src/cli/cli_handler.cc +++ b/src/cli/cli_handler.cc @@ -83,6 +83,11 @@ cli_flow_t cli_handler::parse(int argc, const char **argv) app.add_flag("-l,--list-diagrams", list_diagrams, "Print list of diagrams defined in the config file"); app.add_flag("--init", initialize, "Initialize example config file"); + app.add_option("--add-compile-flag", add_compile_flag, + "Add a compilation flag to each entry in the compilation database"); + app.add_option("--remove-compile-flag", remove_compile_flag, + "Remove a compilation flag from each entry in the compilation " + "database"); app.add_option( "--add-class-diagram", add_class_diagram, "Add class diagram config"); app.add_option("--add-sequence-diagram", add_sequence_diagram, @@ -269,6 +274,21 @@ cli_flow_t cli_handler::handle_post_config_options() if (!ensure_output_directory_exists(effective_output_directory)) return cli_flow_t::kError; + // + // Append add_compile_flags and remove_compile_flags to the config + // + if (add_compile_flag) { + std::copy(add_compile_flag->begin(), add_compile_flag->end(), + std::back_inserter(config.add_compile_flags.value)); + config.add_compile_flags.has_value = true; + } + + if (remove_compile_flag) { + std::copy(remove_compile_flag->begin(), remove_compile_flag->end(), + std::back_inserter(config.remove_compile_flags.value)); + config.remove_compile_flags.has_value = true; + } + return cli_flow_t::kContinue; } diff --git a/src/cli/cli_handler.h b/src/cli/cli_handler.h index 575a113c..a2dce4d1 100644 --- a/src/cli/cli_handler.h +++ b/src/cli/cli_handler.h @@ -121,6 +121,8 @@ public: bool list_diagrams{false}; bool quiet{false}; bool initialize{false}; + std::optional> add_compile_flag; + std::optional> remove_compile_flag; std::optional add_class_diagram; std::optional add_sequence_diagram; std::optional add_package_diagram; diff --git a/tests/test_cli_handler.cc b/tests/test_cli_handler.cc index 799b1d38..b64947a0 100644 --- a/tests/test_cli_handler.cc +++ b/tests/test_cli_handler.cc @@ -156,4 +156,31 @@ TEST_CASE("Test cli handler print_diagram_template", "[unit-test]") namespaces: [{{ namespace_name }}] )"); +} + +TEST_CASE( + "Test cli handler add_compile_flag and remove_compile_flag", "[unit-test]") +{ + using clanguml::cli::cli_flow_t; + using clanguml::cli::cli_handler; + using clanguml::util::contains; + + std::vector argv{"clang-uml", "--config", + "./test_config_data/simple.yml", "--add-compile-flag", "-Wno-error", + "--add-compile-flag", "-Wno-warning", "--remove-compile-flag", + "-I/usr/include"}; + + std::ostringstream ostr; + cli_handler cli{ostr, make_sstream_logger(ostr)}; + + auto res = cli.handle_options(argv.size(), argv.data()); + + REQUIRE(res == cli_flow_t::kContinue); + + REQUIRE(cli.config.add_compile_flags.has_value); + REQUIRE(cli.config.remove_compile_flags.has_value); + + REQUIRE(contains(cli.config.add_compile_flags(), "-Wno-error")); + REQUIRE(contains(cli.config.add_compile_flags(), "-Wno-warning")); + REQUIRE(contains(cli.config.remove_compile_flags(), "-I/usr/include")); } \ No newline at end of file From e6fb4329dfcabcfdc56ea6d95216ebc201e45fd8 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Fri, 5 May 2023 23:00:23 +0200 Subject: [PATCH 3/6] Updated troubleshooting docs section --- docs/troubleshooting.md | 56 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 434a8e9f..c00bac86 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -24,6 +24,43 @@ $ plantuml -tsvg mydiagram.puml $ convert +antialias mydiagram.svg mydiagram.png ``` +### `clang` produces several warnings during diagram generation +During the generation of the diagram `clang` may report a lot of warnings, which +do not occur during the compilation with other compiler (e.g. GCC). This can be +fixed easily by using the `add_compile_flags` config option. For instance, +assuming that the warnings are as follows: + +``` +... warning: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Wimplicit-const-int-float-conversion] +... warning: declaration shadows a variable in namespace 'YAML' [-Wshadow] +``` + +simply add the following to your `.clang-uml` configuration file: + +``` +add_compile_flags: + - -Wno-implicit-const-int-float-conversion + - -Wno-shadow +``` + +Alternatively, the same can be passed through the `clang-uml` command line, e.g. + +```bash +$ clang-uml --add-compile-flag -Wno-implicit-const-int-float-conversion \ + --add-compile-flag -Wno-shadow ... +``` + +Please note that if your `compile_commands.json` already contains - for instance +`-Wshadow` - then you also have to remove it, i.e.: + +``` +add_compile_flags: + - -Wno-implicit-const-int-float-conversion + - -Wno-shadow +remove_compile_flags: + - -Wshadow +``` + ### YAML anchors and aliases are not fully supported `clang-uml` uses [yaml-cpp](https://github.com/jbeder/yaml-cpp) library, which currently does not support @@ -76,6 +113,25 @@ project), e.g.: apt install clang ``` +If this doesn't help the include paths can be customized using config options: + * `add_compile_flags` - which adds a list of compile flags such as include paths to each entry of the compilation database + * `remove_compile_flags` - which removes existing compile flags from each entry of the compilation database + +For instance: + +```yaml +add_compile_flags: + - -I/opt/my_toolchain/include +remove_compile_flags: + - -I/usr/include +``` + +These options can be also passed on the command line, for instance: + +```bash +$ clang-uml --add-compile-flag -I/opt/my_toolchain/include \ + --remove-compile-flag -I/usr/include ... +``` ## Sequence diagrams ### Generated diagram is empty In order to generate sequence diagram the `start_from` configuration option must have a valid starting point From 2367765d1fbb148dab81863c92765e20eee8a3ce Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Fri, 5 May 2023 23:47:40 +0200 Subject: [PATCH 4/6] Fixed .gitignore --- .gitignore | 2 +- .../compile_commands.json | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/test_compilation_database_data/compile_commands.json diff --git a/.gitignore b/.gitignore index fdd98960..ae9199b0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ CMakeScripts Testing cmake_install.cmake install_manifest.txt -compile_commands.json +/compile_commands.json CTestTestfile.cmake Session.vim _deps diff --git a/tests/test_compilation_database_data/compile_commands.json b/tests/test_compilation_database_data/compile_commands.json new file mode 100644 index 00000000..bcdbb35c --- /dev/null +++ b/tests/test_compilation_database_data/compile_commands.json @@ -0,0 +1,17 @@ +[ + { + "directory": ".", + "command": "/usr/bin/c++ -I/usr/lib/llvm-15/include -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field -Wno-deprecated-declarations -std=c++17 -o CMakeFiles/clang-umllib.dir/class_diagram/generators/json/class_diagram_generator.cc.o -c ./src/class_diagram/generators/json/class_diagram_generator.cc", + "file": "./src/class_diagram/generators/json/class_diagram_generator.cc" + }, + { + "directory": ".", + "command": "/usr/bin/c++ -I/usr/lib/llvm-15/include -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field -Wno-deprecated-declarations -std=c++17 -o CMakeFiles/clang-umllib.dir/class_diagram/generators/plantuml/class_diagram_generator.cc.o -c ./src/class_diagram/generators/plantuml/class_diagram_generator.cc", + "file": "./src/class_diagram/generators/plantuml/class_diagram_generator.cc" + }, + { + "directory": ".", + "command": "/usr/bin/c++ -I/usr/lib/llvm-15/include -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field -Wno-deprecated-declarations -std=c++17 -o CMakeFiles/clang-umllib.dir/class_diagram/model/class.cc.o -c ./src/class_diagram/model/class.cc", + "file": "./src/class_diagram/model/class.cc" + } +] \ No newline at end of file From 4477a1892fb9bcb05c41719ee710f280fe9d1f7c Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sat, 6 May 2023 00:14:26 +0200 Subject: [PATCH 5/6] Updated configuration file specification --- docs/configuration_file.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/configuration_file.md b/docs/configuration_file.md index d365e3e9..25493ff1 100644 --- a/docs/configuration_file.md +++ b/docs/configuration_file.md @@ -16,6 +16,8 @@ * `diagrams` - the map of diagrams to be generated, each diagram name is provided as the key of the diagram YAML node * `debug_mode` - add inline debug information in the generated diagrams +* `add_compile_flags` - add compile flags to all compilation database entries +* `remove_compile_flags` - remove compile flags from all compilation database entries ### Diagram options * `type` - type of diagram, one of [`class`, `sequence`, `package`, `include`] @@ -56,6 +58,9 @@ compilation_database_dir: debug # Inject additional compile commands to the compilation database entries add_compile_flags: - '-Wno-vla-extension' +# Remove specified compile flags from all compilation database entries +remove_compile_flags: + - '-Wshadow' # The directory where *.puml files will be generated output_directory: docs/diagrams # Set this as default for all diagrams From 68a20c550bdc8468d492fdfb261b2dd03eaf5713 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sat, 6 May 2023 00:15:46 +0200 Subject: [PATCH 6/6] Updated troubleshooting --- docs/troubleshooting.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index c00bac86..23a4c3af 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -4,6 +4,7 @@ * [General issues](#general-issues) * [Diagram generated with PlantUML is cropped](#diagram-generated-with-plantuml-is-cropped) + * [`clang` produces several warnings during diagram generation](#clang-produces-several-warnings-during-diagram-generation) * [YAML anchors and aliases are not fully supported](#yaml-anchors-and-aliases-are-not-fully-supported) * [Class diagrams](#class-diagrams) * ["fatal error: 'stddef.h' file not found"](#fatal-error-stddefh-file-not-found)