From e63151ff543bb665fea255713e2e643e64527517 Mon Sep 17 00:00:00 2001
From: Alex Turbov <i.zaufi@gmail.com>
Date: Tue, 14 Jun 2016 02:27:58 +0700
Subject: cmake: Add an option to control what files needs to be traced

Even in relatively small projects using `--trace` (and `--trace-expand`)
may produce a lot of output.  When developing a custom module usually
one is interested in output of only a few particular modules.

Add a `--trace-source=<file>` option to enable tracing only a subset of
source files.  The final output would be only from requested modules,
ignoring anything else not matched to given filename(s).
---
 Help/manual/cmake.1.rst                            |  5 +++++
 Help/release/dev/cmake-trace-source.rst            |  4 ++++
 Source/cmMakefile.cxx                              | 24 +++++++++++++++++++++-
 Source/cmake.cxx                                   |  5 +++++
 Source/cmake.h                                     | 10 +++++++++
 Source/cmakemain.cxx                               |  2 ++
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake      |  4 ++++
 .../CommandLine/trace-only-this-file.cmake         |  1 +
 Tests/RunCMake/CommandLine/trace-source-stderr.txt |  1 +
 Tests/RunCMake/CommandLine/trace-source.cmake      |  3 +++
 10 files changed, 58 insertions(+), 1 deletion(-)
 create mode 100644 Help/release/dev/cmake-trace-source.rst
 create mode 100644 Tests/RunCMake/CommandLine/trace-only-this-file.cmake
 create mode 100644 Tests/RunCMake/CommandLine/trace-source-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/trace-source.cmake

diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 65153af..8f7c336 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -108,6 +108,11 @@ Options
 
  Like ``--trace``, but with variables expanded.
 
+``--trace-source=<file>``
+ Put cmake in trace mode, but output only lines of a specified file.
+
+ Multiple options are allowed.
+
 ``--warn-uninitialized``
  Warn about uninitialized values.
 
diff --git a/Help/release/dev/cmake-trace-source.rst b/Help/release/dev/cmake-trace-source.rst
new file mode 100644
index 0000000..9b17f6c
--- /dev/null
+++ b/Help/release/dev/cmake-trace-source.rst
@@ -0,0 +1,4 @@
+cmake-trace-source
+------------------
+
+* The :manual:`cmake(1)` command learned a ``--trace-source=<file>`` option.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 5712070..e8c1576 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -37,6 +37,7 @@
 
 #include <cmsys/FStream.hxx>
 #include <cmsys/RegularExpression.hxx>
+#include <cmsys/SystemTools.hxx>
 #include <cmsys/auto_ptr.hxx>
 
 #include <assert.h>
@@ -175,8 +176,29 @@ cmListFileContext cmMakefile::GetExecutionContext() const
 
 void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
 {
+  // Check if current file in the list of requested to trace...
+  std::vector<std::string> const& trace_only_this_files =
+    this->GetCMakeInstance()->GetTraceSources();
+  std::string const& full_path = this->GetExecutionFilePath();
+  std::string const& only_filename = cmSystemTools::GetFilenameName(full_path);
+  bool trace = trace_only_this_files.empty();
+  if (!trace) {
+    for (std::vector<std::string>::const_iterator i =
+           trace_only_this_files.begin();
+         !trace && i != trace_only_this_files.end(); ++i) {
+      std::string::size_type const pos = full_path.rfind(*i);
+      trace = (pos != std::string::npos) &&
+        ((pos + i->size()) == full_path.size()) &&
+        (only_filename == cmSystemTools::GetFilenameName(*i));
+    }
+    // Do nothing if current file wasn't requested for trace...
+    if (!trace) {
+      return;
+    }
+  }
+
   std::ostringstream msg;
-  msg << this->GetExecutionFilePath() << "(" << lff.Line << "):  ";
+  msg << full_path << "(" << lff.Line << "):  ";
   msg << lff.Name << "(";
   bool expand = this->GetCMakeInstance()->GetTraceExpand();
   std::string temp;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index db0072a..654100b 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -589,6 +589,11 @@ void cmake::SetArgs(const std::vector<std::string>& args,
       std::cout << "Running with expanded trace output on.\n";
       this->SetTrace(true);
       this->SetTraceExpand(true);
+    } else if (arg.find("--trace-source=", 0) == 0) {
+      std::string file = arg.substr(strlen("--trace-source="));
+      cmSystemTools::ConvertToUnixSlashes(file);
+      this->AddTraceSource(file);
+      this->SetTrace(true);
     } else if (arg.find("--trace", 0) == 0) {
       std::cout << "Running with trace output on.\n";
       this->SetTrace(true);
diff --git a/Source/cmake.h b/Source/cmake.h
index c5d7cbb..9ac6935 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -307,6 +307,14 @@ public:
   void SetTrace(bool b) { this->Trace = b; }
   bool GetTraceExpand() { return this->TraceExpand; }
   void SetTraceExpand(bool b) { this->TraceExpand = b; }
+  void AddTraceSource(std::string const& file)
+  {
+    this->TraceOnlyThisSources.push_back(file);
+  }
+  std::vector<std::string> const& GetTraceSources() const
+  {
+    return this->TraceOnlyThisSources;
+  }
   bool GetWarnUninitialized() { return this->WarnUninitialized; }
   void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
   bool GetWarnUnused() { return this->WarnUnused; }
@@ -481,6 +489,8 @@ private:
   cmState* State;
   cmState::Snapshot CurrentSnapshot;
 
+  std::vector<std::string> TraceOnlyThisSources;
+
   void UpdateConversionPathTable();
 
   // Print a list of valid generators to stderr.
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 056671a..495aae5 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -73,6 +73,8 @@ static const char* cmDocumentationOptions[][2] = {
   { "--debug-output", "Put cmake in a debug mode." },
   { "--trace", "Put cmake in trace mode." },
   { "--trace-expand", "Put cmake in trace mode with variable expansion." },
+  { "--trace-source=<file>",
+    "Trace only this CMake file/module. Multiple options allowed." },
   { "--warn-uninitialized", "Warn about uninitialized values." },
   { "--warn-unused-vars", "Warn about unused variables." },
   { "--no-warn-unused-cli", "Don't warn about command line options." },
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index f449f1d..077a19d 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -264,6 +264,10 @@ set(RunCMake_TEST_OPTIONS --trace-expand)
 run_cmake(trace-expand)
 unset(RunCMake_TEST_OPTIONS)
 
+set(RunCMake_TEST_OPTIONS --trace-source=trace-only-this-file.cmake)
+run_cmake(trace-source)
+unset(RunCMake_TEST_OPTIONS)
+
 set(RunCMake_TEST_OPTIONS --debug-trycompile)
 run_cmake(debug-trycompile)
 unset(RunCMake_TEST_OPTIONS)
diff --git a/Tests/RunCMake/CommandLine/trace-only-this-file.cmake b/Tests/RunCMake/CommandLine/trace-only-this-file.cmake
new file mode 100644
index 0000000..1450271
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/trace-only-this-file.cmake
@@ -0,0 +1 @@
+message(STATUS "trace particular file test passed")
diff --git a/Tests/RunCMake/CommandLine/trace-source-stderr.txt b/Tests/RunCMake/CommandLine/trace-source-stderr.txt
new file mode 100644
index 0000000..dc90c65
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/trace-source-stderr.txt
@@ -0,0 +1 @@
+^.*/trace-only-this-file.cmake\(1\):  message\(STATUS trace particular file test passed \)$
diff --git a/Tests/RunCMake/CommandLine/trace-source.cmake b/Tests/RunCMake/CommandLine/trace-source.cmake
new file mode 100644
index 0000000..5ac2d9d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/trace-source.cmake
@@ -0,0 +1,3 @@
+message(STATUS "before include()")
+include("trace-only-this-file.cmake")
+message(STATUS "after include()")
-- 
cgit v0.12