@@ -82,6 +82,7 @@ def value(self):
8282
8383 def set_value (self , value , pos ):
8484 # TODO add a stack where the values get changed
85+ logger .debug ("overwrite value name=%s at pos=%r" , self .name , pos )
8586 self .pos = pos
8687 self ._value = value
8788
@@ -151,9 +152,21 @@ def sanity(self):
151152# -- GNU Make manual Version 4.3 Jan 2020
152153class DefaultEntry (Entry ):
153154 origin = "default"
154- never_export = True
155155
156- class CallbackEntry (DefaultEntry ):
156+ # An Immutable Entry is one where we cannot change the value BUT we can
157+ # completely change the entry. For example, .VARIABLES has a special meaning in
158+ # Make (a string containing names of all the defined variables) BUT we can do something bone-headed like:
159+ #
160+ # .VARIABLES:=foo # kill the .VARIABLES variable
161+ #
162+ # When am Immutable Entry is updated, the set_value() will throw an exception.
163+ # The Symbol Table add() method will then create a new entry instead.
164+ #
165+ class ImmutablemixIn :
166+ def set_value (self , value , pos ):
167+ raise ValueError ("cannot update CallbackEntry name=%s" % self .name )
168+
169+ class CallbackEntry (ImmutablemixIn , DefaultEntry ):
157170 # Some built-in variables have complex requirements that can't be stored as
158171 # a simple string in the symbol table. For example .VARIABLES returns a
159172 # list of the variables currently defined.
@@ -167,12 +180,13 @@ def __init__(self, name, callback_fn):
167180 def eval (self , symbol_table ):
168181 return self ._value (symbol_table )
169182
183+
170184# Environment Variables are higher precedence than File variables. But Command
171185# Line args are higher precedence than Environment Variables.
172186# "By default, only variables that came from the environment or the
173187# command line are passed to recursive invocations."
174188# -- GNU Make manual Version 4.3 Jan 2020
175- class EnvVarEntry (Entry ):
189+ class EnvVarEntry (ImmutablemixIn , Entry ):
176190 origin = "environment"
177191
178192 def __init__ (self , name , value ):
@@ -188,16 +202,13 @@ def __init__(self, name, value):
188202# "By default, only variables that came from the environment or the
189203# command line are passed to recursive invocations."
190204# -- GNU Make manual Version 4.3 Jan 2020
191- class CommandLineEntry (Entry ):
205+ class CommandLineEntry (ImmutablemixIn , Entry ):
192206 origin = "command line"
193207
194208 def __init__ (self , name , value ):
195209 super ().__init__ (name ,value )
196210 self .set_export (Export .SUBMAKE )
197211
198- def set_value (self , value , pos ):
199- pass
200-
201212
202213class AutomaticEntry (Entry ):
203214 origin = "automatic"
@@ -312,29 +323,49 @@ def add(self, name, value, pos=None):
312323
313324 try :
314325 entry = self .symbols [name ]
315- logger .debug ("overwrite value name=%s at pos=%r" , entry .name , pos )
316326 except KeyError :
317- entry = None
318-
319- # if we didn't find it, make it
320- if self .command_line_flag :
321- # this flag is a weird hack to support vars created by eval()'ing
322- # expressions from the command line
323- new_entry = CommandLineEntry (name , value )
324- # command line vars are always exported until explicitly unexported
327+ entry = None
328+
329+ if entry is None :
330+ # easy case: if we didn't find it, make it
331+ if self .command_line_flag :
332+ # this flag is a weird hack to support vars created by eval()'ing
333+ # expressions from the command line
334+ # - command line vars are always exported until explicitly
335+ # marked 'unexport'
336+ # - command line vars cannot be overwritten by file variables
337+ # except by the 'override' directive (not yet implemented)
338+ entry = CommandLineEntry (name , value )
339+ else :
340+ if pos and pos [0 ] == "@defaults" :
341+ entry = DefaultEntry (name , value , pos )
342+ else :
343+ entry = FileEntry (name , value , pos )
344+ entry .set_export (self .export_default_value )
345+
346+ self ._add_entry (entry )
325347 else :
326- # command line > file
327- if isinstance (entry ,CommandLineEntry ):
328- return
329-
330- new_entry = FileEntry (name , value , pos )
331- new_entry .set_export (self .export_default_value )
332-
333- # XXX not sure read-only is a good idea yet
334- # if entry.read_only:
335- # raise PermissionDenied(name)
336-
337- self ._add_entry (new_entry )
348+ overwrite = False
349+ try :
350+ entry .set_value (value , pos )
351+ except ValueError :
352+ overwrite = True
353+
354+ if overwrite :
355+ # Found an immutable variable that refuses to be overwritten.
356+ # So (maybe) create a new one.
357+ overwrite_entry = None
358+ if self .command_line_flag :
359+ # command line entry can happily override command line entry
360+ overwrite_entry = CommandLineEntry (name , value )
361+ else :
362+ # do not overwrite a command line entry when we're
363+ # no longer processing command line variables
364+ if not isinstance (entry , CommandLineEntry ):
365+ overwrite_entry = FileEntry (name , value , pos )
366+
367+ if overwrite_entry :
368+ self ._add_entry (overwrite_entry )
338369
339370 def add_automatic (self , name , value , pos ):
340371 entry = AutomaticEntry (name , value , pos )
0 commit comments