Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/scripts/ai/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 10 kB image not shown  

Quelle  soong_only_analyzer.py

  Sprache: Python
 

#!/usr/bin/env python3
#
# Copyright (C) 2025 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
A user-friendly wrapper for the 'aninja' tool to inspect the Android build graph.

The Android Open Source Project (AOSP) uses the Soong build system, which generates
'build.ninja' file. The 'ninja' build tool then executes the build steps
defined in this file. 'aninja' is a tool provided with AOSP to query this
generated Ninja file, allowing developers to inspect dependencies, commands, and
the overall build graph.

This script simplifies common 'aninja' queries into easy-to-use modes. It is
designed to be invoked programmatically (e.g., by an LLM) or manually to help
diagnose build failures, understand artifact dependencies, and analyze how
specific files are built.
"""

import argparse
import os
import subprocess
import sys

# --- Helper Functions ---

def run_command(command, **kwargs):
    """
    Executes a shell command safely and returns its standard output.

    This function is a robust wrapper around Python's subprocess module. It
    captures output, checks for errors, and provides detailed error messages
    if the command fails. This is crucial for reliable execution in an
    automated environment.

    Args:
        command: A list of strings representing the command and its arguments
                 (e.g., ['ls''-l']).
        **kwargs: Additional keyword arguments to pass to subprocess.run().

    Returns:
        The standard output of the command as a single, stripped string.

    Raises:
        SystemExit: If the command is not found or fails to execute, the script
                    will terminate with a non-zero exit code.
    """
    try:
        process = subprocess.run(
            command,
            capture_output=True,
            text=True,
            check=True,
            **kwargs
        )
        return process.stdout.strip()
    except FileNotFoundError:
        print(f"Error: Command '{command[0]}' not found. Is it in your PATH?", file=sys.stderr)
        sys.exit(1)
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {' '.join(command)}", file=sys.stderr)
        print(f"Return code: {e.returncode}", file=sys.stderr)
        print(f"Stdout:\n{e.stdout}", file=sys.stderr)
        print(f"Stderr:\n{e.stderr}", file=sys.stderr)
        sys.exit(1)

def get_product_config(variable_name):
    """
    Retrieves a product configuration variable from the Soong build system.

    AOSP builds are highly configurable via product variables like TARGET_PRODUCT
    and TARGET_DEVICE. This function provides a canonical way to fetch these
    values by invoking the build system's own variable dumping mechanism.

    Args:
        variable_name: The name of the variable to retrieve (e.g., 'TARGET_PRODUCT').

    Returns:
        The value of the specified configuration variable as a string.
    """
    soong_ui_path = 'build/soong/soong_ui.bash'
    if not os.path.exists(soong_ui_path):
        print(f"Error: '{soong_ui_path}' not found.", file=sys.stderr)
        print("Please run this script from the root of the AOSP source tree.", file=sys.stderr)
        sys.exit(1)

    return run_command([soong_ui_path, '--dumpvar-mode', variable_name])

# --- Sub-command Handlers ---

def handle_target_files_inputs(args):
    """
    Implements the 'target_files_inputs' mode.

    This function finds the list of inputs for the 'target-files.zip' package,
    which is a critical intermediate used for generating system images and OTA
    updates. It can operate in two modes: one for Soong-only inputs and one
    for the final, mixed-build system inputs.
    """
    print("�� Analyzing target files inputs...")
    target_path = ""
    if args.soong_only:
        # Soong-only mode: useful for debugging issues within Soong itself.
        product_name = get_product_config('TARGET_PRODUCT')
        search_dir = f'out/soong/.intermediates/build/soong/fsgen/{product_name}_generated_device'
        if not os.path.isdir(search_dir):
            print(f"Error: Directory not found: {search_dir}", file=sys.stderr)
            sys.exit(1)

        find_cmd = ['find', search_dir, '-name''target_files_dir.stamp']
        found_paths = run_command(find_cmd)
        if not found_paths:
            print(f"Error: 'target_files_dir.stamp' not found in {search_dir}", file=sys.stderr)
            sys.exit(1)
        target_path = found_paths.split('\n')[0]
        print(f"Found Soong-only target files stamp at: {target_path}")
    else:
        # Default mode: inspects the final artifact list from the mixed build.
        device = get_product_config('TARGET_DEVICE')
        product_name = get_product_config('TARGET_PRODUCT')
        target_path = (f'out/target/product/{device}/obj/PACKAGING/'
                       f'target_files_intermediates/{product_name}-target_files.zip.list')
        print(f"Using mixed build system target files list at: {target_path}")

    if not os.path.exists(target_path):
        print(f"Error: Target path does not exist: {target_path}", file=sys.stderr)
        print("Have you run a build first (e.g., 'm nothing')?", file=sys.stderr)
        sys.exit(1)

    aninja_cmd = ['aninja''-t''query', target_path]
    result = run_command(aninja_cmd)
    print("\n--- aninja query result ---")
    print(result)
    print("--- end of result ---")


def handle_commands(args):
    """
    Implements the 'commands' mode.

    This function retrieves the command-line rule used to build a specified
    artifact. This is extremely useful for seeing the exact compiler flags,
    script arguments, or other options used to generate a file.
    """
    print(f"�� Getting last {args.n} build commands for target: {args.target}")
    if not os.path.exists(args.target):
        print(f"Error: Target path does not exist: {args.target}", file=sys.stderr)
        sys.exit(1)

    aninja_cmd = ['aninja''-t''commands', args.target]
    full_output = run_command(aninja_cmd)
    lines = full_output.strip().split('\n')
    last_n_lines = lines[-args.n:]

    print(f"\n--- Last {len(last_n_lines)} of {len(lines)} commands ---")
    print('\n'.join(last_n_lines))
    print("--- end of result ---")


def handle_query(args):
    """
    Implements the 'query' mode.

    This function shows the direct inputs and outputs for a given build target.
    It helps answer the question: "What files are needed to build this target,
    and what files are produced by the same build rule?" This is fundamental for
    tracing build dependencies.
    """
    print(f"�� Querying inputs and outputs for target: {args.target}")
    if not os.path.exists(args.target):
        print(f"Error: Target path does not exist: {args.target}", file=sys.stderr)
        sys.exit(1)

    aninja_cmd = ['aninja''-t''query', args.target]
    result = run_command(aninja_cmd)
    print("\n--- aninja query result ---")
    print(result)
    print("--- end of result ---")

# --- Main Execution ---

def main():
    """Parses command-line arguments and dispatches to the correct handler."""
    parser = argparse.ArgumentParser(
        description="A wrapper for 'aninja' to inspect AOSP build failures. Run from the root of your AOSP checkout.",
        formatter_class=argparse.RawTextHelpFormatter
    )
    subparsers = parser.add_subparsers(dest='command', required=True, help='Available commands')

    # 'target_files_inputs' sub-command
    parser_tfi = subparsers.add_parser(
        'target_files_inputs',
        help="Shows the full list of files that go into making the system image and OTA package.",
        description=(
            "ACTION: Inspects the inputs for the 'target-files.zip' archive.\n"
            "USE CASE: This is crucial for debugging packaging issues or understanding what is included in a final device build.\n"
            "By default, it shows the query output of the soong plus make build.\n"
            "The --soong-only flag shows the query output of the 'target-files.zip' of soong only build."
        )
    )
    parser_tfi.add_argument(
        '--soong-only',
        action='store_true',
        help='Inspect the soong only build dependency stamp instead of the final artifact list from the soong plus make build.'
    )
    parser_tfi.set_defaults(func=handle_target_files_inputs)

    # 'commands' sub-command
    parser_commands = subparsers.add_parser(
        'commands',
        help="Shows the exact command-line rule used to build a file.",
        description=(
            "ACTION: Prints the build rule (e.g., compiler or script call) that produces the specified target file.\n"
            "USE CASE: Use this to check the exact compiler flags, paths, and arguments used to build an artifact. Indispensable for debugging compilation errors."
        )
    )
    parser_commands.add_argument(
        '--target',
        required=True,
        help='The path to the target build artifact (e.g., out/soong/.../libc.so).'
    )
    parser_commands.add_argument(
        '-n',
        type=int,
        default=10,
        help='The number of last lines of the command to print. Some commands are long scripts (default: 10).'
    )
    parser_commands.set_defaults(func=handle_commands)

    # 'query' sub-command
    parser_query = subparsers.add_parser(
        'query',
        help="Shows the direct inputs and outputs for a specific build target.",
        description=(
            "ACTION: Shows the immediate inputs (dependencies) and outputs for a specific build target.\n"
            "USE CASE: This is the primary tool for dependency graph analysis. Use it to find out why a module is being rebuilt or to trace the source of a required file."
        )
    )
    parser_query.add_argument(
        '--target',
        required=True,
        help='The path to the target build artifact (e.g., out/soong/.../libc.so).'
    )
    parser_query.set_defaults(func=handle_query)

    args = parser.parse_args()
    args.func(args)

if __name__ == '__main__':
    main()

Messung V0.5 in Prozent
C=88 H=92 G=89

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet am  2026-06-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.