diff --git a/tools/precise_build/precise_build.py b/tools/precise_build/precise_build.py new file mode 100644 index 0000000000000000000000000000000000000000..a27a6df8a0440cafd7dfe3a6b9c099a26dfd4386 --- /dev/null +++ b/tools/precise_build/precise_build.py @@ -0,0 +1,186 @@ +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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. +# + +import os +import subprocess +import time +import argparse +import shlex +import signal +import sys +import re +import tempfile +import shutil +import json + + +def get_target(target): + if target.startswith("//"): + return target[2:] + else: + return target + + +def execute_build_command(command, use_shell=False): + process = subprocess.Popen( + command, + shell=use_shell, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT + ) + + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + if output: + print(output.strip()) + + return_code = process.poll() + print(f"build finish,return code is: {return_code}") + return return_code == 0 + + +def monitor_file_and_stop(shell_script_path, target_file, shell_args=None, + use_shell=False): + + if isinstance(shell_args, str): + command = [shell_script_path] + shlex.split(shell_args) + elif shell_args: + command = [shell_script_path] + shell_args + else: + command = [shell_script_path] + + command += ["--build-only-gn"] + + execute_build_command(command, use_shell=use_shell) + + file_detected = False + + while True: + if os.path.exists(target_file): + file_detected = True + break + sleep(0.5) + + if file_detected: + if os.stat(target_file).st_size == 0: + print("No changes to the unittest detected, skipping compilation directly.") + sys.exit() + command.remove("--build-only-gn") + command.extend(["--build-target", "precise_module_build"]) + return execute_build_command(command, use_shell=use_shell) + + return False + + +def process_changes(): + change_info = read_json("change_info.json") + openharmony_fields = [v["name"] for v in change_info.values() if "name" in v] + change_files = [] + file_operations = { + "added": lambda x: x, + "rename": lambda x: [item for pair in x for item in pair], + "modified": lambda x: x, + "deleted": lambda x: x + } + gn_files, c_files, h_files = [], [], [] + file_type_map = { + 'h': h_files, + 'hh': h_files, + 'hpp': h_files, + 'gn': gn_files, + 'c': c_files, + 'cpp': c_files, + 'cc': c_files, + 'cxx': c_files, + } + + for key, value in change_info.items(): + changed_files = value.get("changed_file_list", {}) + for operation, processor in file_operations.items(): + if operation not in changed_files: + print(f"unknown file operation: {operation}") + continue + for modified_file in processor(changed_files[operation]): + target_list = file_type_map.get(get_file_extension(modified_file)) + if target_list is not None: + target_list.append("//" + os.path.join(key, modified_file)) + + modified_files = { + "h_file": h_files, + "c_file": c_files, + "gn_file": gn_files, + "gn_module":[] + } + + with open('modify_files.json', 'w') as json_file: + json.dump(modified_files, json_file, indent=4) + return ( + [os.path.join(self.ace_root, f) for f in change_files], + openharmony_fields + ) + +def get_file_extension(filename): + if '.' in filename: + return filename.split(".")[-1] + else: + return None + +def read_json(path): + try: + with open(path, 'r', encoding='utf-8') as f: + return json.load(f) + except Exception as e: + return {} + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + add_help=False + ) + + parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, + help='display help information and exit') + parser.add_argument('-s', '--script', required=True, + help='the path to the shell script to be executed') + parser.add_argument('-f', '--file', required=True, + help='the path of the target file to be monitored') + parser.add_argument('--use-shell', action='store_true', + help='execute commands using the shell (handle complex commands)') + parser.add_argument('shell_args', nargs=argparse.REMAINDER, + help='parameters passed to the shell script (after --)') + + args = parser.parse_args() + process_changes() + shell_args = [] + if args.shell_args: + try: + sep_index = args.shell_args.index("--") + shell_args = args.shell_args[sep_index + 1:] + except ValueError: + shell_args = args.shell_args + + success = monitor_file_and_stop( + shell_script_path=args.script, + target_file=args.file, + shell_args=shell_args, + use_shell=args.use_shell, + ) + + exit(0 if success else 1) diff --git a/tools/precise_build/precise_build_config.json b/tools/precise_build/precise_build_config.json new file mode 100644 index 0000000000000000000000000000000000000000..cc2fb89be6440863270ab224d5b52c77a369a1bc --- /dev/null +++ b/tools/precise_build/precise_build_config.json @@ -0,0 +1,79 @@ +{ + "h_file_depth": 3, + "c_file_depth": 3, + "gn_file_depth": 3, + "gn_module_depth": 3, + "test_only": true, + "target_type_list": [ + "executable" + ], + "ignore_list": [ + "//base/hiviewdfx/hiview/plugins/eventlogger/test:EventloggerPluginTest", + "//base/inputmethod/imf/test/fuzztest/systemabilitystubfuzztest:ImsCmdLastFuzzTest", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_base_test", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_device_service_test", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_helper_test", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_service_test", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_soft_bus_test", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_subscriber_test", + "//base/notification/distributed_notification_service/services/distributed/test/unittest:distributed_tlvbox_test", + "//base/print/print_fwk/test/unittest/service_test:scan_service_test", + "//base/web/webview/test/unittest/ohos_adapter/ohos_image_adapter:ohos_image_decoder_adapter_test", + "//foundation/ability/ability_runtime/test/unittest/frameworks_kits_ability_native_test:ability_impl_active_test", + "//foundation/ability/dmsfwk/frameworks/native/distributed_extension/test/unittest/distributed_extension:distributed_connection_test", + "//foundation/ability/form_fwk/test/unittest/fms_form_set_next_refresh_test:FmsFormSetNextRefreshTest", + "//foundation/arkui/ace_engine/test/unittest/core/accessibility:accessibility_adapter_test_web_ng", + "//foundation/arkui/ace_engine/test/unittest/core/base:force_split_base_test_ng", + "//foundation/arkui/ace_engine/test/unittest/core/base:view_abstract_test_resetposition_ng", + "//foundation/arkui/ace_engine/test/unittest/core/base:view_partial_update_model_test_ng", + "//foundation/arkui/ace_engine/test/unittest/core/image:ImageCompressorTest", + "//foundation/arkui/ace_engine/test/unittest/core/image:ImageProviderTest", + "//foundation/arkui/ace_engine/test/unittest/core/image:image_cache_test", + "//foundation/arkui/ace_engine/test/unittest/core/pattern/stage:force_split_stage_test_ng", + "//foundation/communication/netmanager_base/test/netstatsmanager/unittest/net_stats_manager_test:net_stats_cached_service_test", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteServGetDataTest", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteServGetLocalDataTest", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteServInterfaceTest", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteServNotifyTest", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteServSetDataTest", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteServSubscribeTest", + "//foundation/graphic/graphic_2d/rosen/test/render_service/render_service_client/unittest/feature:RSCompositeLayerUtilsTest", + "//foundation/multimedia/image_framework/frameworks/innerkitsimpl/test:picture_ext_test", + "//foundation/multimedia/audio_framework/services/audio_service/test/unittest:audio_process_in_client_second_unit_test", + "//foundation/multimodalinput/input/service:EventHandlerEXTest", + "//foundation/multimodalinput/input/service:TwoFingerLongTouchTest", + "//foundation/multimodalinput/input/service/crown_transform_processor/test:CrownTransformProcessorExTest", + "//foundation/multimodalinput/input/service/mouse_event_normalize/test:MouseTransformProcessorMockTest", + "//foundation/multimodalinput/input/service/touch_event_normalize/test:GestureTransformTest", + "//foundation/multimodalinput/input/service/touch_event_normalize/test:TabletToolTranformTest", + "//foundation/multimodalinput/input/service/touch_event_normalize/test:TouchPadTransformProcessorMockTest", + "//foundation/multimodalinput/input/service/touch_event_normalize/test:TouchTransformProcessorTestWithMock", + "//foundation/multimodalinput/input/service/touch_event_normalize/test:TouchpadGestureTest", + "//foundation/multimodalinput/input/service:InterceptorExTest", + "//foundation/multimodalinput/input/service:KeyGestureManagerEXTest", + "//foundation/multimodalinput/input/test/fuzztest/setcustomcursor_fuzzer:SetCustomCursorFuzzTest", + "//foundation/multimodalinput/input/test/fuzztest/stubsetmouseicon_fuzzer:StubSetMouseIconFuzzTest", + "//foundation/window/window_manager/test/systemtest/dms:dms_screen_gamut_test", + "//foundation/window/window_manager/window_scene/test/dms_unittest:ws_screen_session_dumper_test", + "//foundation/window/window_manager/window_scene/test/dms_unittest:ws_screen_session_manager_client_test", + "//foundation/window/window_manager/window_scene/test/dms_unittest:ws_screen_session_manager_proxy_test", + "//foundation/window/window_manager/window_scene/test/dms_unittest:ws_screen_session_manager_test", + "//foundation/window/window_manager/window_scene/test/dms_unittest:ws_screen_session_manager_test2", + "//foundation/window/window_manager/window_scene/test/unittest:ws_session_test", + "//foundation/window/window_manager/window_scene/test/unittest:ws_scene_session_lifecycle_test", + "//foundation/window/window_manager/window_scene/test/unittest:ws_scene_session_manager_one_test", + "//foundation/window/window_manager/wmserver/test/unittest:wmserver_avoid_area_controller_test", + "//foundation/window/window_manager/wmserver/test/unittest:wmserver_window_manager_service_test", + "//foundation/window/window_manager/wmserver/test/unittest:wmserver_window_node_test", + "//foundation/window/window_manager/wmserver/test/unittest:wmserver_window_pair_test", + "//foundation/window/window_manager/wm/test/unittest:wm_window_adapter_lite_test", + "//foundation/window/window_manager/wm/test/unittest:wm_window_manager_lite_test" + ], + "max_range_list": [], + "modify_files_path": "modify_files.json", + "precise_result_path": "precise_build_result.txt", + "precise_log_path": "out/rk3568/precise_build_log.txt", + "root_target": [ + "//build/core/gn:build_all_test_pkg" + ] +} \ No newline at end of file