|
|
|
# Copyright 2024 The Chromium Authors. All rights reserved.
|
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
"""This provides an easy way to access args.gn."""
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
def _find_root(output_dir):
|
|
|
|
curdir = output_dir
|
|
|
|
while True:
|
|
|
|
if os.path.exists(os.path.join(curdir, ".gn")):
|
|
|
|
return curdir
|
|
|
|
nextdir = os.path.join(curdir, "..")
|
|
|
|
if os.path.abspath(curdir) == os.path.abspath(nextdir):
|
|
|
|
raise Exception(
|
|
|
|
'Could not find checkout in any parent of the current path.')
|
|
|
|
curdir = nextdir
|
|
|
|
|
|
|
|
|
|
|
|
def _gn_lines(output_dir, path):
|
|
|
|
"""
|
|
|
|
Generator function that returns args.gn lines one at a time, following
|
|
|
|
import directives as needed.
|
|
|
|
"""
|
|
|
|
import_re = re.compile(r'\s*import\("(.*)"\)')
|
|
|
|
with open(path, encoding="utf-8") as f:
|
|
|
|
for line in f:
|
|
|
|
match = import_re.match(line)
|
|
|
|
if match:
|
|
|
|
raw_import_path = match.groups()[0]
|
|
|
|
if raw_import_path[:2] == "//":
|
|
|
|
import_path = os.path.normpath(
|
|
|
|
os.path.join(_find_root(output_dir),
|
|
|
|
raw_import_path[2:]))
|
|
|
|
elif raw_import_path.startswith('/'):
|
|
|
|
# GN uses "/"-prefix as absolute path,
|
|
|
|
# https://gn.googlesource.com/gn/+/main/docs/reference.md#labels
|
|
|
|
# e.g.
|
|
|
|
# /usr/local/foo:bar
|
|
|
|
# /C:/Program Files/MyLibs:bar
|
|
|
|
# but Win32's absolute path doesn't have "/"-prefix.
|
|
|
|
if sys.platform.startswith('win32'):
|
|
|
|
import_path = raw_import_path[1:]
|
|
|
|
else:
|
|
|
|
import_path = raw_import_path
|
|
|
|
if not os.path.isabs(import_path):
|
|
|
|
raise Exception('Wrong absolute path for import %s' %
|
|
|
|
raw_import_path)
|
|
|
|
else:
|
|
|
|
if os.path.isabs(raw_import_path):
|
|
|
|
raise Execption(
|
|
|
|
'Absolute path "%s" should start with "/" in GN' %
|
|
|
|
raw_import_path)
|
|
|
|
import_path = os.path.normpath(
|
|
|
|
os.path.join(os.path.dirname(path), raw_import_path))
|
|
|
|
yield from _gn_lines(output_dir, import_path)
|
|
|
|
else:
|
|
|
|
yield line
|
|
|
|
|
|
|
|
|
|
|
|
def _path(output_dir):
|
|
|
|
return os.path.join(output_dir, "args.gn")
|
|
|
|
|
|
|
|
|
|
|
|
def exists(output_dir):
|
|
|
|
"""Checks args.gn exists in output_dir."""
|
|
|
|
return os.path.exists(_path(output_dir))
|
|
|
|
|
|
|
|
|
|
|
|
def lines(output_dir):
|
|
|
|
"""Generator of args.gn lines. comment is removed."""
|
|
|
|
if not exists(output_dir):
|
|
|
|
return
|
|
|
|
for line in _gn_lines(output_dir, _path(output_dir)):
|
|
|
|
line_without_comment = line.split("#")[0]
|
|
|
|
yield line_without_comment
|
|
|
|
|
|
|
|
|
|
|
|
_gn_arg_pattern = re.compile(r"(^|\s*)([^=\s]*)\s*=\s*(\S*)\s*$")
|
|
|
|
|
|
|
|
|
|
|
|
def args(output_dir):
|
|
|
|
"""Generator of args.gn's key,value pair."""
|
|
|
|
for line in lines(output_dir):
|
|
|
|
m = _gn_arg_pattern.match(line)
|
|
|
|
if not m:
|
|
|
|
continue
|
|
|
|
yield (m.group(2), m.group(3))
|