summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2022-10-15 21:09:36 +0300
committerGitHub <noreply@github.com>2022-10-15 20:09:36 +0200
commitbda468cf42988546cd84ab5a6f8e556cff29480a (patch)
tree9b9edc3c6042644dfa471b1722c3e3040c7a4f3b
parent3dc94c94a00d592533b40baa5f6a56eba268ba3e (diff)
downloadccache-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.adoc2
-rw-r--r--src/Config.hpp7
-rw-r--r--src/Context.hpp2
-rw-r--r--src/argprocessing.cpp7
-rw-r--r--src/ccache.cpp10
-rw-r--r--src/core/ResultRetriever.cpp6
-rw-r--r--src/core/ShowIncludesParser.cpp24
-rw-r--r--src/core/ShowIncludesParser.hpp4
-rw-r--r--unittest/test_core_ShowIncludesParser.cpp78
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();