Bug 922685 - Local $(foreach) variable isn't set properly; r=ted
authorGregory Szorc <gps@mozilla.com>
Tue, 01 Oct 2013 18:48:26 +0200
changeset 357 166a45b029b9262b1f633e265aad8a27cc7520a6
parent 356 498a23902260beef13c1013ef657765e74d6606f
child 358 87a4f61ed5fe7f7d14559052a58c2ac4f1b75d67
push id227
push usergszorc@mozilla.com
push dateTue, 01 Oct 2013 16:53:56 +0000
reviewersted
bugs922685
Bug 922685 - Local $(foreach) variable isn't set properly; r=ted
build/pymake/tests/foreach-local-variable.mk
pymake/data.py
pymake/functions.py
new file mode 100644
--- /dev/null
+++ b/build/pymake/tests/foreach-local-variable.mk
@@ -0,0 +1,8 @@
+# This test ensures that a local variable in a $(foreach) is bound to
+# the local value, not a global value.
+i := dummy
+
+all:
+	test "$(foreach i,foo bar,found:$(i))" = "found:foo found:bar"
+	test "$(i)" = "dummy"
+	@echo TEST-PASS
--- a/pymake/data.py
+++ b/pymake/data.py
@@ -500,23 +500,23 @@ class Variables(object):
 
             return flavor, source, val
 
         if self.parent is not None:
             return self.parent.get(name, expand)
 
         return (None, None, None)
 
-    def set(self, name, flavor, source, value):
+    def set(self, name, flavor, source, value, force=False):
         assert flavor in (self.FLAVOR_RECURSIVE, self.FLAVOR_SIMPLE)
         assert source in (self.SOURCE_OVERRIDE, self.SOURCE_COMMANDLINE, self.SOURCE_MAKEFILE, self.SOURCE_ENVIRONMENT, self.SOURCE_AUTOMATIC, self.SOURCE_IMPLICIT)
         assert isinstance(value, str_type), "expected str, got %s" % type(value)
 
         prevflavor, prevsource, prevvalue = self.get(name)
-        if prevsource is not None and source > prevsource:
+        if prevsource is not None and source > prevsource and not force:
             # TODO: give a location for this warning
             _log.info("not setting variable '%s', set by higher-priority source to value '%s'" % (name, prevvalue))
             return
 
         self._map[name] = flavor, source, value, None
 
     def append(self, name, source, value, variables, makefile):
         assert source in (self.SOURCE_OVERRIDE, self.SOURCE_MAKEFILE, self.SOURCE_AUTOMATIC)
--- a/pymake/functions.py
+++ b/pymake/functions.py
@@ -644,17 +644,21 @@ class ForEachFunction(Function):
         firstword = True
 
         for w in self._arguments[1].resolvesplit(makefile, variables, setting):
             if firstword:
                 firstword = False
             else:
                 fd.write(' ')
 
-            v.set(vname, data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, w)
+            # The $(origin) of the local variable must be "automatic" to
+            # conform with GNU make. However, automatic variables have low
+            # priority. So, we must force its assignment to occur.
+            v.set(vname, data.Variables.FLAVOR_SIMPLE,
+                    data.Variables.SOURCE_AUTOMATIC, w, force=True)
             e.resolve(makefile, v, fd, setting)
 
 class CallFunction(Function):
     name = 'call'
     minargs = 1
     maxargs = 0
 
     __slots__ = Function.__slots__