Skip to content

Commit 86ac787

Browse files
zcbenzmarco-ippolito
authored andcommitted
build: do not rely on gn_helpers in GN build
PR-URL: #51439 Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent 5911731 commit 86ac787

File tree

2 files changed

+110
-20
lines changed

2 files changed

+110
-20
lines changed

deps/ngtcp2/unofficial.gni

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# building official binaries.
33
# Please edit the gyp files if you are making changes to build system.
44

5-
import("//node/node.gni")
5+
import("../../node.gni")
66

77
# The actual configurations are put inside a template in unofficial.gni to
88
# prevent accidental edits from contributors.

tools/gypi_to_gn.py

+109-19
Original file line numberDiff line numberDiff line change
@@ -102,29 +102,119 @@
102102
from __future__ import absolute_import
103103
from __future__ import print_function
104104
from optparse import OptionParser
105-
import os
106105
import sys
107106

108107

109-
# Look for standalone GN distribution.
110-
def FindGNPath():
111-
for i in os.environ['PATH'].split(os.pathsep):
112-
if i.rstrip(os.sep).endswith('gn'):
113-
return i
114-
return None
108+
# This function is copied from build/gn_helpers.py in Chromium.
109+
def ToGNString(value, pretty=False):
110+
"""Returns a stringified GN equivalent of a Python value.
115111
112+
Args:
113+
value: The Python value to convert.
114+
pretty: Whether to pretty print. If true, then non-empty lists are rendered
115+
recursively with one item per line, with indents. Otherwise lists are
116+
rendered without new line.
117+
Returns:
118+
The stringified GN equivalent to |value|.
116119
117-
try:
118-
# May already be in the import path.
119-
import gn_helpers
120-
except ImportError:
121-
# Add src/build to import path.
122-
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
123-
os.pardir, os.pardir))
124-
sys.path.append(os.path.join(src_dir, 'build'))
125-
if FindGNPath():
126-
sys.path.append(os.path.join(FindGNPath(), 'build'))
127-
import gn_helpers
120+
Raises:
121+
ValueError: |value| cannot be printed to GN.
122+
"""
123+
124+
# Emits all output tokens without intervening whitespaces.
125+
def GenerateTokens(v, level):
126+
if isinstance(v, str):
127+
yield '"' + ''.join(TranslateToGnChars(v)) + '"'
128+
129+
elif isinstance(v, bool):
130+
yield 'true' if v else 'false'
131+
132+
elif isinstance(v, int):
133+
yield str(v)
134+
135+
elif isinstance(v, list):
136+
yield '['
137+
for i, item in enumerate(v):
138+
if i > 0:
139+
yield ','
140+
for tok in GenerateTokens(item, level + 1):
141+
yield tok
142+
yield ']'
143+
144+
elif isinstance(v, dict):
145+
if level > 0:
146+
yield '{'
147+
for key in sorted(v):
148+
if not isinstance(key, str):
149+
raise ValueError('Dictionary key is not a string.')
150+
if not key or key[0].isdigit() or not key.replace('_', '').isalnum():
151+
raise ValueError('Dictionary key is not a valid GN identifier.')
152+
yield key # No quotations.
153+
yield '='
154+
for tok in GenerateTokens(v[key], level + 1):
155+
yield tok
156+
if level > 0:
157+
yield '}'
158+
159+
else: # Not supporting float: Add only when needed.
160+
raise ValueError('Unsupported type when printing to GN.')
161+
162+
can_start = lambda tok: tok and tok not in ',}]='
163+
can_end = lambda tok: tok and tok not in ',{[='
164+
165+
# Adds whitespaces, trying to keep everything (except dicts) in 1 line.
166+
def PlainGlue(gen):
167+
prev_tok = None
168+
for i, tok in enumerate(gen):
169+
if i > 0:
170+
if can_end(prev_tok) and can_start(tok):
171+
yield '\n' # New dict item.
172+
elif prev_tok == '[' and tok == ']':
173+
yield ' ' # Special case for [].
174+
elif tok != ',':
175+
yield ' '
176+
yield tok
177+
prev_tok = tok
178+
179+
# Adds whitespaces so non-empty lists can span multiple lines, with indent.
180+
def PrettyGlue(gen):
181+
prev_tok = None
182+
level = 0
183+
for i, tok in enumerate(gen):
184+
if i > 0:
185+
if can_end(prev_tok) and can_start(tok):
186+
yield '\n' + ' ' * level # New dict item.
187+
elif tok == '=' or prev_tok in '=':
188+
yield ' ' # Separator before and after '=', on same line.
189+
if tok in ']}':
190+
level -= 1
191+
# Exclude '[]' and '{}' cases.
192+
if int(prev_tok == '[') + int(tok == ']') == 1 or \
193+
int(prev_tok == '{') + int(tok == '}') == 1:
194+
yield '\n' + ' ' * level
195+
yield tok
196+
if tok in '[{':
197+
level += 1
198+
if tok == ',':
199+
yield '\n' + ' ' * level
200+
prev_tok = tok
201+
202+
token_gen = GenerateTokens(value, 0)
203+
ret = ''.join((PrettyGlue if pretty else PlainGlue)(token_gen))
204+
# Add terminating '\n' for dict |value| or multi-line output.
205+
if isinstance(value, dict) or '\n' in ret:
206+
return ret + '\n'
207+
return ret
208+
209+
210+
def TranslateToGnChars(s):
211+
for code in s.encode('utf-8'):
212+
if code in (34, 36, 92): # For '"', '$', or '\\'.
213+
yield '\\' + chr(code)
214+
elif 32 <= code < 127:
215+
yield chr(code)
216+
else:
217+
yield '$0x%02X' % code
128218

129219

130220
def LoadPythonDictionary(path):
@@ -234,7 +324,7 @@ def main():
234324
else:
235325
gn_dict[gn_key] = data[key]
236326

237-
print(gn_helpers.ToGNString(DeduplicateLists(gn_dict)))
327+
print(ToGNString(DeduplicateLists(gn_dict)))
238328

239329
if __name__ == '__main__':
240330
try:

0 commit comments

Comments
 (0)