Skip to content

Commit f487772

Browse files
committed
build: do not rely on gn_helpers in GN build
1 parent af8ba37 commit f487772

File tree

2 files changed

+118
-21
lines changed

2 files changed

+118
-21
lines changed

deps/ngtcp2/unofficial.gni

Lines changed: 1 addition & 1 deletion
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

Lines changed: 117 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -106,25 +106,122 @@
106106
import sys
107107

108108

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

129226

130227
def LoadPythonDictionary(path):
@@ -234,7 +331,7 @@ def main():
234331
else:
235332
gn_dict[gn_key] = data[key]
236333

237-
print(gn_helpers.ToGNString(DeduplicateLists(gn_dict)))
334+
print(ToGNString(DeduplicateLists(gn_dict)))
238335

239336
if __name__ == '__main__':
240337
try:

0 commit comments

Comments
 (0)