Strange behaviour with variable default values in gyp

145 views
Skip to first unread message

Andrew Walbran

unread,
Apr 3, 2014, 10:11:28 AM4/3/14
to gyp-de...@googlegroups.com
I am trying to create a gyp file for a library where a certain variable is set to a default value, and used in other variables, but clients using the library can override the variable and the value they set will be used to set other variables appropriately. However, it appears that variable default values (set with %) cannot be used to in other variable definitions. Why is this?

As a minimal test case, this works:
variables: {
'foo': 'bar',
'baz': '<(foo)',
}

But this fails, with an error like "gyp: Undefined variable foo in test.gyp":
variables: {
'foo%': 'bar',
'baz': '<(foo)',
}

And so does this:
variables: {
'foo%': 'bar',
'baz%': '<(foo)',
}

Sylvain Defresne

unread,
Apr 3, 2014, 10:24:42 AM4/3/14
to Andrew Walbran, gyp-developer
I don't know why, but as a workaround, you can do (this is what Chrome uses):

'variables': {
  'variables': {
    'foo%': 'bar',
  },
  'foo%': '<(foo)',
  'baz%': '<(foo)',
},
-- Sylvain



--

---
You received this message because you are subscribed to the Google Groups "gyp-developer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gyp-develope...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Torne (Richard Coles)

unread,
Apr 3, 2014, 11:10:31 AM4/3/14
to Sylvain Defresne, Andrew Walbran, gyp-developer
Use the workaround Sylvain suggested. Unfortunately I *do* know why, and the explanation will probably make you really sad; the quick summary is that all the variables' values are expanded *first*, before anything goes to look for the %. At the time the variable expansions are done, you haven't defined a variable called foo, you have defined one called foo%, and it will remain that way until later. :/
--
Torne (Richard Coles)
to...@google.com

Dirk Pranke

unread,
Apr 4, 2014, 7:28:31 PM4/4/14
to Torne (Richard Coles), Sylvain Defresne, Andrew Walbran, gyp-developer
I don't know if this is actually the case, but my first thought on looking at this is that when GYP reads the files, it's actually just slurping them in as blocks of Python. So, that's a python dict, and therefore the keys in that dict are not actually processed in a particular order, and so relying on foo to be set before baz would be dodgy.

The nested dict mechanism thus makes more sense as a workaround - since 'variables' are dealt with before the other keys, it is a way to force ordering of an otherwise unordered thing.

(Torne's explanation is probably the right one, but perhaps mine gives you some sort of intuitive backing for it ...)

-- Dirk

Andrew Walbran

unread,
Apr 7, 2014, 6:36:01 AM4/7/14
to Dirk Pranke, Torne (Richard Coles), Sylvain Defresne, gyp-developer
On 5 April 2014 00:28, Dirk Pranke <dpr...@chromium.org> wrote:
I don't know if this is actually the case, but my first thought on looking at this is that when GYP reads the files, it's actually just slurping them in as blocks of Python. So, that's a python dict, and therefore the keys in that dict are not actually processed in a particular order, and so relying on foo to be set before baz would be dodgy.

The nested dict mechanism thus makes more sense as a workaround - since 'variables' are dealt with before the other keys, it is a way to force ordering of an otherwise unordered thing.

I don't think ordering within the dict is the issue here. This works equally well:
variables: {
'foo': 'bar',
'baz': '<(foo)',
}

Torne's description of the issue kind of makes sense, but I do not see why it could not easily be fixed  by making the variable expansion process look for foo% if it cannot find foo.

Torne (Richard Coles)

unread,
Apr 7, 2014, 7:47:12 AM4/7/14
to Andrew Walbran, Dirk Pranke, Sylvain Defresne, gyp-developer
On 7 April 2014 11:36, Andrew Walbran <qwa...@google.com> wrote:
On 5 April 2014 00:28, Dirk Pranke <dpr...@chromium.org> wrote:
I don't know if this is actually the case, but my first thought on looking at this is that when GYP reads the files, it's actually just slurping them in as blocks of Python. So, that's a python dict, and therefore the keys in that dict are not actually processed in a particular order, and so relying on foo to be set before baz would be dodgy.

They're not processed in any particular order, but that doesn't matter because it refers back to the dictionary to find the values, specifically to make expansion at the same level work. You can demonstrate by defining:

variables: {
  'foo': '<(bar)',
  'bar': '<(foo)',
}

and watching gyp crash when it expands this recursively forever until it hits the python recursion limit ;)
 
The nested dict mechanism thus makes more sense as a workaround - since 'variables' are dealt with before the other keys, it is a way to force ordering of an otherwise unordered thing.

I don't think ordering within the dict is the issue here. This works equally well:
variables: {
'foo': 'bar',
'baz': '<(foo)',
}

Torne's description of the issue kind of makes sense, but I do not see why it could not easily be fixed  by making the variable expansion process look for foo% if it cannot find foo.

It might be possible to fix it to do that, but my experience trying to fix things like this leads me to assume that changing anything will break something else in some unexpected way. gyp's phases of processing and sequences of operations are really complicated and *something* in chromium's gyp files appears to depend on every single tiny detail, no matter how unintentional. You're welcome to try ;)

I don't think % is the only case, also. I think you'll get the same problem with variables that are lists, when using things like foo+ to insert at the start of the list, etc.
Reply all
Reply to author
Forward
0 new messages