summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2019-10-11 15:56:55 (GMT)
committerGitHub <noreply@github.com>2019-10-11 15:56:55 (GMT)
commit7b64ba14d84a48389b4d452d6d5dba69e3f9f93a (patch)
tree4f72c541aa8166864b2d31c64da33c361cc51d14
parent0ad7620c6451cb3fa0ca2ac091131f21701be9b5 (diff)
parent722228995b223b4507ebb686b48f94b9f7a8380c (diff)
downloadSCons-7b64ba14d84a48389b4d452d6d5dba69e3f9f93a.zip
SCons-7b64ba14d84a48389b4d452d6d5dba69e3f9f93a.tar.gz
SCons-7b64ba14d84a48389b4d452d6d5dba69e3f9f93a.tar.bz2
Merge pull request #3456 from edobez/master
Debug option "timestamp"
-rw-r--r--doc/man/scons.xml36
-rwxr-xr-xsrc/CHANGES.txt3
-rw-r--r--src/engine/SCons/Script/Main.py10
-rw-r--r--src/engine/SCons/Script/SConsOptions.py2
-rw-r--r--test/option/debug-action-timestamps.py105
5 files changed, 153 insertions, 3 deletions
diff --git a/doc/man/scons.xml b/doc/man/scons.xml
index 9065f25..b346cac 100644
--- a/doc/man/scons.xml
+++ b/doc/man/scons.xml
@@ -890,9 +890,43 @@ since multiple build commands and
intervening SCons processing
should take place in parallel.)
</para>
-
</listitem>
</varlistentry>
+
+<varlistentry>
+ <term>--debug=action_timestamps</term>
+ <listitem>
+ <para>Prints additional time profiling information:</para>
+ <itemizedlist>
+ <listitem>
+ <para>The time spent executing each individual build command</para>
+ </listitem>
+ <listitem>
+ <para>The total build time (time SCons ran from beginning to end)</para>
+ </listitem>
+ <listitem>
+ <para>The total time spent reading and executing SConscript files</para>
+ </listitem>
+ <listitem>
+ <para>The total time spent SCons itself spend running
+(that is, not counting reading and executing SConscript files)</para>
+ </listitem>
+ <listitem>
+ <para>The total time spent executing all build commands</para>
+ </listitem>
+ <listitem>
+ <para>The elapsed wall-clock time spent executing those build commands</para>
+ </listitem>
+ <listitem>
+ <para>The absolute start and end wall-clock time spent executing those build commands</para>
+ </listitem>
+ <listitem>
+ <para>The time spent processing each file passed to the <emphasis>SConscript()</emphasis> function</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+</varlistentry>
+
<varlistentry>
<term>--diskcheck=<emphasis>types</emphasis></term>
<listitem>
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 0a30bfa..260cb91 100755
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -25,6 +25,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
From Jakub Kulik
- Fix subprocess result bytes not being decoded in SunOS/Solaris related tools.
+
+ From Edoardo Bezzeccheri
+ - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target.
RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index acc8678..58dbf64 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -75,6 +75,7 @@ print_objects = 0
print_memoizer = 0
print_stacktrace = 0
print_time = 0
+print_action_timestamps = 0
sconscript_time = 0
cumulative_command_time = 0
exit_status = 0 # final exit status, assume success by default
@@ -209,7 +210,11 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask):
finish_time = time.time()
last_command_end = finish_time
cumulative_command_time = cumulative_command_time+finish_time-start_time
+ if print_action_timestamps:
+ sys.stdout.write("Command execution start time: %s: %f seconds\n"%(str(self.node), start_time))
sys.stdout.write("Command execution time: %s: %f seconds\n"%(str(self.node), finish_time-start_time))
+ if print_action_timestamps:
+ sys.stdout.write("Command execution stop time: %s: %f seconds\n"%(str(self.node), finish_time))
def do_failed(self, status=2):
_BuildFailures.append(self.exception[1])
@@ -636,7 +641,7 @@ def _SConstruct_exists(dirname='', repositories=[], filelist=None):
return None
def _set_debug_values(options):
- global print_memoizer, print_objects, print_stacktrace, print_time
+ global print_memoizer, print_objects, print_stacktrace, print_time, print_action_timestamps
debug_values = options.debug
@@ -674,6 +679,9 @@ def _set_debug_values(options):
options.tree_printers.append(TreePrinter(status=True))
if "time" in debug_values:
print_time = 1
+ if "action_timestamps" in debug_values:
+ print_time = 1
+ print_action_timestamps = 1
if "tree" in debug_values:
options.tree_printers.append(TreePrinter())
if "prepare" in debug_values:
diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py
index add1150..7b5d523 100644
--- a/src/engine/SCons/Script/SConsOptions.py
+++ b/src/engine/SCons/Script/SConsOptions.py
@@ -622,7 +622,7 @@ def Parser(version):
debug_options = ["count", "duplicate", "explain", "findlibs",
"includes", "memoizer", "memory", "objects",
"pdb", "prepare", "presub", "stacktrace",
- "time"]
+ "time", "action_timestamps"]
def opt_debug(option, opt, value__, parser,
debug_options=debug_options,
diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py
new file mode 100644
index 0000000..11a4bf5
--- /dev/null
+++ b/test/option/debug-action-timestamps.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+from __future__ import division, print_function
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+import re
+
+_python_ = TestSCons._python_
+
+def setup_fixtures():
+ test.file_fixture('../fixture/test_main.c', 'main.c')
+ test.write('SConstruct', """
+DefaultEnvironment(tools=[])
+env = Environment()
+env.Program('main.exe', ['main.c'])
+""")
+
+def test_help_function():
+ # Before anything else, make sure we get valid --debug=action_timestamps results
+ # when just running the help option.
+ test.run(arguments = "-h --debug=action_timestamps")
+
+def build():
+ # Execute build
+ test.run(arguments='--debug=action_timestamps')
+ build_output = test.stdout()
+ return build_output
+
+def get_matches_from_output(build_output):
+ return [re.findall(pattern, build_output) for pattern in debug_time_patterns]
+
+def test_presence_of_debug_time_strings(build_output):
+ # Check presence of duration and timestamps
+ if None in get_matches_from_output(build_output):
+ print("One or more of the time debug strings were not found in the build output")
+ test.fail_test(1)
+
+def test_equal_number_of_debug_time_strings(build_output):
+ matches = get_matches_from_output(build_output)
+ num_of_matches = [len(match) for match in matches]
+
+ # Check that the number of matches for each pattern is the same
+ if num_of_matches.count(num_of_matches[0]) != len(num_of_matches):
+ print("Debug time strings differs in quantity")
+ test.fail_test(2)
+
+def test_correctness_of_timestamps(build_output):
+ # Check if difference between timestamps is equal to duration
+ matches = get_matches_from_output(build_output)
+
+ def match_to_float(m):
+ return float(m[1][1])
+
+ execution_time = match_to_float(matches[0])
+ start_time = match_to_float(matches[1])
+ stop_time = match_to_float(matches[2])
+ delta_time = stop_time - start_time
+
+ def within_tolerance(expected, actual, tolerance):
+ return abs((expected-actual)/actual) <= tolerance
+
+ if not within_tolerance(execution_time, delta_time, 0.001):
+ print("Difference of timestamps differ from action duration")
+ print("Execution time = {}. Start time = {}. Stop time = {}. Delta time = {}".format(execution_time, start_time, stop_time, delta_time))
+ test.fail_test(3)
+
+debug_time_patterns = [
+ r'Command execution time: (.*): (\d+\.\d+) seconds',
+ r'Command execution start time: (.*): (\d+\.\d+) seconds',
+ r'Command execution stop time: (.*): (\d+\.\d+) seconds'
+]
+
+test = TestSCons.TestSCons()
+setup_fixtures()
+
+test_help_function()
+
+build_output = build()
+test_presence_of_debug_time_strings(build_output)
+test_equal_number_of_debug_time_strings(build_output)
+test_correctness_of_timestamps(build_output)
+
+test.pass_test()