summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2019-07-14 21:19:49 (GMT)
committerGitHub <noreply@github.com>2019-07-14 21:19:49 (GMT)
commitdf0b5d7336b586481aace243925d688505a0dcba (patch)
treef0dfd5c4b9c89e617d5949bc59890b324fadede4
parent2f38ee65e95cdcea441f028d7c3ce9d1b4746862 (diff)
parenta2bb59f78fb41ca5b81e220032245d4c732ba566 (diff)
downloadSCons-df0b5d7336b586481aace243925d688505a0dcba.zip
SCons-df0b5d7336b586481aace243925d688505a0dcba.tar.gz
SCons-df0b5d7336b586481aace243925d688505a0dcba.tar.bz2
Merge pull request #3400 from bdbaddog/fix_slow_md5_decider
Fix slow MD5-timestamp decider
-rw-r--r--.gitignore3
-rwxr-xr-xbin/upload-release-files.sh3
-rw-r--r--doc/generated/examples/caching_ex-random_1.xml6
-rw-r--r--doc/generated/examples/troubleshoot_explain1_3.xml2
-rw-r--r--doc/generated/functions.gen13
-rw-r--r--doc/generated/tools.gen12
-rw-r--r--doc/generated/tools.mod4
-rw-r--r--doc/generated/variables.gen20
-rw-r--r--doc/generated/variables.mod4
-rw-r--r--doc/scons.mod1
-rw-r--r--doc/user/depends.xml11
-rwxr-xr-xsrc/CHANGES.txt8
-rwxr-xr-xsrc/RELEASE.txt8
-rw-r--r--src/engine/SCons/Action.py2
-rw-r--r--src/engine/SCons/Environment.py39
-rw-r--r--src/engine/SCons/Environment.xml13
-rw-r--r--src/engine/SCons/Node/FS.py110
-rw-r--r--src/engine/SCons/Node/__init__.py47
-rw-r--r--src/engine/SCons/SConf.py9
-rw-r--r--test/Decider/Environment.py2
-rw-r--r--test/Decider/Node.py2
-rw-r--r--test/Decider/default.py2
-rw-r--r--test/Decider/mixed.py6
-rw-r--r--test/packaging/rpm/explicit-target.py2
24 files changed, 196 insertions, 133 deletions
diff --git a/.gitignore b/.gitignore
index 546c893..99c8ab2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,3 +48,6 @@ htmlcov
*.bak
*~
!/test/Decider/switch-rebuild.py
+
+# Mac junk
+**/.DS_Store
diff --git a/bin/upload-release-files.sh b/bin/upload-release-files.sh
index 9a09206..577203e 100755
--- a/bin/upload-release-files.sh
+++ b/bin/upload-release-files.sh
@@ -35,7 +35,7 @@ $RSYNC $RSYNCOPTS \
Announce.txt CHANGES.txt RELEASE.txt \
$SF_USER@$SF_MACHINE:$SF_TOPDIR/scons-local/$VERSION/
-Source packages:
+# Source packages:
$RSYNC $RSYNCOPTS \
scons-src-$VERSION.tar.gz \
scons-src-$VERSION.zip \
@@ -48,7 +48,6 @@ $RSYNC $RSYNCOPTS \
$SF_USER@$SF_MACHINE:$SF_TOPDIR/
-
#
# scons.org stuff:
#
diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml
index 9f59db5..9ad59e0 100644
--- a/doc/generated/examples/caching_ex-random_1.xml
+++ b/doc/generated/examples/caching_ex-random_1.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput>
-cc -o f2.o -c f2.c
-cc -o f1.o -c f1.c
-cc -o f5.o -c f5.c
cc -o f4.o -c f4.c
+cc -o f2.o -c f2.c
cc -o f3.o -c f3.c
+cc -o f5.o -c f5.c
+cc -o f1.o -c f1.c
cc -o prog f1.o f2.o f3.o f4.o f5.o
</screen>
diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml
index a461f60..8f06986 100644
--- a/doc/generated/examples/troubleshoot_explain1_3.xml
+++ b/doc/generated/examples/troubleshoot_explain1_3.xml
@@ -3,5 +3,5 @@
cp file.in file.oout
scons: warning: Cannot find target file.out after building
-File "/home/bdeegan/devel/scons/git/scons/bootstrap/src/script/scons.py", line 204, in &lt;module&gt;
+File "/Users/bdbaddog/devel/scons/git/scons-bugfixes-3/bootstrap/src/script/scons.py", line 204, in &lt;module&gt;
</screen>
diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen
index 953d374..5e8bebb 100644
--- a/doc/generated/functions.gen
+++ b/doc/generated/functions.gen
@@ -1139,6 +1139,17 @@ size, or content signature.
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+<term><parameter>repo_node</parameter></term>
+<listitem>
+<para>
+Use this node instead of the one specified by
+<varname>dependency</varname>
+ to determine if the dependency has changed.
+</para>
+</listitem>
+</varlistentry>
+
</variablelist>
</para>
@@ -1175,7 +1186,7 @@ Example:
</para>
<example_commands xmlns="http://www.scons.org/dbxsd/v1.0">
-def my_decider(dependency, target, prev_ni):
+def my_decider(dependency, target, prev_ni, repo_node=None):
return not os.path.exists(str(target))
env.Decider(my_decider)
diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen
index be717e3..ecd9c98 100644
--- a/doc/generated/tools.gen
+++ b/doc/generated/tools.gen
@@ -779,19 +779,19 @@ Sets construction variables for the
</para>
<para>Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.</para><para>Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;.</para></listitem>
</varlistentry>
- <varlistentry id="t-packaging">
- <term>packaging</term>
+ <varlistentry id="t-Packaging">
+ <term>Packaging</term>
<listitem>
<para xmlns="http://www.scons.org/dbxsd/v1.0">
-A framework for building binary and source packages.
+Sets construction variables for the <function xmlns="http://www.scons.org/dbxsd/v1.0">Package</function> Builder.
</para>
</listitem>
</varlistentry>
- <varlistentry id="t-Packaging">
- <term>Packaging</term>
+ <varlistentry id="t-packaging">
+ <term>packaging</term>
<listitem>
<para xmlns="http://www.scons.org/dbxsd/v1.0">
-Sets construction variables for the <function xmlns="http://www.scons.org/dbxsd/v1.0">Package</function> Builder.
+A framework for building binary and source packages.
</para>
</listitem>
</varlistentry>
diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod
index f9bc1d7..1209d74 100644
--- a/doc/generated/tools.mod
+++ b/doc/generated/tools.mod
@@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY t-mwcc "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>mwcc</literal>">
<!ENTITY t-mwld "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>mwld</literal>">
<!ENTITY t-nasm "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>nasm</literal>">
-<!ENTITY t-packaging "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>packaging</literal>">
<!ENTITY t-Packaging "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Packaging</literal>">
+<!ENTITY t-packaging "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>packaging</literal>">
<!ENTITY t-pdf "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>pdf</literal>">
<!ENTITY t-pdflatex "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>pdflatex</literal>">
<!ENTITY t-pdftex "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>pdftex</literal>">
@@ -186,8 +186,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY t-link-mwcc "<link linkend='t-mwcc' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>mwcc</literal></link>">
<!ENTITY t-link-mwld "<link linkend='t-mwld' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>mwld</literal></link>">
<!ENTITY t-link-nasm "<link linkend='t-nasm' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>nasm</literal></link>">
-<!ENTITY t-link-packaging "<link linkend='t-packaging' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>packaging</literal></link>">
<!ENTITY t-link-Packaging "<link linkend='t-Packaging' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>Packaging</literal></link>">
+<!ENTITY t-link-packaging "<link linkend='t-packaging' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>packaging</literal></link>">
<!ENTITY t-link-pdf "<link linkend='t-pdf' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>pdf</literal></link>">
<!ENTITY t-link-pdflatex "<link linkend='t-pdflatex' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>pdflatex</literal></link>">
<!ENTITY t-link-pdftex "<link linkend='t-pdftex' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>pdftex</literal></link>">
diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen
index ad64b70..5606e2e 100644
--- a/doc/generated/variables.gen
+++ b/doc/generated/variables.gen
@@ -6789,6 +6789,16 @@ Example <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION">
</para>
</listitem>
</varlistentry>
+ <varlistentry id="cv-SHLIBVERSIONFLAGS">
+ <term>SHLIBVERSIONFLAGS</term>
+ <listitem>
+<para xmlns="http://www.scons.org/dbxsd/v1.0">
+Extra flags added to <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLINKCOM"><envar>$SHLINKCOM</envar></link> when building versioned
+<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="b-SharedLibrary"><function>SharedLibrary</function></link>. These flags are only used when <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> is
+set.
+</para>
+</listitem>
+ </varlistentry>
<varlistentry id="cv-_SHLIBVERSIONFLAGS">
<term>_SHLIBVERSIONFLAGS</term>
<listitem>
@@ -6802,16 +6812,6 @@ and some extra dynamically generated options (such as
</para>
</listitem>
</varlistentry>
- <varlistentry id="cv-SHLIBVERSIONFLAGS">
- <term>SHLIBVERSIONFLAGS</term>
- <listitem>
-<para xmlns="http://www.scons.org/dbxsd/v1.0">
-Extra flags added to <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLINKCOM"><envar>$SHLINKCOM</envar></link> when building versioned
-<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="b-SharedLibrary"><function>SharedLibrary</function></link>. These flags are only used when <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> is
-set.
-</para>
-</listitem>
- </varlistentry>
<varlistentry id="cv-SHLINK">
<term>SHLINK</term>
<listitem>
diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod
index 47576f4..372a15f 100644
--- a/doc/generated/variables.mod
+++ b/doc/generated/variables.mod
@@ -504,8 +504,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY cv-_SHLIBSONAME "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_SHLIBSONAME</envar>">
<!ENTITY cv-SHLIBSUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBSUFFIX</envar>">
<!ENTITY cv-SHLIBVERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBVERSION</envar>">
-<!ENTITY cv-_SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_SHLIBVERSIONFLAGS</envar>">
<!ENTITY cv-SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBVERSIONFLAGS</envar>">
+<!ENTITY cv-_SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_SHLIBVERSIONFLAGS</envar>">
<!ENTITY cv-SHLINK "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLINK</envar>">
<!ENTITY cv-SHLINKCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLINKCOM</envar>">
<!ENTITY cv-SHLINKCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLINKCOMSTR</envar>">
@@ -1144,8 +1144,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY cv-link-_SHLIBSONAME "<link linkend='cv-_SHLIBSONAME' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_SHLIBSONAME</envar></link>">
<!ENTITY cv-link-SHLIBSUFFIX "<link linkend='cv-SHLIBSUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBSUFFIX</envar></link>">
<!ENTITY cv-link-SHLIBVERSION "<link linkend='cv-SHLIBVERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBVERSION</envar></link>">
-<!ENTITY cv-link-_SHLIBVERSIONFLAGS "<link linkend='cv-_SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_SHLIBVERSIONFLAGS</envar></link>">
<!ENTITY cv-link-SHLIBVERSIONFLAGS "<link linkend='cv-SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBVERSIONFLAGS</envar></link>">
+<!ENTITY cv-link-_SHLIBVERSIONFLAGS "<link linkend='cv-_SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_SHLIBVERSIONFLAGS</envar></link>">
<!ENTITY cv-link-SHLINK "<link linkend='cv-SHLINK' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLINK</envar></link>">
<!ENTITY cv-link-SHLINKCOM "<link linkend='cv-SHLINKCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLINKCOM</envar></link>">
<!ENTITY cv-link-SHLINKCOMSTR "<link linkend='cv-SHLINKCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLINKCOMSTR</envar></link>">
diff --git a/doc/scons.mod b/doc/scons.mod
index 974ec02..77fa39b 100644
--- a/doc/scons.mod
+++ b/doc/scons.mod
@@ -67,6 +67,7 @@
<!ENTITY Action "<classname xmlns='http://www.scons.org/dbxsd/v1.0'>Action</classname>">
<!ENTITY ActionBase "<classname xmlns='http://www.scons.org/dbxsd/v1.0'>ActionBase</classname>">
+<!ENTITY BuildInfo "<classname xmlns='http://www.scons.org/dbxsd/v1.0'>BuildInfo</classname>">
<!ENTITY CommandAction "<classname xmlns='http://www.scons.org/dbxsd/v1.0'>CommandAction</classname>">
<!ENTITY FunctionAction "<classname xmlns='http://www.scons.org/dbxsd/v1.0'>FunctionAction</classname>">
<!ENTITY ListAction "<classname xmlns='http://www.scons.org/dbxsd/v1.0'>ListAction</classname>">
diff --git a/doc/user/depends.xml b/doc/user/depends.xml
index 297eaa2..7947900 100644
--- a/doc/user/depends.xml
+++ b/doc/user/depends.xml
@@ -517,7 +517,7 @@ cc -o hello hello.o
<scons_example name="depends_function">
<file name="SConstruct" printme="1">
Program('hello.c')
-def decide_if_changed(dependency, target, prev_ni):
+def decide_if_changed(dependency, target, prev_ni, repo_node=None):
if dependency.get_timestamp() != prev_ni.timestamp:
dep = str(dependency)
tgt = str(target)
@@ -561,6 +561,13 @@ int main() { printf("Hello, world!\n"); }
</para>
+ <para>
+ The fourth argument <varname>repo_node</varname>,
+ is the &Node; to use if it is not None when comparing &BuildInfo;.
+ This is typically only set when the target node only exists in a
+ &Repository;
+ </para>
+
<variablelist>
<varlistentry>
@@ -637,7 +644,7 @@ int main() { printf("Hello, world!\n"); }
<sconstruct>
env = Environment()
-def config_file_decider(dependency, target, prev_ni):
+def config_file_decider(dependency, target, prev_ni, repo_node=None):
import os.path
# We always have to init the .csig value...
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 965bc28..a07165a 100755
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -41,6 +41,14 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- Fix Issue #3350 - mslink failing when too many objects. This is resolved by adding TEMPFILEARGJOIN variable
which specifies what character to join all the argements output into the tempfile. The default remains a space
when mslink, msvc, or mslib tools are loaded they change the TEMPFILEARGJOIN to be a line separator (\r\n on win32)
+ - Fix performance degradation for MD5-timestamp decider. NOTE: This changes the Decider() function arguments.
+ From:
+ def my_decider(dependency, target, prev_ni):
+ To:
+ def my_decider(dependency, target, prev_ni, repo_node):
+ Where repo_node is the repository (or other) node to use to check if the node is out of date instead of dependency.
+
+
From Michael Hartmann:
- Fix handling of Visual Studio Compilers to properly reject any unknown HOST_PLATFORM or TARGET_PLATFORM
diff --git a/src/RELEASE.txt b/src/RELEASE.txt
index c95c336..9e4e314 100755
--- a/src/RELEASE.txt
+++ b/src/RELEASE.txt
@@ -41,6 +41,14 @@
CHANGED/ENHANCED EXISTING FUNCTIONALITY
+ - Fix performance degradation for MD5-timestamp decider. NOTE: This changes the Decider() function arguments.
+ From:
+ def my_decider(dependency, target, prev_ni):
+ To:
+ def my_decider(dependency, target, prev_ni, repo_node):
+ Where repo_node is the repository (or other) node to use to check if the node is out of date instead of dependency.
+
+
- Enhanced --debug=explain output. Now the separate components of the dependency list are split up
as follows:
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index 3ec8a4c..c6fc575 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -534,7 +534,7 @@ class ActionBase(object):
result = self.get_presig(target, source, env)
if not isinstance(result,(bytes, bytearray)):
- result = bytearray("",'utf-8').join([ SCons.Util.to_bytes(r) for r in result ])
+ result = bytearray(result, 'utf-8')
else:
# Make a copy and put in bytearray, without this the contents returned by get_presig
# can be changed by the logic below, appending with each call and causing very
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 395a6a7..8d06af7 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -864,18 +864,21 @@ class SubstitutionEnvironment(object):
return self
-def default_decide_source(dependency, target, prev_ni):
+def default_decide_source(dependency, target, prev_ni, repo_node=None):
f = SCons.Defaults.DefaultEnvironment().decide_source
- return f(dependency, target, prev_ni)
+ return f(dependency, target, prev_ni, repo_node)
-def default_decide_target(dependency, target, prev_ni):
+
+def default_decide_target(dependency, target, prev_ni, repo_node=None):
f = SCons.Defaults.DefaultEnvironment().decide_target
- return f(dependency, target, prev_ni)
+ return f(dependency, target, prev_ni, repo_node)
+
def default_copy_from_cache(src, dst):
f = SCons.Defaults.DefaultEnvironment().copy_from_cache
return f(src, dst)
+
class Base(SubstitutionEnvironment):
"""Base class for "real" construction Environments. These are the
primary objects used to communicate dependency and construction
@@ -1434,30 +1437,30 @@ class Base(SubstitutionEnvironment):
_warn_copy_deprecated = False
return self.Clone(*args, **kw)
- def _changed_build(self, dependency, target, prev_ni):
- if dependency.changed_state(target, prev_ni):
+ def _changed_build(self, dependency, target, prev_ni, repo_node=None):
+ if dependency.changed_state(target, prev_ni, repo_node):
return 1
- return self.decide_source(dependency, target, prev_ni)
+ return self.decide_source(dependency, target, prev_ni, repo_node)
- def _changed_content(self, dependency, target, prev_ni):
- return dependency.changed_content(target, prev_ni)
+ def _changed_content(self, dependency, target, prev_ni, repo_node=None):
+ return dependency.changed_content(target, prev_ni, repo_node)
- def _changed_source(self, dependency, target, prev_ni):
+ def _changed_source(self, dependency, target, prev_ni, repo_node=None):
target_env = dependency.get_build_env()
type = target_env.get_tgt_sig_type()
if type == 'source':
- return target_env.decide_source(dependency, target, prev_ni)
+ return target_env.decide_source(dependency, target, prev_ni, repo_node)
else:
- return target_env.decide_target(dependency, target, prev_ni)
+ return target_env.decide_target(dependency, target, prev_ni, repo_node)
- def _changed_timestamp_then_content(self, dependency, target, prev_ni):
- return dependency.changed_timestamp_then_content(target, prev_ni)
+ def _changed_timestamp_then_content(self, dependency, target, prev_ni, repo_node=None):
+ return dependency.changed_timestamp_then_content(target, prev_ni, repo_node)
- def _changed_timestamp_newer(self, dependency, target, prev_ni):
- return dependency.changed_timestamp_newer(target, prev_ni)
+ def _changed_timestamp_newer(self, dependency, target, prev_ni, repo_node=None):
+ return dependency.changed_timestamp_newer(target, prev_ni, repo_node)
- def _changed_timestamp_match(self, dependency, target, prev_ni):
- return dependency.changed_timestamp_match(target, prev_ni)
+ def _changed_timestamp_match(self, dependency, target, prev_ni, repo_node=None):
+ return dependency.changed_timestamp_match(target, prev_ni, repo_node)
def _copy_from_cache(self, src, dst):
return self.fs.copy(src, dst)
diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml
index 0982c31..1b0a04c 100644
--- a/src/engine/SCons/Environment.xml
+++ b/src/engine/SCons/Environment.xml
@@ -1213,6 +1213,17 @@ size, or content signature.
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+<term><parameter>repo_node</parameter></term>
+<listitem>
+<para>
+Use this node instead of the one specified by
+<varname>dependency</varname>
+ to determine if the dependency has changed.
+</para>
+</listitem>
+</varlistentry>
+
</variablelist>
</para>
@@ -1249,7 +1260,7 @@ Example:
</para>
<example_commands>
-def my_decider(dependency, target, prev_ni):
+def my_decider(dependency, target, prev_ni, repo_node=None):
return not os.path.exists(str(target))
env.Decider(my_decider)
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 91d349d..33105fb 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -57,7 +57,6 @@ import SCons.Util
import SCons.Warnings
from SCons.Debug import Trace
-from . import DeciderNeedsNode
print_duplicate = 0
@@ -2261,7 +2260,7 @@ class RootDir(Dir):
this directory.
"""
- __slots__ = ['_lookupDict']
+ __slots__ = ('_lookupDict', )
def __init__(self, drive, fs):
if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.RootDir')
@@ -2467,7 +2466,7 @@ class FileNodeInfo(SCons.Node.NodeInfoBase):
"""
state = getattr(self, '__dict__', {}).copy()
for obj in type(self).mro():
- for name in getattr(obj,'__slots__',()):
+ for name in getattr(obj, '__slots__', ()):
if hasattr(self, name):
state[name] = getattr(self, name)
@@ -2511,7 +2510,7 @@ class FileBuildInfo(SCons.Node.BuildInfoBase):
or count of any of these could yield writing wrong csig, and then false positive
rebuilds
"""
- __slots__ = ('dependency_map')
+ __slots__ = ['dependency_map', ]
current_version_id = 2
def __setattr__(self, key, value):
@@ -3283,14 +3282,14 @@ class File(Base):
self._memo['changed'] = has_changed
return has_changed
- def changed_content(self, target, prev_ni):
+ def changed_content(self, target, prev_ni, repo_node=None):
cur_csig = self.get_csig()
try:
return cur_csig != prev_ni.csig
except AttributeError:
return 1
- def changed_state(self, target, prev_ni):
+ def changed_state(self, target, prev_ni, repo_node=None):
return self.state != SCons.Node.up_to_date
@@ -3317,13 +3316,26 @@ class File(Base):
len(binfo.bimplicitsigs)) == 0:
return {}
-
- # store this info so we can avoid regenerating it.
- binfo.dependency_map = { str(child):signature for child, signature in zip(chain(binfo.bsources, binfo.bdepends, binfo.bimplicit),
+ binfo.dependency_map = { child:signature for child, signature in zip(chain(binfo.bsources, binfo.bdepends, binfo.bimplicit),
chain(binfo.bsourcesigs, binfo.bdependsigs, binfo.bimplicitsigs))}
return binfo.dependency_map
+ # @profile
+ def _add_strings_to_dependency_map(self, dmap):
+ """
+ In the case comparing node objects isn't sufficient, we'll add the strings for the nodes to the dependency map
+ :return:
+ """
+
+ first_string = str(next(iter(dmap)))
+
+ # print("DMAP:%s"%id(dmap))
+ if first_string not in dmap:
+ string_dict = {str(child): signature for child, signature in dmap.items()}
+ dmap.update(string_dict)
+ return dmap
+
def _get_previous_signatures(self, dmap):
"""
Return a list of corresponding csigs from previous
@@ -3342,37 +3354,62 @@ class File(Base):
if len(dmap) == 0:
if MD5_TIMESTAMP_DEBUG: print("Nothing dmap shortcutting")
return None
+ elif MD5_TIMESTAMP_DEBUG: print("len(dmap):%d"%len(dmap))
+
- if MD5_TIMESTAMP_DEBUG: print("len(dmap):%d"%len(dmap))
- # First try the simple name for node
- c_str = str(self)
- if MD5_TIMESTAMP_DEBUG: print("Checking :%s"%c_str)
- df = dmap.get(c_str, None)
+ # First try retrieving via Node
+ if MD5_TIMESTAMP_DEBUG: print("Checking if self is in map:%s id:%s type:%s"%(str(self), id(self), type(self)))
+ df = dmap.get(self, False)
if df:
return df
+ # Now check if self's repository file is in map.
+ rf = self.rfile()
+ if MD5_TIMESTAMP_DEBUG: print("Checking if self.rfile is in map:%s id:%s type:%s"%(str(rf), id(rf), type(rf)))
+ rfm = dmap.get(rf, False)
+ if rfm:
+ return rfm
+
+ # get default string for node and then also string swapping os.altsep for os.sep (/ for \)
+ c_strs = [str(self)]
+
if os.altsep:
- c_str = c_str.replace(os.sep, os.altsep)
- df = dmap.get(c_str, None)
- if MD5_TIMESTAMP_DEBUG: print("-->%s"%df)
+ c_strs.append(c_strs[0].replace(os.sep, os.altsep))
+
+ # In some cases the dependency_maps' keys are already strings check.
+ # Check if either string is now in dmap.
+ for s in c_strs:
+ if MD5_TIMESTAMP_DEBUG: print("Checking if str(self) is in map :%s" % s)
+ df = dmap.get(s, False)
if df:
return df
+ # Strings don't exist in map, add them and try again
+ # If there are no strings in this dmap, then add them.
+ # This may not be necessary, we could walk the nodes in the dmap and check each string
+ # rather than adding ALL the strings to dmap. In theory that would be n/2 vs 2n str() calls on node
+ # if not dmap.has_strings:
+ dmap = self._add_strings_to_dependency_map(dmap)
+
+ # In some cases the dependency_maps' keys are already strings check.
+ # Check if either string is now in dmap.
+ for s in c_strs:
+ if MD5_TIMESTAMP_DEBUG: print("Checking if str(self) is in map (now with strings) :%s" % s)
+ df = dmap.get(s, False)
+ if df:
+ return df
+
+ # Lastly use nodes get_path() to generate string and see if that's in dmap
if not df:
try:
# this should yield a path which matches what's in the sconsign
c_str = self.get_path()
- df = dmap.get(c_str, None)
- if MD5_TIMESTAMP_DEBUG: print("-->%s"%df)
- if df:
- return df
-
if os.altsep:
c_str = c_str.replace(os.sep, os.altsep)
- df = dmap.get(c_str, None)
- if MD5_TIMESTAMP_DEBUG: print("-->%s"%df)
- if df:
- return df
+
+ if MD5_TIMESTAMP_DEBUG: print("Checking if self.get_path is in map (now with strings) :%s" % s)
+
+ df = dmap.get(c_str, None)
except AttributeError as e:
raise FileBuildInfoFileToCsigMappingError("No mapping from file name to content signature for :%s"%c_str)
@@ -3392,16 +3429,12 @@ class File(Base):
self - dependency
target - target
prev_ni - The NodeInfo object loaded from previous builds .sconsign
- node - Node instance. This is the only changed* function which requires
- node to function. So if we detect that it's not passed.
- we throw DeciderNeedsNode, and caller should handle this and pass node.
+ node - Node instance. Check this node for file existence/timestamp
+ if specified.
Returns:
Boolean - Indicates if node(File) has changed.
"""
- if node is None:
- # We need required node argument to get BuildInfo to function
- raise DeciderNeedsNode(self.changed_timestamp_then_content)
# Now get sconsign name -> csig map and then get proper prev_ni if possible
bi = node.get_stored_info().binfo
@@ -3433,7 +3466,6 @@ class File(Base):
print("Mismatch self.changed_timestamp_match(%s, prev_ni) old:%s new:%s"%(str(target), old, new))
new_prev_ni = self._get_previous_signatures(dependency_map)
-
if not new:
try:
# NOTE: We're modifying the current node's csig in a query.
@@ -3443,13 +3475,13 @@ class File(Base):
return False
return self.changed_content(target, new_prev_ni)
- def changed_timestamp_newer(self, target, prev_ni):
+ def changed_timestamp_newer(self, target, prev_ni, repo_node=None):
try:
return self.get_timestamp() > target.get_timestamp()
except AttributeError:
return 1
- def changed_timestamp_match(self, target, prev_ni):
+ def changed_timestamp_match(self, target, prev_ni, repo_node=None):
"""
Return True if the timestamps don't match or if there is no previous timestamp
:param target:
@@ -3462,14 +3494,18 @@ class File(Base):
return 1
def is_up_to_date(self):
+ """Check for whether the Node is current
+ In all cases self is the target we're checking to see if it's up to date
+ """
+
T = 0
if T: Trace('is_up_to_date(%s):' % self)
if not self.exists():
if T: Trace(' not self.exists():')
- # The file doesn't exist locally...
+ # The file (always a target) doesn't exist locally...
r = self.rfile()
if r != self:
- # ...but there is one in a Repository...
+ # ...but there is one (always a target) in a Repository...
if not self.changed(r):
if T: Trace(' changed(%s):' % r)
# ...and it's even up-to-date...
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index aeb7092..3073d59 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -253,25 +253,10 @@ _target_from_source_map = {0 : target_from_source_none,
# used by it.
#
-
-class DeciderNeedsNode(Exception):
- """
- Indicate that the decider needs the node as well as the target and the dependency.
- Normally the node and the target are the same, but in the case of repository
- They may be different. Also the NodeInfo is retrieved from the node
- """
- def __init__(self, call_this_decider):
- """
- :param call_this_decider: to return the decider to call directly since deciders
- are called through several levels of indirection
- """
- self.decider = call_this_decider
-
-
#
# First, the single decider functions
#
-def changed_since_last_build_node(node, target, prev_ni):
+def changed_since_last_build_node(node, target, prev_ni, repo_node=None):
"""
Must be overridden in a specific subclass to return True if this
@@ -292,7 +277,7 @@ def changed_since_last_build_node(node, target, prev_ni):
raise NotImplementedError
-def changed_since_last_build_alias(node, target, prev_ni):
+def changed_since_last_build_alias(node, target, prev_ni, repo_node=None):
cur_csig = node.get_csig()
try:
return cur_csig != prev_ni.csig
@@ -300,24 +285,24 @@ def changed_since_last_build_alias(node, target, prev_ni):
return 1
-def changed_since_last_build_entry(node, target, prev_ni):
+def changed_since_last_build_entry(node, target, prev_ni, repo_node=None):
node.disambiguate()
- return _decider_map[node.changed_since_last_build](node, target, prev_ni)
+ return _decider_map[node.changed_since_last_build](node, target, prev_ni, repo_node)
-def changed_since_last_build_state_changed(node, target, prev_ni):
+def changed_since_last_build_state_changed(node, target, prev_ni, repo_node=None):
return node.state != SCons.Node.up_to_date
-def decide_source(node, target, prev_ni):
- return target.get_build_env().decide_source(node, target, prev_ni)
+def decide_source(node, target, prev_ni, repo_node=None):
+ return target.get_build_env().decide_source(node, target, prev_ni, repo_node)
-def decide_target(node, target, prev_ni):
- return target.get_build_env().decide_target(node, target, prev_ni)
+def decide_target(node, target, prev_ni, repo_node=None):
+ return target.get_build_env().decide_target(node, target, prev_ni, repo_node)
-def changed_since_last_build_python(node, target, prev_ni):
+def changed_since_last_build_python(node, target, prev_ni, repo_node=None):
cur_csig = node.get_csig()
try:
return cur_csig != prev_ni.csig
@@ -1505,17 +1490,11 @@ class Node(object, with_metaclass(NoSlotsPyPy)):
result = True
for child, prev_ni in zip(children, then):
- try:
- if _decider_map[child.changed_since_last_build](child, self, prev_ni):
- if t: Trace(': %s changed' % child)
- result = True
- except DeciderNeedsNode as e:
- if e.decider(self, prev_ni, node=node):
- if t: Trace(': %s changed' % child)
- result = True
+ if _decider_map[child.changed_since_last_build](child, self, prev_ni, node):
+ if t: Trace(': %s changed' % child)
+ result = True
if self.has_builder():
- import SCons.Util
contents = self.get_executor().get_contents()
newsig = SCons.Util.MD5signature(contents)
if bi.bactsig != newsig:
diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py
index 59afb40..71729c9 100644
--- a/src/engine/SCons/SConf.py
+++ b/src/engine/SCons/SConf.py
@@ -56,7 +56,6 @@ import SCons.Warnings
import SCons.Conftest
from SCons.Debug import Trace
-from SCons.Node import DeciderNeedsNode
# Turn off the Conftest error logging
SCons.Conftest.LogInputFiles = 0
@@ -407,12 +406,10 @@ class SConfBase(object):
# that the correct .sconsign info will get calculated
# and keep the build state consistent.
def force_build(dependency, target, prev_ni,
- env_decider=env.decide_source,
- node=None):
+ repo_node=None,
+ env_decider=env.decide_source):
try:
- env_decider(dependency, target, prev_ni)
- except DeciderNeedsNode as e:
- e.decider(target, prev_ni, node=target)
+ env_decider(dependency, target, prev_ni, repo_node)
except Exception as e:
raise e
return True
diff --git a/test/Decider/Environment.py b/test/Decider/Environment.py
index 58cd57b..4a23b5c 100644
--- a/test/Decider/Environment.py
+++ b/test/Decider/Environment.py
@@ -38,7 +38,7 @@ DefaultEnvironment(tools=[])
import os.path
env = Environment(tools=[])
env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
-def my_decider(dependency, target, prev_ni):
+def my_decider(dependency, target, prev_ni, repo_node=None):
return os.path.exists('has-changed')
env.Decider(my_decider)
""")
diff --git a/test/Decider/Node.py b/test/Decider/Node.py
index c1910de..0fa9726 100644
--- a/test/Decider/Node.py
+++ b/test/Decider/Node.py
@@ -38,7 +38,7 @@ import os.path
file_in = File('file.in')
file_out = File('file.out')
Command(file_out, file_in, Copy('$TARGET', '$SOURCE'))
-def my_decider(dependency, target, prev_ni):
+def my_decider(dependency, target, prev_ni, repo_node):
return os.path.exists('has-changed')
file_in.Decider(my_decider)
""")
diff --git a/test/Decider/default.py b/test/Decider/default.py
index 5d0a452..78f981e 100644
--- a/test/Decider/default.py
+++ b/test/Decider/default.py
@@ -36,7 +36,7 @@ test.write('SConstruct', """
DefaultEnvironment(tools=[])
import os.path
Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
-def my_decider(dependency, target, prev_ni):
+def my_decider(dependency, target, prev_ni, repo_node=None):
return os.path.exists('has-changed')
Decider(my_decider)
""")
diff --git a/test/Decider/mixed.py b/test/Decider/mixed.py
index 08daa7d..711bd2b 100644
--- a/test/Decider/mixed.py
+++ b/test/Decider/mixed.py
@@ -47,11 +47,11 @@ denv.Command('ddd.out', 'ddd.in', Copy('$TARGET', '$SOURCE'))
denv.Command('n2.out', n2_in, Copy('$TARGET', '$SOURCE'))
env.Command( 'eee.out', 'eee.in', Copy('$TARGET', '$SOURCE'))
env.Command( 'n3.out', n3_in, Copy('$TARGET', '$SOURCE'))
-def default_decider(dependency, target, prev_ni):
+def default_decider(dependency, target, prev_ni, repo_node=None):
return os.path.exists('default-has-changed')
-def env_decider(dependency, target, prev_ni):
+def env_decider(dependency, target, prev_ni, repo_node=None):
return os.path.exists('env-has-changed')
-def node_decider(dependency, target, prev_ni):
+def node_decider(dependency, target, prev_ni, repo_node=None):
return os.path.exists('node-has-changed')
Decider(default_decider)
env.Decider(env_decider)
diff --git a/test/packaging/rpm/explicit-target.py b/test/packaging/rpm/explicit-target.py
index 553ce27..48b5c83 100644
--- a/test/packaging/rpm/explicit-target.py
+++ b/test/packaging/rpm/explicit-target.py
@@ -77,7 +77,7 @@ env.Package( NAME = 'foo',
expect = """
scons: *** Setting target is not supported for rpm.
-""" + test.python_file_line(test.workpath('SConstruct'), 12)
+""" + test.python_file_line(test.workpath('SConstruct'), 23)
test.run(arguments='', status=2, stderr=expect)