diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2022-10-15 21:09:36 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-15 20:09:36 +0200 |
commit | bda468cf42988546cd84ab5a6f8e556cff29480a (patch) | |
tree | 9b9edc3c6042644dfa471b1722c3e3040c7a4f3b | |
parent | 3dc94c94a00d592533b40baa5f6a56eba268ba3e (diff) | |
download | ccache-bda468cf42988546cd84ab5a6f8e556cff29480a.tar.gz |
feat: Support auto depend mode for MSVC without /showIncludes (#1176)
If MSVC is executed *without* /showIncludes, and ccache is configured with
depend mode, add /showIncludes and strip the extra output from stdout.
-rw-r--r-- | doc/MANUAL.adoc | 2 | ||||
-rw-r--r-- | src/Config.hpp | 7 | ||||
-rw-r--r-- | src/Context.hpp | 2 | ||||
-rw-r--r-- | src/argprocessing.cpp | 7 | ||||
-rw-r--r-- | src/ccache.cpp | 10 | ||||
-rw-r--r-- | src/core/ResultRetriever.cpp | 6 | ||||
-rw-r--r-- | src/core/ShowIncludesParser.cpp | 24 | ||||
-rw-r--r-- | src/core/ShowIncludesParser.hpp | 4 | ||||
-rw-r--r-- | unittest/test_core_ShowIncludesParser.cpp | 78 |
9 files changed, 136 insertions, 4 deletions
diff --git a/doc/MANUAL.adoc b/doc/MANUAL.adoc index 37e0226a..e2ebf408 100644 --- a/doc/MANUAL.adoc +++ b/doc/MANUAL.adoc @@ -1583,7 +1583,7 @@ The depend mode will be disabled if any of the following holds: * <<config_depend_mode,*depend_mode*>> is false. * <<config_run_second_cpp,*run_second_cpp*>> is false. * The compiler is not generating dependencies using `-MD` or `-MMD` (for MSVC, - /showIncludes). + /showIncludes is added automatically if not specified by the user). == Handling of newly created header files diff --git a/src/Config.hpp b/src/Config.hpp index 6399253f..18cf74a7 100644 --- a/src/Config.hpp +++ b/src/Config.hpp @@ -120,6 +120,7 @@ public: void set_max_size(uint64_t value); void set_run_second_cpp(bool value); void set_temporary_dir(const std::string& value); + void set_msvc_dep_prefix(const std::string& value); // Where to write configuration changes. const std::string& config_path() const; @@ -593,3 +594,9 @@ Config::set_temporary_dir(const std::string& value) { m_temporary_dir = value; } + +inline void +Config::set_msvc_dep_prefix(const std::string& value) +{ + m_msvc_dep_prefix = value; +} diff --git a/src/Context.hpp b/src/Context.hpp index 9d608410..25b11409 100644 --- a/src/Context.hpp +++ b/src/Context.hpp @@ -118,6 +118,8 @@ public: std::unique_ptr<MiniTrace> mini_trace; #endif + bool auto_depend_mode = false; + // Register a temporary file to remove at program exit. void register_pending_tmp_file(const std::string& path); diff --git a/src/argprocessing.cpp b/src/argprocessing.cpp index e1ec1121..2b0603f9 100644 --- a/src/argprocessing.cpp +++ b/src/argprocessing.cpp @@ -1499,6 +1499,13 @@ process_args(Context& ctx) } } + if (ctx.config.depend_mode() && !args_info.generating_includes + && ctx.config.compiler_type() == CompilerType::msvc) { + ctx.auto_depend_mode = true; + args_info.generating_includes = true; + args_info.depend_extra_args.push_back("-showIncludes"); + } + return { preprocessor_args, extra_args_to_hash, diff --git a/src/ccache.cpp b/src/ccache.cpp index 6effb648..5b8ce656 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -1075,7 +1075,10 @@ to_cache(Context& ctx, Util::send_to_fd( ctx, util::to_string_view(result->stderr_data), STDERR_FILENO); Util::send_to_fd( - ctx, util::to_string_view(result->stdout_data), STDOUT_FILENO); + ctx, + util::to_string_view(core::ShowIncludesParser::strip_includes( + ctx, std::move(result->stdout_data))), + STDOUT_FILENO); auto failure = Failure(Statistic::compile_failed); failure.set_exit_code(result->exit_status); @@ -1134,7 +1137,10 @@ to_cache(Context& ctx, ctx, util::to_string_view(result->stderr_data), STDERR_FILENO); // Send stdout after stderr, it makes the output clearer with MSVC. Util::send_to_fd( - ctx, util::to_string_view(result->stdout_data), STDOUT_FILENO); + ctx, + util::to_string_view(core::ShowIncludesParser::strip_includes( + ctx, std::move(result->stdout_data))), + STDOUT_FILENO); return *result_key; } diff --git a/src/core/ResultRetriever.cpp b/src/core/ResultRetriever.cpp index bdefc19f..484e1632 100644 --- a/src/core/ResultRetriever.cpp +++ b/src/core/ResultRetriever.cpp @@ -24,6 +24,7 @@ #include <Context.hpp> #include <Stat.hpp> +#include <core/ShowIncludesParser.hpp> #include <core/exceptions.hpp> #include <core/wincompat.hpp> #include <fmtmacros.hpp> @@ -61,7 +62,10 @@ ResultRetriever::on_embedded_file(uint8_t file_number, data.size()); if (file_type == FileType::stdout_output) { - Util::send_to_fd(m_ctx, util::to_string_view(data), STDOUT_FILENO); + Util::send_to_fd( + m_ctx, + util::to_string_view(ShowIncludesParser::strip_includes(m_ctx, data)), + STDOUT_FILENO); } else if (file_type == FileType::stderr_output) { Util::send_to_fd(m_ctx, util::to_string_view(data), STDERR_FILENO); } else { diff --git a/src/core/ShowIncludesParser.cpp b/src/core/ShowIncludesParser.cpp index a25cf76a..ca1b764c 100644 --- a/src/core/ShowIncludesParser.cpp +++ b/src/core/ShowIncludesParser.cpp @@ -49,4 +49,28 @@ tokenize(std::string_view file_content, std::string_view prefix) return result; } +util::Bytes +strip_includes(const Context& ctx, util::Bytes&& stdout_data) +{ + using util::Tokenizer; + using Mode = Tokenizer::Mode; + using IncludeDelimiter = Tokenizer::IncludeDelimiter; + + if (stdout_data.empty() || !ctx.auto_depend_mode + || ctx.config.compiler_type() != CompilerType::msvc) { + return std::move(stdout_data); + } + + std::string new_stdout_text; + for (const auto line : Tokenizer(util::to_string_view(stdout_data), + "\n", + Mode::include_empty, + IncludeDelimiter::yes)) { + if (!util::starts_with(line, ctx.config.msvc_dep_prefix())) { + new_stdout_text.append(line.data(), line.length()); + } + } + return util::Bytes(new_stdout_text.data(), new_stdout_text.size()); +} + } // namespace core::ShowIncludesParser diff --git a/src/core/ShowIncludesParser.hpp b/src/core/ShowIncludesParser.hpp index a977cec0..a368d62b 100644 --- a/src/core/ShowIncludesParser.hpp +++ b/src/core/ShowIncludesParser.hpp @@ -18,6 +18,8 @@ #pragma once +#include <util/Bytes.hpp> + #include <string_view> #include <vector> @@ -28,4 +30,6 @@ namespace core::ShowIncludesParser { std::vector<std::string_view> tokenize(std::string_view file_content, std::string_view prefix); +util::Bytes strip_includes(const Context& ctx, util::Bytes&& stdout_data); + } // namespace core::ShowIncludesParser diff --git a/unittest/test_core_ShowIncludesParser.cpp b/unittest/test_core_ShowIncludesParser.cpp index c3ba58c5..2d3fc572 100644 --- a/unittest/test_core_ShowIncludesParser.cpp +++ b/unittest/test_core_ShowIncludesParser.cpp @@ -16,7 +16,9 @@ // this program; if not, write to the Free Software Foundation, Inc., 51 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#include "../src/Context.hpp" #include "../src/core/ShowIncludesParser.hpp" +#include "../src/util/string.hpp" #include "TestUtil.hpp" #include "third_party/doctest.h" @@ -93,4 +95,80 @@ Just a line with custom in the middle)"; } } +TEST_CASE("ShowIncludesParser::strip_includes") +{ + Context ctx; + const util::Bytes input = util::to_span( + "First\n" + "Note: including file: foo\n" + "Second\n"); + + SUBCASE("empty output") + { + const util::Bytes result = + core::ShowIncludesParser::strip_includes(ctx, {}); + CHECK(result.size() == 0); + } + + SUBCASE("feature disabled") + { + const util::Bytes result = + core::ShowIncludesParser::strip_includes(ctx, util::Bytes(input)); + CHECK(result == input); + } + + ctx.auto_depend_mode = true; + + SUBCASE("wrong compiler") + { + const util::Bytes result = + core::ShowIncludesParser::strip_includes(ctx, util::Bytes(input)); + CHECK(result == input); + } + + ctx.config.set_compiler_type(CompilerType::msvc); + + SUBCASE("Simple output") + { + const util::Bytes result = + core::ShowIncludesParser::strip_includes(ctx, util::Bytes(input)); + CHECK(result == util::to_span("First\nSecond\n")); + } + + SUBCASE("Empty lines") + { + const util::Bytes result = core::ShowIncludesParser::strip_includes( + ctx, + util::to_span("First\n" + "\n" + "Note: including file: foo\n" + "\n" + "Second\n" + "\n")); + CHECK(result == util::to_span("First\n\n\nSecond\n\n")); + } + + SUBCASE("CRLF") + { + const util::Bytes result = core::ShowIncludesParser::strip_includes( + ctx, + util::to_span("First\r\n" + "Note: including file: foo\r\n" + "Second\r\n")); + CHECK(result == util::to_span("First\r\nSecond\r\n")); + } + + SUBCASE("Custom prefix") + { + ctx.config.set_msvc_dep_prefix("custom"); + const util::Bytes result = core::ShowIncludesParser::strip_includes( + ctx, + util::to_span("First\n" + "custom: including file: foo\n" + "Second\n" + "Third custom line\n")); + CHECK(result == util::to_span("First\nSecond\nThird custom line\n")); + } +} + TEST_SUITE_END(); |