15f9996aaSopenharmony_ci#!/usr/bin/env python3
25f9996aaSopenharmony_ci# coding: utf-8
35f9996aaSopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd.
45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License.
65f9996aaSopenharmony_ci# You may obtain a copy of the License at
75f9996aaSopenharmony_ci#
85f9996aaSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
95f9996aaSopenharmony_ci#
105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and
145f9996aaSopenharmony_ci# limitations under the License.
155f9996aaSopenharmony_ci
165f9996aaSopenharmony_ciimport os
175f9996aaSopenharmony_ciimport subprocess
185f9996aaSopenharmony_ci
195f9996aaSopenharmony_ci
205f9996aaSopenharmony_cidef run_cmd(cmd: str):
215f9996aaSopenharmony_ci    res = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE,
225f9996aaSopenharmony_ci                           stderr=subprocess.PIPE)
235f9996aaSopenharmony_ci    sout, serr = res.communicate(timeout=60)
245f9996aaSopenharmony_ci
255f9996aaSopenharmony_ci    return res.pid, res.returncode, sout, serr
265f9996aaSopenharmony_ci
275f9996aaSopenharmony_ci
285f9996aaSopenharmony_cidef get_needed_lib(file_path: str) -> list:
295f9996aaSopenharmony_ci    cmd = " ".join(["readelf", "-d", file_path])
305f9996aaSopenharmony_ci    res = run_cmd(cmd)
315f9996aaSopenharmony_ci    if res[1] != 0:
325f9996aaSopenharmony_ci        print("error run readelf -d {}".format(file_path))
335f9996aaSopenharmony_ci        print(" ".join(["pid ", str(res[0]), " ret ", str(res[1]), "\n",
345f9996aaSopenharmony_ci                        res[2].decode(), res[3].decode()]))
355f9996aaSopenharmony_ci        return []
365f9996aaSopenharmony_ci    needed_lib_name = []
375f9996aaSopenharmony_ci    lib_info = res[2].decode().split()
385f9996aaSopenharmony_ci    for i, val in enumerate(lib_info):
395f9996aaSopenharmony_ci        # lib_info : ... (NEEDED) Shared library: [libc++.so] ...
405f9996aaSopenharmony_ci        if val == "(NEEDED)" and lib_info[i + 3].startswith("[") and lib_info[i + 3].endswith("]"):
415f9996aaSopenharmony_ci            needed_lib_name.append(lib_info[i + 3][1 : -1])
425f9996aaSopenharmony_ci    return needed_lib_name
435f9996aaSopenharmony_ci
445f9996aaSopenharmony_ci
455f9996aaSopenharmony_cidef judge_lib_available(lib_name: str, lib_chain: list, available_libs: list, lib_to_path: dict) -> bool:
465f9996aaSopenharmony_ci    if lib_name in available_libs:
475f9996aaSopenharmony_ci        return True
485f9996aaSopenharmony_ci    lib_path = lib_to_path.get(lib_name)
495f9996aaSopenharmony_ci    if lib_path is None:
505f9996aaSopenharmony_ci        return False
515f9996aaSopenharmony_ci    for next_lib in get_needed_lib(lib_path):
525f9996aaSopenharmony_ci        if next_lib not in lib_chain:
535f9996aaSopenharmony_ci            lib_chain.append(next_lib)
545f9996aaSopenharmony_ci            if not judge_lib_available(next_lib, lib_chain, available_libs, lib_to_path):
555f9996aaSopenharmony_ci                return False
565f9996aaSopenharmony_ci            lib_chain.remove(next_lib)
575f9996aaSopenharmony_ci    available_libs.add(lib_name)
585f9996aaSopenharmony_ci    return True
595f9996aaSopenharmony_ci
605f9996aaSopenharmony_ci
615f9996aaSopenharmony_cidef judge_updater_available(updater_root_path: str) -> bool:
625f9996aaSopenharmony_ci    lib_to_path = dict()
635f9996aaSopenharmony_ci    for path in [os.path.join(updater_root_path, "lib64"), os.path.join(updater_root_path, "lib")]:
645f9996aaSopenharmony_ci        for root, dirs, files in os.walk(path):
655f9996aaSopenharmony_ci            for file in files:
665f9996aaSopenharmony_ci                lib_to_path[file] = os.path.join(root, file)
675f9996aaSopenharmony_ci    lib_to_path["updater"] = os.path.join(updater_root_path, "bin", "updater")
685f9996aaSopenharmony_ci    lib_chain = ["updater"]
695f9996aaSopenharmony_ci    available_libs = set()
705f9996aaSopenharmony_ci    if not judge_lib_available("updater", lib_chain, available_libs, lib_to_path):
715f9996aaSopenharmony_ci        print("Reason:  not allow updater to depend dynamic library which not exist in updater.img. {}"\
725f9996aaSopenharmony_ci              .format("->".join(lib_chain)))
735f9996aaSopenharmony_ci        print("Solution:  add updater in install_images field when compiling {}".format(lib_chain[-1]))
745f9996aaSopenharmony_ci        return False
755f9996aaSopenharmony_ci    return True
765f9996aaSopenharmony_ci
775f9996aaSopenharmony_ci
785f9996aaSopenharmony_cidef judge_updater_img_available(updater_root_path: str) -> bool:
795f9996aaSopenharmony_ci    return judge_updater_available(updater_root_path)
80