1be168c0dSopenharmony_ci#!/usr/bin/env python3
2be168c0dSopenharmony_ci# encoding: utf-8
3be168c0dSopenharmony_ci# Copyright 2024 Huawei Technologies Co., Ltd
4be168c0dSopenharmony_ci#
5be168c0dSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
6be168c0dSopenharmony_ci# you may not use this file except in compliance with the License.
7be168c0dSopenharmony_ci# You may obtain a copy of the License at
8be168c0dSopenharmony_ci#
9be168c0dSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0
10be168c0dSopenharmony_ci#
11be168c0dSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
12be168c0dSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
13be168c0dSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14be168c0dSopenharmony_ci# See the License for the specific language governing permissions and
15be168c0dSopenharmony_ci# limitations under the License.
16be168c0dSopenharmony_ci# ============================================================================
17be168c0dSopenharmony_ci
18be168c0dSopenharmony_ciimport os
19be168c0dSopenharmony_ciimport shutil
20be168c0dSopenharmony_ciimport zipfile
21be168c0dSopenharmony_ciimport argparse
22be168c0dSopenharmony_ciimport hashlib
23be168c0dSopenharmony_ciimport subprocess
24be168c0dSopenharmony_ci
25be168c0dSopenharmony_cidef extract_source(in_zip_path, out_src_path):
26be168c0dSopenharmony_ci    "depress source code form release package"
27be168c0dSopenharmony_ci    print('Extracting zipped release package...')
28be168c0dSopenharmony_ci    f = zipfile.ZipFile(in_zip_path, "r")
29be168c0dSopenharmony_ci    f.extractall(path=out_src_path)
30be168c0dSopenharmony_ci    old_src_dir = out_src_path + "/mindspore-v2.1.0/"
31be168c0dSopenharmony_ci    new_src_dir = out_src_path + "/source/"
32be168c0dSopenharmony_ci    os.rename(old_src_dir, new_src_dir)
33be168c0dSopenharmony_ci    print("Done extraction.")
34be168c0dSopenharmony_ci
35be168c0dSopenharmony_cidef do_patch(patch_dir, target_dir):
36be168c0dSopenharmony_ci    patches = [
37be168c0dSopenharmony_ci        '0001-build-gn-c-api-for-OHOS.patch',
38be168c0dSopenharmony_ci        '0002-train-and-build.patch',
39be168c0dSopenharmony_ci        '0003-add-js-api.patch',
40be168c0dSopenharmony_ci        '0004-cross-compile-ndkso-fp16-nnrt-train_capi.patch',
41be168c0dSopenharmony_ci        '0005-micro-for-ohos.patch',
42be168c0dSopenharmony_ci        '0006-remove-lite-expression-fix-double-loadso.patch',
43be168c0dSopenharmony_ci        '0007-deobfuscator.patch',
44be168c0dSopenharmony_ci        '0008-upgrade-flatbuffers-fix_crash.patch',
45be168c0dSopenharmony_ci        '0009-npu-zero-copy.patch',
46be168c0dSopenharmony_ci        '0010-micro-dynamic-shape-support-discrete-value.patch',
47be168c0dSopenharmony_ci        '0011-fix-npu-infer-memory-leak-delete-liteGraph.patch',
48be168c0dSopenharmony_ci        '0012-add-mindir-ops.patch',
49be168c0dSopenharmony_ci        '0013-hiappevent.patch',
50be168c0dSopenharmony_ci        '0014-DynamicQuant-strategy-optimization.patch',
51be168c0dSopenharmony_ci        '0015-bugfix-for-cpu-kernel.patch',
52be168c0dSopenharmony_ci        '0016-bugfix-for-argminmax-swish-int8-and-vad-asan.patch',
53be168c0dSopenharmony_ci        '0017-bugfix-for-onnx-parser.patch',
54be168c0dSopenharmony_ci        '0018-nnrt-litegraph-dequant.patch',
55be168c0dSopenharmony_ci        '0019-adaper-NNCore-Api.patch',
56be168c0dSopenharmony_ci        '0020-fix-ocr-gcn-model-crash.patch',
57be168c0dSopenharmony_ci        '0021-add-mindir-ops.patch',
58be168c0dSopenharmony_ci        '0022-adapter-HiAI-Foundation-NPU.patch',
59be168c0dSopenharmony_ci        '0023-support-x86-emulator-build.patch',
60be168c0dSopenharmony_ci        '0024-fix-gcn-model-squeeze-transpose-infershape-not-do.patch',
61be168c0dSopenharmony_ci        '0025-support-kirin-npu-dynamic-dims.patch',
62be168c0dSopenharmony_ci        '0026-fix-depthwise-conv-kernel.patch',
63be168c0dSopenharmony_ci        '0027-reduce-memory-when-npu-compilation-with-cache.patch',
64be168c0dSopenharmony_ci        '0028-fix-onnx-parser-and-cpu-kernel.patch',
65be168c0dSopenharmony_ci        '0029-remove-recursive-lock.patch',
66be168c0dSopenharmony_ci        '0030-generate-flatbuffer-notice.patch',
67be168c0dSopenharmony_ci        '0031-fix-matmul-assemble-can-not-protect-stack-in-mutil-thread.patch',
68be168c0dSopenharmony_ci        '0032-fix-for-concat-bool-type.patch',
69be168c0dSopenharmony_ci        '0033-fix-nullptr-etal.patch',
70be168c0dSopenharmony_ci        '0034-fix-semicolon-and-nullptr-etal.patch',
71be168c0dSopenharmony_ci        '0035-fix-ArgMaxFusion_get_max_parameter_uninitialized.patch',
72be168c0dSopenharmony_ci        '0036-fix-split-non-uniform-split.patch',
73be168c0dSopenharmony_ci        '0037-fix-for-fuzz-problem.patch',
74be168c0dSopenharmony_ci        '0038-refactor-nnrt-allocator-to-singleton.patch',
75be168c0dSopenharmony_ci        '0039-add-compile-option-SP-extensions-white-list.patch',
76be168c0dSopenharmony_ci        '0040-fix-context-double-free.patch',
77be168c0dSopenharmony_ci        '0041-fix-MutableData-memory-leak.patch',
78be168c0dSopenharmony_ci        '0042-scatterND-indices-illegal.patch',
79be168c0dSopenharmony_ci        '0043-fix-too-many-hi-app-event-reports.patch',
80be168c0dSopenharmony_ci    ]
81be168c0dSopenharmony_ci
82be168c0dSopenharmony_ci    cwd = os.getcwd()
83be168c0dSopenharmony_ci    os.chdir(target_dir)
84be168c0dSopenharmony_ci    print('Change dir to', os.getcwd())
85be168c0dSopenharmony_ci    subprocess.run(['git', 'init', '.'])
86be168c0dSopenharmony_ci    subprocess.run(['git', 'add', '.'])
87be168c0dSopenharmony_ci    subprocess.run(['git', 'commit', '-m', '"init"'])
88be168c0dSopenharmony_ci
89be168c0dSopenharmony_ci    for patch in patches:
90be168c0dSopenharmony_ci        print('Applying ', patch, '...')
91be168c0dSopenharmony_ci        ret = subprocess.run(['git', 'apply', '{0}/{1}'.format(patch_dir, patch)])
92be168c0dSopenharmony_ci        if ret.returncode != 0:
93be168c0dSopenharmony_ci            raise Exception("Apply patch {0} failed, ret: {1}".format(patch, ret))
94be168c0dSopenharmony_ci        subprocess.run(['git', 'add', '.'])
95be168c0dSopenharmony_ci        subprocess.run(['git', 'commit', '-m', "auto-apply {0}".format(patch)])
96be168c0dSopenharmony_ci        print('Done')
97be168c0dSopenharmony_ci    os.chdir(cwd)
98be168c0dSopenharmony_ci
99be168c0dSopenharmony_cidef create_status_file(out_src_path):
100be168c0dSopenharmony_ci    with open("{0}/.status".format(out_src_path), 'w+') as f:
101be168c0dSopenharmony_ci        f.write('ok')
102be168c0dSopenharmony_ci
103be168c0dSopenharmony_ci
104be168c0dSopenharmony_cidef compute_md5(file):
105be168c0dSopenharmony_ci    m = hashlib.md5()
106be168c0dSopenharmony_ci    with open(file, 'rb') as f:
107be168c0dSopenharmony_ci        m.update(f.read())
108be168c0dSopenharmony_ci    return m.hexdigest()
109be168c0dSopenharmony_ci
110be168c0dSopenharmony_ci
111be168c0dSopenharmony_cidef save_md5s(folder_path, out_path):
112be168c0dSopenharmony_ci    files_list = []
113be168c0dSopenharmony_ci    for file_name in os.listdir(folder_path):
114be168c0dSopenharmony_ci        if (file_name.endswith(".patch")):
115be168c0dSopenharmony_ci            files_list.append(file_name)
116be168c0dSopenharmony_ci
117be168c0dSopenharmony_ci    os.makedirs(out_path, exist_ok=True)
118be168c0dSopenharmony_ci    for pf in files_list:
119be168c0dSopenharmony_ci        md5_path = os.path.join(out_path, pf.replace(".patch", ".md5"))
120be168c0dSopenharmony_ci        with open(md5_path, 'w') as f:
121be168c0dSopenharmony_ci            f.write(compute_md5(os.path.join(folder_path, pf)))
122be168c0dSopenharmony_ci
123be168c0dSopenharmony_ci
124be168c0dSopenharmony_cidef md5_changed(patch_path, md5_path):
125be168c0dSopenharmony_ci    if not os.path.exists(md5_path):
126be168c0dSopenharmony_ci        return True
127be168c0dSopenharmony_ci    patch_list = []
128be168c0dSopenharmony_ci    md5_list = []
129be168c0dSopenharmony_ci    for file_name in os.listdir(patch_path):
130be168c0dSopenharmony_ci        if (file_name.endswith(".patch")):
131be168c0dSopenharmony_ci            patch_list.append(file_name)
132be168c0dSopenharmony_ci    for file_name in os.listdir(md5_path):
133be168c0dSopenharmony_ci        if (file_name.endswith(".md5")):
134be168c0dSopenharmony_ci            md5_list.append(file_name)
135be168c0dSopenharmony_ci    if (len(patch_list) != len(md5_list)):
136be168c0dSopenharmony_ci        return True
137be168c0dSopenharmony_ci
138be168c0dSopenharmony_ci    for md5_file in md5_list:
139be168c0dSopenharmony_ci        if not os.path.exists(os.path.join(patch_path, md5_file.replace(".md5", ".patch"))):
140be168c0dSopenharmony_ci            return True
141be168c0dSopenharmony_ci        with open(os.path.join(md5_path, md5_file), 'r') as f:
142be168c0dSopenharmony_ci            origin_v = f.read().strip()
143be168c0dSopenharmony_ci            if (origin_v != compute_md5(os.path.join(patch_path, md5_file.replace(".md5", ".patch")))):
144be168c0dSopenharmony_ci                return True
145be168c0dSopenharmony_ci    return False
146be168c0dSopenharmony_ci
147be168c0dSopenharmony_ci
148be168c0dSopenharmony_cidef source_has_changed(out_src_path, patch_path, md5_path):
149be168c0dSopenharmony_ci    if not os.path.exists(os.path.join(out_src_path, ".status")):
150be168c0dSopenharmony_ci        print(".status not exist.")
151be168c0dSopenharmony_ci        return True
152be168c0dSopenharmony_ci    return md5_changed(patch_path, md5_path)
153be168c0dSopenharmony_ci
154be168c0dSopenharmony_ci
155be168c0dSopenharmony_cidef main_work():
156be168c0dSopenharmony_ci    parser = argparse.ArgumentParser(description="mindspore build helper")
157be168c0dSopenharmony_ci    parser.add_argument('--in_zip_path')
158be168c0dSopenharmony_ci    parser.add_argument('--out_src_path')
159be168c0dSopenharmony_ci    parser.add_argument('--patch_dir')
160be168c0dSopenharmony_ci    args = vars(parser.parse_args())
161be168c0dSopenharmony_ci
162be168c0dSopenharmony_ci    in_zip_path = os.path.realpath(args['in_zip_path'])
163be168c0dSopenharmony_ci    out_src_path = args['out_src_path']
164be168c0dSopenharmony_ci    patch_dir = os.path.realpath(args['patch_dir'])
165be168c0dSopenharmony_ci
166be168c0dSopenharmony_ci    md5_dir = os.path.join(out_src_path, "patches_md5")
167be168c0dSopenharmony_ci    if source_has_changed(out_src_path, patch_dir, md5_dir):
168be168c0dSopenharmony_ci        print("remove ", out_src_path)
169be168c0dSopenharmony_ci        if os.path.exists(out_src_path):
170be168c0dSopenharmony_ci            shutil.rmtree(out_src_path)
171be168c0dSopenharmony_ci        save_md5s(patch_dir, md5_dir)
172be168c0dSopenharmony_ci
173be168c0dSopenharmony_ci    if os.path.exists(os.path.join(out_src_path, ".status")):
174be168c0dSopenharmony_ci        print("patch files not changed and " + os.path.join(out_src_path, ".status") + " exists.")
175be168c0dSopenharmony_ci        return
176be168c0dSopenharmony_ci
177be168c0dSopenharmony_ci    os.makedirs(out_src_path, exist_ok=True)
178be168c0dSopenharmony_ci    out_src_path = os.path.realpath(out_src_path)
179be168c0dSopenharmony_ci
180be168c0dSopenharmony_ci    extract_source(in_zip_path, out_src_path)
181be168c0dSopenharmony_ci
182be168c0dSopenharmony_ci    do_patch(patch_dir, out_src_path + '/source/')
183be168c0dSopenharmony_ci
184be168c0dSopenharmony_ci    create_status_file(out_src_path)
185be168c0dSopenharmony_ci
186be168c0dSopenharmony_ci
187be168c0dSopenharmony_ciif __name__ == "__main__":
188be168c0dSopenharmony_ci    main_work()
189be168c0dSopenharmony_ci
190