Re: undefine
Paul Smith <[email protected]>
| Newsgroups | gmane.comp.gnu.make.devel |
|---|---|
| Organization | GNU's Not Unix! |
| Message-ID | <[email protected]> |
On Mon, 2009-10-05 at 17:16 +0200, Boris Kolpackov wrote: > So I would like to implement a complimentary directive for 'define', > called 'undefine', which will allow to completely undefine a variable: > > foo := foo > define bar > bar > endef > > undefine foo > undefine bar > > $(info $(origin foo)) > $(info $(origin bar)) > > This would print: > > undefined > undefined > > I made a prototype of this feature and it gave me a 20% speedup. > > The only mildly interesting area in the implementation of undefine > is undefining of a command line variable. I think for this we should > just use the same approach as with define, i.e., it can only be done > with override: > > override undefine CFLAGS We don't really have much precedent for combining keywords like this. What if someone wrote "undefine override CFLAGS" instead? Does/should order matter here? The other thing I wonder about is using undefine in a target-specific variable context. Is this allowed? If so I suppose it undefines the variable only if it's defined in that target, and not any "global" setting of the variable? This might need a bit of detail. In a way it's a shame we don't have some concept of scope in the makefile syntax. We already have a concept of scope in variable definitions; we can push a new variable context quite easily in the code and that's done all the time. If there were syntax brought out into the makefile to push the variable scope then you could create variables local to that scope and when it ended, they would be freed up using existing features of the code. Of course this is a big change to the syntax and requires its own set of questions to be answered, such as is scope only for variables? What does it mean to define a target inside a pushed scope? etc. Today we "know" that a variable, once defined, can never disappear. I think there might be a few places in the code where we try to do some small performance improvements based on this; for example storing pointers to variable structures in global variables to allow for faster checking. You might take a look at where we use global "struct variable" variables. Also, variable names are currently stored in the string cache so they can never be removed from memory; your change might save performance but it won't help memory usage (I know that's not why you suggested it). I'm actually a bit unhappy with the string cache. I mean, the cache itself is fine but it irks me that we have three entirely separate hash tables: one for the string cache, one for files, and one for variables. There's a lot of overlap here, IMO: we look up filenames in the string cache and we also look them up in the file hash. Ditto for variables. Also, the set of strings that make up filenames and the set that make up variable names are extremely unlikely to overlap. I was toying with the idea (not for 3.82 but in the future) of creating one string cache for files and another for variable names, and combining the hash tables together. The only good way I can think of to do this is to increase the size of the hash element to be two pointers: one to the string (for the lookup etc.) and one to a struct file. If the file pointer was NULL then the file doesn't exist (we don't want to create a struct file for every name in the filename hash). If we allowed undefining of variables then doing this for variables would be problematic since we'd lose the pointer to the variable name; if someone wrote: foo = bar undefine foo foo = bar then "foo" would be added to the variable string cache twice. Maybe that's not a big deal. Now I'm just babbling :-)