[go: nahoru, domu]

Android: Refactor dep_operations -> //build/gn_ast

These scripts belong in //build and should not have deps on //tools.
This CL is more of a simple move, subsequent CLs may combine some common
code with gn_ast.py.

This refactor also makes dep_operations.py easier to use via the
shortcut: //build/gn_editor

Bug: 1486020
Fixed: 1486020
Change-Id: I3d186616517a9c53addb0ac2960c1af047d4bfe5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4885960
Auto-Submit: Peter Wen <wnwen@chromium.org>
Reviewed-by: Andrew Grieve <agrieve@chromium.org>
Commit-Queue: Peter Wen <wnwen@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1201207}
diff --git a/build/android/gyp/bytecode_processor.py b/build/android/gyp/bytecode_processor.py
index 421b54e..e6c41c3 100755
--- a/build/android/gyp/bytecode_processor.py
+++ b/build/android/gyp/bytecode_processor.py
@@ -21,8 +21,8 @@
 import action_helpers  # build_utils adds //build to sys.path.
 
 _SRC_PATH = pathlib.Path(build_utils.DIR_SOURCE_ROOT).resolve()
-sys.path.append(str(_SRC_PATH / 'tools/android/modularization/gn'))
-from dep_operations import NO_VALID_GN_STR
+sys.path.append(str(_SRC_PATH / 'build/gn_ast'))
+from gn_editor import NO_VALID_GN_STR
 
 
 def _ShouldIgnoreDep(dep_name: str):
diff --git a/build/android/gyp/bytecode_processor.pydeps b/build/android/gyp/bytecode_processor.pydeps
index 78db0c4..a729800 100644
--- a/build/android/gyp/bytecode_processor.pydeps
+++ b/build/android/gyp/bytecode_processor.pydeps
@@ -9,13 +9,10 @@
 ../../../third_party/catapult/devil/devil/android/sdk/version_codes.py
 ../../../third_party/catapult/devil/devil/constants/__init__.py
 ../../../third_party/catapult/devil/devil/constants/exit_codes.py
-../../../tools/android/modularization/gn/dep_operations.py
-../../../tools/android/modularization/gn/json_gn_editor.py
-../../../tools/android/modularization/gn/utils.py
-../../../tools/android/python_utils/__init__.py
-../../../tools/android/python_utils/git_metadata_utils.py
-../../../tools/android/python_utils/subprocess_utils.py
 ../../action_helpers.py
+../../gn_ast/gn_editor.py
+../../gn_ast/json_gn_editor.py
+../../gn_ast/utils.py
 ../../gn_helpers.py
 ../list_java_targets.py
 ../pylib/__init__.py
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index 752aa21..938c7041 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -224,6 +224,7 @@
   logging.info('CheckOutput: %s', ' '.join(args))
   child = subprocess.Popen(args,
       stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env)
+
   stdout, stderr = child.communicate()
 
   # For Python3 only:
diff --git a/build/android/gyp/util/dep_utils.py b/build/android/gyp/util/dep_utils.py
index c849df6..cbf8937 100644
--- a/build/android/gyp/util/dep_utils.py
+++ b/build/android/gyp/util/dep_utils.py
@@ -255,8 +255,8 @@
 
   build_file_path = GnTargetToBuildFilePath(gn_target)
   return [
-      'tools/android/modularization/gn/dep_operations.py', 'add', '--quiet',
-      '--file', build_file_path, '--target', gn_target, '--deps'
+      'build/gn_editor', 'add', '--quiet', '--file', build_file_path,
+      '--target', gn_target, '--deps'
   ] + missing_deps
 
 
diff --git a/tools/android/modularization/gn/dep_operations.py b/build/gn_ast/gn_editor.py
similarity index 95%
rename from tools/android/modularization/gn/dep_operations.py
rename to build/gn_ast/gn_editor.py
index 797a4d0..3b63ba8 100755
--- a/tools/android/modularization/gn/dep_operations.py
+++ b/build/gn_ast/gn_editor.py
@@ -18,15 +18,19 @@
 import json_gn_editor
 import utils
 
-_TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve().parents[2]
-if str(_TOOLS_ANDROID_PATH) not in sys.path:
-    sys.path.append(str(_TOOLS_ANDROID_PATH))
-from python_utils import git_metadata_utils, subprocess_utils
+_SRC_PATH = pathlib.Path(__file__).resolve().parents[2]
 
-_SRC_PATH = git_metadata_utils.get_chromium_src_path()
-sys.path.append(str(_SRC_PATH / 'build' / 'android'))
+_BUILD_ANDROID_PATH = _SRC_PATH / 'build/android'
+if str(_BUILD_ANDROID_PATH) not in sys.path:
+    sys.path.append(str(_BUILD_ANDROID_PATH))
 from pylib import constants
 
+_BUILD_ANDROID_GYP_PATH = _SRC_PATH / 'build/android/gyp'
+if str(_BUILD_ANDROID_GYP_PATH) not in sys.path:
+    sys.path.append(str(_BUILD_ANDROID_GYP_PATH))
+
+from util import build_utils
+
 _GIT_IGNORE_STR = '(git ignored file) '
 
 NO_VALID_GN_STR = 'No valid GN files found after filtering.'
@@ -177,13 +181,13 @@
         # TODO: Ensure that the build server is not running.
 
     logging.info(f'Running "gn gen" in output directory: {out_dir}')
-    subprocess_utils.run_command(['gn', 'gen', '-C', out_dir, '--ide=json'])
+    build_utils.CheckOutput(['gn', 'gen', '-C', out_dir, '--ide=json'])
 
     if args.all_java_deps:
         assert not args.dep, '--all-java-target does not support passing deps.'
         assert args.file, '--all-java-target requires passing --file.'
         logging.info(f'Finding java deps under {out_dir}.')
-        all_java_deps = subprocess_utils.run_command([
+        all_java_deps = build_utils.CheckOutput([
             str(_SRC_PATH / 'build' / 'android' / 'list_java_targets.py'),
             '--gn-labels', '-C', out_dir
         ]).split('\n')
@@ -264,7 +268,7 @@
 
 def main():
     parser = argparse.ArgumentParser(
-        description='Add or remove deps programatically.')
+        prog='gn_editor', description='Add or remove deps programatically.')
 
     common_args_parser = argparse.ArgumentParser(add_help=False)
     common_args_parser.add_argument(
@@ -287,7 +291,7 @@
         help='Skip files before this build file path (debugging).')
 
     subparsers = parser.add_subparsers(
-        help='Use subcommand -h to see full usage.')
+        required=True, help='Use subcommand -h to see full usage.')
 
     add_parser = subparsers.add_parser(
         'add',
@@ -375,7 +379,7 @@
     logging.basicConfig(
         level=level, format='%(levelname).1s %(relativeCreated)7d %(message)s')
 
-    root = git_metadata_utils.get_chromium_src_path()
+    root = _SRC_PATH
     if args.file:
         build_filepaths = [os.path.relpath(args.file, root)]
     else:
diff --git a/tools/android/modularization/gn/json_gn_editor.py b/build/gn_ast/json_gn_editor.py
similarity index 96%
rename from tools/android/modularization/gn/json_gn_editor.py
rename to build/gn_ast/json_gn_editor.py
index ce67e86..abafb63 100644
--- a/tools/android/modularization/gn/json_gn_editor.py
+++ b/build/gn_ast/json_gn_editor.py
@@ -20,12 +20,13 @@
 
 from typing import Dict, Iterator, List, Optional, Tuple
 
-_TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve().parents[2]
-if str(_TOOLS_ANDROID_PATH) not in sys.path:
-    sys.path.insert(0, str(_TOOLS_ANDROID_PATH))
-from python_utils import git_metadata_utils, subprocess_utils
+_SRC_PATH = pathlib.Path(__file__).resolve().parents[2]
 
-_SRC_PATH = git_metadata_utils.get_chromium_src_path()
+_BUILD_ANDROID_GYP_PATH = _SRC_PATH / 'build/android/gyp'
+if str(_BUILD_ANDROID_GYP_PATH) not in sys.path:
+    sys.path.append(str(_BUILD_ANDROID_GYP_PATH))
+
+from util import build_utils
 
 # Refer to parse_tree.cc for GN AST implementation details:
 # https://gn.googlesource.com/gn/+/refs/heads/main/src/gn/parse_tree.cc
@@ -52,10 +53,10 @@
             f.write(contents)
 
 
-def _build_targets_output(out_dir: str,
-                          targets: List[str],
-                          should_print: Optional[bool] = None
-                          ) -> Optional[str]:
+def _build_targets_output(
+        out_dir: str,
+        targets: List[str],
+        should_print: Optional[bool] = None) -> Optional[str]:
     env = os.environ.copy()
     if should_print is None:
         should_print = logging.getLogger().isEnabledFor(logging.DEBUG)
@@ -102,7 +103,7 @@
 
 
 def _generate_project_json_content(out_dir: str) -> str:
-    subprocess_utils.run_command(['gn', 'gen', '--ide=json', out_dir])
+    build_utils.CheckOutput(['gn', 'gen', '--ide=json', out_dir])
     with open(os.path.join(out_dir, 'project.json')) as f:
         return f.read()
 
@@ -118,7 +119,6 @@
 
 class BuildFile:
     """Represents the contents of a BUILD.gn file."""
-
     def __init__(self,
                  build_gn_path: str,
                  root_gn_path: pathlib.Path,
@@ -131,7 +131,7 @@
         self._skip_write_content = dryrun
 
     def __enter__(self):
-        output = subprocess_utils.run_command(
+        output = build_utils.CheckOutput(
             ['gn', 'format', '--dump-tree=json', self._full_path])
         self._content = json.loads(output)
         self._original_content = json.dumps(self._content)
@@ -141,7 +141,6 @@
         if not self._skip_write_content:
             self.write_content_to_file()
 
-
     # See: https://gist.github.com/sgraham/bd9ffee312f307d5f417019a9c0f0777
     def _find_all(self, match_fn):
         results = []
@@ -226,7 +225,6 @@
         return name
 
     def _find_all_list_assignments(self):
-
         def match_list_assignments(node):
             r"""Matches and returns the list being assigned.
 
@@ -558,6 +556,8 @@
     def write_content_to_file(self) -> None:
         current_content = json.dumps(self._content)
         if current_content != self._original_content:
-            subprocess_utils.run_command(
+            subprocess.run(
                 ['gn', 'format', '--read-tree=json', self._full_path],
-                cmd_input=current_content)
+                text=True,
+                check=True,
+                input=current_content)
diff --git a/tools/android/modularization/gn/json_gn_editor_test.py b/build/gn_ast/json_gn_editor_test.py
similarity index 100%
rename from tools/android/modularization/gn/json_gn_editor_test.py
rename to build/gn_ast/json_gn_editor_test.py
diff --git a/tools/android/modularization/gn/utils.py b/build/gn_ast/utils.py
similarity index 75%
rename from tools/android/modularization/gn/utils.py
rename to build/gn_ast/utils.py
index aa4049e3..05fe41b 100644
--- a/tools/android/modularization/gn/utils.py
+++ b/build/gn_ast/utils.py
@@ -6,12 +6,7 @@
 import logging
 import os
 import pathlib
-import sys
-
-_TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve().parents[2]
-if str(_TOOLS_ANDROID_PATH) not in sys.path:
-    sys.path.append(str(_TOOLS_ANDROID_PATH))
-from python_utils import subprocess_utils
+import subprocess
 
 # These paths should be relative to repository root.
 _BAD_FILES = [
@@ -35,6 +30,6 @@
 def is_git_ignored(root: pathlib.Path, filepath: str) -> bool:
     # The command git check-ignore exits with 0 if the path is ignored, 1 if it
     # is not ignored.
-    exit_code = subprocess_utils.run_command(
-        ['git', 'check-ignore', '-q', filepath], cwd=root, exitcode_only=True)
+    exit_code = subprocess.run(['git', 'check-ignore', '-q', filepath],
+                               cwd=root).returncode
     return exit_code == 0
diff --git a/build/gn_editor b/build/gn_editor
new file mode 100755
index 0000000..ecf86e8
--- /dev/null
+++ b/build/gn_editor
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+base_dir=$(dirname "$0")
+
+exec python3 "$base_dir/gn_ast/gn_editor.py" "$@"