Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: do not rely on gn_helpers in GN build #51439

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deps/ngtcp2/unofficial.gni
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# building official binaries.
# Please edit the gyp files if you are making changes to build system.

import("//node/node.gni")
import("../../node.gni")

# The actual configurations are put inside a template in unofficial.gni to
# prevent accidental edits from contributors.
Expand Down
128 changes: 109 additions & 19 deletions tools/gypi_to_gn.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,29 +102,119 @@
from __future__ import absolute_import
from __future__ import print_function
from optparse import OptionParser
import os
import sys


# Look for standalone GN distribution.
def FindGNPath():
for i in os.environ['PATH'].split(os.pathsep):
if i.rstrip(os.sep).endswith('gn'):
return i
return None
# This function is copied from build/gn_helpers.py in Chromium.
def ToGNString(value, pretty=False):
"""Returns a stringified GN equivalent of a Python value.

Args:
value: The Python value to convert.
pretty: Whether to pretty print. If true, then non-empty lists are rendered
recursively with one item per line, with indents. Otherwise lists are
rendered without new line.
Returns:
The stringified GN equivalent to |value|.

try:
# May already be in the import path.
import gn_helpers
except ImportError:
# Add src/build to import path.
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir))
sys.path.append(os.path.join(src_dir, 'build'))
if FindGNPath():
sys.path.append(os.path.join(FindGNPath(), 'build'))
import gn_helpers
Raises:
ValueError: |value| cannot be printed to GN.
"""

# Emits all output tokens without intervening whitespaces.
def GenerateTokens(v, level):
if isinstance(v, str):
yield '"' + ''.join(TranslateToGnChars(v)) + '"'

elif isinstance(v, bool):
yield 'true' if v else 'false'

elif isinstance(v, int):
yield str(v)

elif isinstance(v, list):
yield '['
for i, item in enumerate(v):
if i > 0:
yield ','
for tok in GenerateTokens(item, level + 1):
yield tok
yield ']'

elif isinstance(v, dict):
if level > 0:
yield '{'
for key in sorted(v):
if not isinstance(key, str):
raise ValueError('Dictionary key is not a string.')
if not key or key[0].isdigit() or not key.replace('_', '').isalnum():
raise ValueError('Dictionary key is not a valid GN identifier.')
yield key # No quotations.
yield '='
for tok in GenerateTokens(v[key], level + 1):
yield tok
if level > 0:
yield '}'

else: # Not supporting float: Add only when needed.
raise ValueError('Unsupported type when printing to GN.')

can_start = lambda tok: tok and tok not in ',}]='
can_end = lambda tok: tok and tok not in ',{[='

# Adds whitespaces, trying to keep everything (except dicts) in 1 line.
def PlainGlue(gen):
prev_tok = None
for i, tok in enumerate(gen):
if i > 0:
if can_end(prev_tok) and can_start(tok):
yield '\n' # New dict item.
elif prev_tok == '[' and tok == ']':
yield ' ' # Special case for [].
elif tok != ',':
yield ' '
yield tok
prev_tok = tok

# Adds whitespaces so non-empty lists can span multiple lines, with indent.
def PrettyGlue(gen):
prev_tok = None
level = 0
for i, tok in enumerate(gen):
if i > 0:
if can_end(prev_tok) and can_start(tok):
yield '\n' + ' ' * level # New dict item.
elif tok == '=' or prev_tok in '=':
yield ' ' # Separator before and after '=', on same line.
if tok in ']}':
level -= 1
# Exclude '[]' and '{}' cases.
if int(prev_tok == '[') + int(tok == ']') == 1 or \
int(prev_tok == '{') + int(tok == '}') == 1:
yield '\n' + ' ' * level
yield tok
if tok in '[{':
level += 1
if tok == ',':
yield '\n' + ' ' * level
prev_tok = tok

token_gen = GenerateTokens(value, 0)
ret = ''.join((PrettyGlue if pretty else PlainGlue)(token_gen))
# Add terminating '\n' for dict |value| or multi-line output.
if isinstance(value, dict) or '\n' in ret:
return ret + '\n'
return ret


def TranslateToGnChars(s):
for code in s.encode('utf-8'):
if code in (34, 36, 92): # For '"', '$', or '\\'.
yield '\\' + chr(code)
elif 32 <= code < 127:
yield chr(code)
else:
yield '$0x%02X' % code


def LoadPythonDictionary(path):
Expand Down Expand Up @@ -234,7 +324,7 @@ def main():
else:
gn_dict[gn_key] = data[key]

print(gn_helpers.ToGNString(DeduplicateLists(gn_dict)))
print(ToGNString(DeduplicateLists(gn_dict)))

if __name__ == '__main__':
try:
Expand Down