diff options
author | Gary Oberbrunner <garyo@oberbrunner.com> | 2013-11-02 20:27:42 (GMT) |
---|---|---|
committer | Gary Oberbrunner <garyo@oberbrunner.com> | 2013-11-02 20:27:42 (GMT) |
commit | cc202cdc15cd156c458ad9a2f94b2e9145be3ec2 (patch) | |
tree | 69c4681b26c8c9d2e94d7c7d24bbe764ec19e4ad /src | |
parent | 6660a1b75c021994ccf352bb5314935d533b7994 (diff) | |
parent | 54eaf41e5eadd05c73b0ad21223f73c4ed47684f (diff) | |
download | SCons-cc202cdc15cd156c458ad9a2f94b2e9145be3ec2.zip SCons-cc202cdc15cd156c458ad9a2f94b2e9145be3ec2.tar.gz SCons-cc202cdc15cd156c458ad9a2f94b2e9145be3ec2.tar.bz2 |
Merge pull request #88: various usability enhancements
* Allow multiple --debug= values
* Add support for a readonly cache (--cache-readonly)
* Always print stats if requested
* Generally try harder to print out a message on build errors
Diffstat (limited to 'src')
-rw-r--r-- | src/engine/SCons/Environment.py | 34 | ||||
-rw-r--r-- | src/engine/SCons/EnvironmentTests.py | 31 | ||||
-rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 13 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 16 | ||||
-rw-r--r-- | src/engine/SCons/Script/Main.py | 1 | ||||
-rw-r--r-- | src/engine/SCons/Script/Main.xml | 21 | ||||
-rw-r--r-- | src/engine/SCons/Warnings.py | 3 |
7 files changed, 99 insertions, 20 deletions
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index ca5df58..3e499b6 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -705,7 +705,7 @@ class SubstitutionEnvironment(object): # -symbolic (linker global binding) # -R dir (deprecated linker rpath) # IBM compilers may also accept -qframeworkdir=foo - + params = shlex.split(arg) append_next_arg_to = None # for multi-word args for arg in params: @@ -795,7 +795,7 @@ class SubstitutionEnvironment(object): append_next_arg_to = arg else: dict['CCFLAGS'].append(arg) - + for arg in flags: do_parse(arg) return dict @@ -859,7 +859,7 @@ class SubstitutionEnvironment(object): # def MergeShellPaths(self, args, prepend=1): # """ -# Merge the dict in args into the shell environment in env['ENV']. +# Merge the dict in args into the shell environment in env['ENV']. # Shell path elements are appended or prepended according to prepend. # Uses Pre/AppendENVPath, so it always appends or prepends uniquely. @@ -962,14 +962,14 @@ class Base(SubstitutionEnvironment): platform = SCons.Platform.Platform(platform) self._dict['PLATFORM'] = str(platform) platform(self) - + self._dict['HOST_OS'] = self._dict.get('HOST_OS',None) self._dict['HOST_ARCH'] = self._dict.get('HOST_ARCH',None) - + # Now set defaults for TARGET_{OS|ARCH} self._dict['TARGET_OS'] = self._dict.get('TARGET_OS',None) self._dict['TARGET_ARCH'] = self._dict.get('TARGET_ARCH',None) - + # Apply the passed-in and customizable variables to the # environment before calling the tools, because they may use @@ -1158,7 +1158,7 @@ class Base(SubstitutionEnvironment): # "continue" statements whenever we finish processing an item, # but Python 1.5.2 apparently doesn't let you use "continue" # within try:-except: blocks, so we have to nest our code. - try: + try: if key == 'CPPDEFINES' and SCons.Util.is_String(self._dict[key]): self._dict[key] = [self._dict[key]] orig = self._dict[key] @@ -1209,7 +1209,7 @@ class Base(SubstitutionEnvironment): orig = orig.items() orig += val self._dict[key] = orig - else: + else: for v in val: orig[v] = None else: @@ -1232,7 +1232,7 @@ class Base(SubstitutionEnvironment): path = str(self.fs.Dir(path)) return path - def AppendENVPath(self, name, newpath, envname = 'ENV', + def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, delete_existing=1): """Append path elements to the path 'name' in the 'ENV' dictionary for this environment. Will only add any particular @@ -1290,7 +1290,7 @@ class Base(SubstitutionEnvironment): dk = dk.items() elif SCons.Util.is_String(dk): dk = [(dk,)] - else: + else: tmp = [] for i in dk: if SCons.Util.is_List(i): @@ -1335,7 +1335,7 @@ class Base(SubstitutionEnvironment): dk = filter(lambda x, val=val: x not in val, dk) self._dict[key] = dk + val else: - dk = [x for x in dk if x not in val] + dk = [x for x in dk if x not in val] self._dict[key] = dk + val else: # By elimination, val is not a list. Since dk is a @@ -1382,7 +1382,7 @@ class Base(SubstitutionEnvironment): builders = self._dict['BUILDERS'] except KeyError: pass - + clone = copy.copy(self) # BUILDERS is not safe to do a simple copy clone._dict = semi_deepcopy_dict(self._dict, ['BUILDERS']) @@ -1410,7 +1410,7 @@ class Base(SubstitutionEnvironment): apply_tools(clone, tools, toolpath) # apply them again in case the tools overwrote them - clone.Replace(**new) + clone.Replace(**new) # Finally, apply any flags to be merged in if parse_flags: clone.MergeFlags(parse_flags) @@ -2087,6 +2087,14 @@ class Base(SubstitutionEnvironment): t.set_precious() return tlist + def Pseudo(self, *targets): + tlist = [] + for t in targets: + tlist.extend(self.arg2nodes(t, self.fs.Entry)) + for t in tlist: + t.set_pseudo() + return tlist + def Repository(self, *dirs, **kw): dirs = self.arg2nodes(list(dirs), self.fs.Dir) self.fs.Repository(*dirs, **kw) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index db788dc..7fa8af4 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -170,7 +170,7 @@ class TestEnvironmentFixture(object): single_source = 1) kw['BUILDERS'] = {'Object' : static_obj} static_obj.add_action('.cpp', 'fake action') - + env = Environment(*args, **kw) return env @@ -1722,7 +1722,7 @@ def exists(env): assert env['DDD1'] == ['c', 'a', 'b'], env['DDD1'] # a & b move to end env.AppendUnique(DDD1 = ['e','f', 'e'], delete_existing=1) assert env['DDD1'] == ['c', 'a', 'b', 'f', 'e'], env['DDD1'] # add last - + env['CLVar'] = CLVar([]) env.AppendUnique(CLVar = 'bar') result = env['CLVar'] @@ -2030,7 +2030,7 @@ def generate(env): try: save_command = [] - env.backtick = my_backtick(save_command, + env.backtick = my_backtick(save_command, "-I/usr/include/fum -I bar -X\n" + \ "-L/usr/fax -L foo -lxxx -l yyy " + \ "-Wa,-as -Wl,-link " + \ @@ -2375,7 +2375,7 @@ f5: \ env.PrependUnique(DDD1 = ['a','c'], delete_existing=1) assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # a & c move to front env.PrependUnique(DDD1 = ['d','e','d'], delete_existing=1) - assert env['DDD1'] == ['d', 'e', 'a', 'c', 'b'], env['DDD1'] + assert env['DDD1'] == ['d', 'e', 'a', 'c', 'b'], env['DDD1'] env['CLVar'] = CLVar([]) @@ -3125,6 +3125,29 @@ def generate(env): assert t[4].path == 'p_ggg' assert t[4].precious + def test_Pseudo(self): + """Test the Pseudo() method""" + env = self.TestEnvironment(FOO='ggg', BAR='hhh') + env.Dir('p_hhhb') + env.File('p_d') + t = env.Pseudo('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') + + assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__ + assert t[0].path == 'p_a' + assert t[0].pseudo + assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__ + assert t[1].path == 'p_hhhb' + assert t[1].pseudo + assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__ + assert t[2].path == 'p_c' + assert t[2].pseudo + assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__ + assert t[3].path == 'p_d' + assert t[3].pseudo + assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__ + assert t[4].path == 'p_ggg' + assert t[4].pseudo + def test_Repository(self): """Test the Repository() method.""" class MyFS(object): diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index a301654..076ca65 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -693,6 +693,15 @@ class NodeTestCase(unittest.TestCase): node.set_precious(7) assert node.precious == 7 + def test_set_pseudo(self): + """Test setting a Node's pseudo value + """ + node = SCons.Node.Node() + node.set_pseudo() + assert node.pseudo + node.set_pseudo(False) + assert not node.pseudo + def test_exists(self): """Test evaluating whether a Node exists. """ @@ -954,7 +963,7 @@ class NodeTestCase(unittest.TestCase): self.source_scanner = scanner builder = Builder2(ts1) - + targets = builder([source]) s = targets[0].get_source_scanner(source) assert s is ts1, s @@ -967,7 +976,7 @@ class NodeTestCase(unittest.TestCase): builder = Builder1(env=Environment(SCANNERS = [ts3])) targets = builder([source]) - + s = targets[0].get_source_scanner(source) assert s is ts3, s diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index c114281..d353245 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -58,6 +58,10 @@ from SCons.Debug import Trace def classname(obj): return str(obj.__class__).split('.')[-1] +# Set to false if we're doing a dry run. There's more than one of these +# little treats +do_store_info = True + # Node states # # These are in "priority" order, so that the maximum value for any @@ -215,6 +219,7 @@ class Node(object): self.env = None self.state = no_state self.precious = None + self.pseudo = False self.noclean = 0 self.nocache = 0 self.cached = 0 # is this node pulled from cache? @@ -386,6 +391,13 @@ class Node(object): self.clear() + if self.pseudo: + if self.exists(): + raise SCons.Errors.UserError("Pseudo target " + str(self) + " must not exist") + else: + if not self.exists() and do_store_info: + SCons.Warnings.warn(SCons.Warnings.TargetNotBuiltWarning, + "Cannot find target " + str(self) + " after building") self.ninfo.update(self) def visited(self): @@ -789,6 +801,10 @@ class Node(object): """Set the Node's precious value.""" self.precious = precious + def set_pseudo(self, pseudo = True): + """Set the Node's precious value.""" + self.pseudo = pseudo + def set_noclean(self, noclean = 1): """Set the Node's noclean value.""" # Make sure noclean is an integer so the --debug=stree diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 9083b8e..a81ac98 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -1086,6 +1086,7 @@ def _build_targets(fs, options, targets, target_top): SCons.Action.print_actions = not options.silent SCons.Action.execute_actions = not options.no_exec SCons.Node.FS.do_store_info = not options.no_exec + SCons.Node.do_store_info = not options.no_exec SCons.SConf.dryrun = options.no_exec if options.diskcheck: diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index b582e0d..147e778 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -685,6 +685,25 @@ Multiple targets can be passed in to a single call to </summary> </scons_function> +<scons_function name="Pseudo"> +<arguments> +(target, ...) +</arguments> +<summary> +<para> +This indicates that each given +<varname>target</varname> +should not be created by the build rule, and if the target is created, +an error will be generated. This is similar to the gnu make .PHONY +target. However, in the vast majority of cases, an +&f-Alias; +is more appropriate. + +Multiple targets can be passed in to a single call to +&f-Pseudo;. +</para> +</summary> +</scons_function> <scons_function name="SetOption"> <arguments> (name, value) @@ -788,4 +807,4 @@ SetOption('max_drift', 1) </summary> </scons_function> -</sconsdoc>
\ No newline at end of file +</sconsdoc> diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index a260c4a..ca6acee 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -42,6 +42,9 @@ class WarningOnByDefault(Warning): # NOTE: If you add a new warning class, add it to the man page, too! +class TargetNotBuiltWarning(Warning): # Should go to OnByDefault + pass + class CacheWriteErrorWarning(Warning): pass |