blob: 1a094b6c4fc8a71612426b89e1e70aae2de53473 [file]
from argparse import ArgumentParser
import json
import os
from pathlib import Path
import subprocess
import sys
from typing import Dict, List
def source_to_targets( ANDROID_BUILD_TOP: Path, source_file: Path):
"""Get list of Soong targets for a pathfile"""
target = []
MAPPING_PATH = (
ANDROID_BUILD_TOP / "out" / "soong" / "rust-target-mapping.json"
)
try:
with open(MAPPING_PATH, "r") as file:
for entry in json.load(file):
if str(source_file).startswith(entry["source_dir"]):
check = entry["check_target"]
product = entry["TARGET_PRODUCT"]
build_variant= entry["TARGET_BUILD_VARIANT"]
target.append((check, product, build_variant))
return target
except FileNotFoundError:
raise Exception(
'The mapping file is not here, please run "SOONG_GEN_RUST_PROJECT=1'
f' m nothing"'
)
def run_targets(targets):
"""Build all the Soong output targets"""
soong_ui_path = ANDROID_BUILD_TOP / "build" / "soong" / "soong_ui.bash"
soong_ui_cmd = [
str(soong_ui_path),
# This will build using the target(s) name.
"--make-mode",
# This will skip the kati, kati ninja and ninja build steps
"--soong-only",
]
for (check, product, build_variant) in targets:
cmd = soong_ui_cmd + [str(check)]
env= {
"TARGET_PRODUCT": product,
# default is used here to run subprocess
# unable to be delivered by Soong or IDE
"TARGET_RELEASE": "trunk_staging",
"TARGET_BUILD_VARIANT": build_variant,
}
result = subprocess.run(
cmd,
env=env,
stdout=sys.stderr,
stderr=sys.stderr,
)
if result.returncode < 0:
raise Exception(f"Command failed. Killed by signal {result.returncode}")
def gather_output(ANDROID_BUILD_TOP: Path, check_targets):
"""Read out the generated output files and print results"""
# We use the error flag when it expects the message flag to be used
# so we need to augment the result by adding the reason field to the JSON
diagnostics = set()
for (clippy_error_file,_,_) in check_targets:
path = str(ANDROID_BUILD_TOP) + "/" + clippy_error_file + ".error"
try:
with open(path, "r") as file:
for line in file:
diagnostics.add(line.strip())
except FileNotFoundError:
continue
for diagnostic in diagnostics:
print(diagnostic)
print(diagnostic, file=sys.stderr)
parser = ArgumentParser(
description="Rust-analyzer integration for rustc/clippy-driver binary"
)
parser.add_argument(
"source_file",
type=Path,
help="The absolute path of the Rust source file to run this check on",
)
args = parser.parse_args()
exe_path = Path(__file__).resolve()
ANDROID_BUILD_TOP = exe_path.parents[3]
source_file = args.source_file.relative_to(ANDROID_BUILD_TOP)
targets = source_to_targets(ANDROID_BUILD_TOP, source_file)
run_targets(targets)
gather_output(ANDROID_BUILD_TOP, targets)