154568cb3Sopenharmony_ci#!/usr/bin/env python3
254568cb3Sopenharmony_ci# coding=utf-8
354568cb3Sopenharmony_ci# The build entrance of UniProton.
454568cb3Sopenharmony_ci
554568cb3Sopenharmony_ci#
654568cb3Sopenharmony_ci# Copyright (c) 2021-2023 Huawei Device Co., Ltd.
754568cb3Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
854568cb3Sopenharmony_ci# you may not use this file except in compliance with the License.
954568cb3Sopenharmony_ci# You may obtain a copy of the License at
1054568cb3Sopenharmony_ci#
1154568cb3Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
1254568cb3Sopenharmony_ci#
1354568cb3Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
1454568cb3Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
1554568cb3Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1654568cb3Sopenharmony_ci# See the License for the specific language governing permissions and
1754568cb3Sopenharmony_ci# limitations under the License.
1854568cb3Sopenharmony_ci#
1954568cb3Sopenharmony_ci
2054568cb3Sopenharmony_ciimport os
2154568cb3Sopenharmony_ciimport sys
2254568cb3Sopenharmony_ciimport time
2354568cb3Sopenharmony_ciimport shutil
2454568cb3Sopenharmony_ciimport subprocess
2554568cb3Sopenharmony_ciimport platform
2654568cb3Sopenharmony_cifrom sys import argv
2754568cb3Sopenharmony_ciUniProton_home = os.path.dirname(os.path.abspath(__file__))
2854568cb3Sopenharmony_cisys.path.insert(0, "%s/cmake/common/build_auxiliary_script"%UniProton_home)
2954568cb3Sopenharmony_cifrom make_buildef import make_buildef
3054568cb3Sopenharmony_cisys.path.insert(0, "%s/build/uniproton_ci_lib"%UniProton_home)
3154568cb3Sopenharmony_ciimport globle
3254568cb3Sopenharmony_cifrom logs import BuilderNolog, log_msg
3354568cb3Sopenharmony_cifrom get_config_info import *
3454568cb3Sopenharmony_ci
3554568cb3Sopenharmony_ci
3654568cb3Sopenharmony_ciclass Compile:
3754568cb3Sopenharmony_ci
3854568cb3Sopenharmony_ci    # 根据makechoice获取config的配置的环境,compile_mode, lib_type,
3954568cb3Sopenharmony_ci    def get_config(self, cpu_type, cpu_plat):
4054568cb3Sopenharmony_ci        self.compile_mode = get_compile_mode()
4154568cb3Sopenharmony_ci        self.lib_type, self.plam_type, self.hcc_path, self.kconf_dir, self.system, self.core = get_cpu_info(cpu_type, cpu_plat, self.build_machine_platform)
4254568cb3Sopenharmony_ci        if not self.compile_mode and self.lib_type and self.plam_type and self.hcc_path and self.kconf_dir:
4354568cb3Sopenharmony_ci            log_msg('error', 'load config.xml env error')
4454568cb3Sopenharmony_ci            sys.exit(0)
4554568cb3Sopenharmony_ci        self.config_file_path = '%s/build/uniproton_config/config_%s'%(self.home_path, self.kconf_dir)
4654568cb3Sopenharmony_ci
4754568cb3Sopenharmony_ci        self.objcopy_path = self.hcc_path
4854568cb3Sopenharmony_ci
4954568cb3Sopenharmony_ci    def setCmdEnv(self):
5054568cb3Sopenharmony_ci        self.build_time_tag = time.strftime('%Y-%m-%d_%H:%M:00')
5154568cb3Sopenharmony_ci        self.log_dir = '%s/logs/%s' % (self.build_dir, self.cpu_type)
5254568cb3Sopenharmony_ci        self.log_file = '%s.log' % self.kconf_dir
5354568cb3Sopenharmony_ci
5454568cb3Sopenharmony_ci    def SetCMakeEnviron(self):
5554568cb3Sopenharmony_ci        os.environ["CPU_TYPE"] = self.cpu_type
5654568cb3Sopenharmony_ci        os.environ["PLAM_TYPE"] = self.plam_type
5754568cb3Sopenharmony_ci        os.environ["LIB_TYPE"] = self.lib_type
5854568cb3Sopenharmony_ci        os.environ["COMPILE_OPTION"] = self.compile_option
5954568cb3Sopenharmony_ci        os.environ["HCC_PATH"] = self.hcc_path
6054568cb3Sopenharmony_ci        os.environ["UNIPROTON_PACKING_PATH"] = self.UniProton_packing_path
6154568cb3Sopenharmony_ci        os.environ["CONFIG_FILE_PATH"] = self.config_file_path
6254568cb3Sopenharmony_ci        os.environ["LIB_RUN_TYPE"] = self.lib_run_type
6354568cb3Sopenharmony_ci        os.environ["HOME_PATH"] = self.home_path
6454568cb3Sopenharmony_ci        os.environ["COMPILE_MODE"] = self.compile_mode
6554568cb3Sopenharmony_ci        os.environ["BUILD_MACHINE_PLATFORM"] = self.build_machine_platform
6654568cb3Sopenharmony_ci        os.environ["SYSTEM"] = self.system
6754568cb3Sopenharmony_ci        os.environ["CORE"] = self.core
6854568cb3Sopenharmony_ci        os.environ["OBJCOPY_PATH"] = self.objcopy_path
6954568cb3Sopenharmony_ci        os.environ['PATH'] = '%s:%s' % (self.hcc_path, os.getenv('PATH'))
7054568cb3Sopenharmony_ci
7154568cb3Sopenharmony_ci    # 环境准备,准备执行cmake,make,makebuildfile,CmakeList需要的环境
7254568cb3Sopenharmony_ci    # 每次compile之前请调用该函数
7354568cb3Sopenharmony_ci    def prepare_env(self, cpu_type, choice):
7454568cb3Sopenharmony_ci        # makebuildfile需要的环境kconf_dir
7554568cb3Sopenharmony_ci        # cmake需要的环境cmake_env_path,home_path(cmakelist所在的路径),home_path,
7654568cb3Sopenharmony_ci        # make cmd拼接需要的环境:home_path,UniProton_make_jx,log_dir,log_file,build_time_tag, UniProton_make_jx
7754568cb3Sopenharmony_ci
7854568cb3Sopenharmony_ci        #根据cpu_type, choice从config文件中获取并初始化初始化hcc_path, plam_type, kconf_dir
7954568cb3Sopenharmony_ci        #根据输入分支获取
8054568cb3Sopenharmony_ci        #从编译镜像环境获取
8154568cb3Sopenharmony_ci        self.get_config(cpu_type, choice)
8254568cb3Sopenharmony_ci        self.setCmdEnv()
8354568cb3Sopenharmony_ci        self.SetCMakeEnviron()
8454568cb3Sopenharmony_ci
8554568cb3Sopenharmony_ci    #获取编译环境是arm64还是x86,用户不感知,并将其写入环境变量。
8654568cb3Sopenharmony_ci    def getOsPlatform(self):
8754568cb3Sopenharmony_ci        self.cmake_env_path = get_tool_info('cmake', 'tool_path')
8854568cb3Sopenharmony_ci
8954568cb3Sopenharmony_ci        if platform.uname()[-1] == 'aarch64':
9054568cb3Sopenharmony_ci            self.build_machine_platform = 'arm64'
9154568cb3Sopenharmony_ci        else:
9254568cb3Sopenharmony_ci            self.build_machine_platform = 'x86'
9354568cb3Sopenharmony_ci
9454568cb3Sopenharmony_ci    # 获取当前编译的路径信息,配置文件信息,编译选项信息
9554568cb3Sopenharmony_ci    def __init__(self, cpu_type: str, make_option="normal", lib_run_type="FPGA", choice="ALL", make_phase="ALL",
9654568cb3Sopenharmony_ci                 UniProton_packing_path=""):
9754568cb3Sopenharmony_ci        # 当前路径信息
9854568cb3Sopenharmony_ci        self.system = ""
9954568cb3Sopenharmony_ci        self.objcopy_path = ""
10054568cb3Sopenharmony_ci        self.builder = None
10154568cb3Sopenharmony_ci        self.compile_mode = ""
10254568cb3Sopenharmony_ci        self.core = ""
10354568cb3Sopenharmony_ci        self.plam_type = ""
10454568cb3Sopenharmony_ci        self.kconf_dir = ""
10554568cb3Sopenharmony_ci        self.build_tmp_dir = ""
10654568cb3Sopenharmony_ci        self.log_dir = ""
10754568cb3Sopenharmony_ci        self.lib_type = ""
10854568cb3Sopenharmony_ci        self.hcc_path = ""
10954568cb3Sopenharmony_ci        self.log_file = ""
11054568cb3Sopenharmony_ci        self.config_file_path = ""
11154568cb3Sopenharmony_ci        self.build_time_tag = ""
11254568cb3Sopenharmony_ci        self.build_dir = globle.build_dir
11354568cb3Sopenharmony_ci        self.home_path = globle.home_path
11454568cb3Sopenharmony_ci        self.kbuild_path = globle.kbuild_path
11554568cb3Sopenharmony_ci        # 当前选项信息
11654568cb3Sopenharmony_ci        self.cpu_type = cpu_type
11754568cb3Sopenharmony_ci        self.compile_option = make_option
11854568cb3Sopenharmony_ci        self.lib_run_type = lib_run_type
11954568cb3Sopenharmony_ci        self.make_choice = choice.lower()
12054568cb3Sopenharmony_ci        self.make_phase = make_phase
12154568cb3Sopenharmony_ci        self.UniProton_packing_path = UniProton_packing_path if make_phase == "CREATE_CMAKE_FILE" else '%s/output'%self.home_path
12254568cb3Sopenharmony_ci        self.UniProton_binary_dir = os.getenv('RPROTON_BINARY_DIR')
12354568cb3Sopenharmony_ci        self.UniProton_install_file_option = os.getenv('RPROTON_INSTALL_FILE_OPTION')
12454568cb3Sopenharmony_ci        self.UniProton_make_jx = 'VERBOSE=1' if self.UniProton_install_file_option == 'SUPER_BUILD' else 'VERBOSE=1 -j$(nproc)'
12554568cb3Sopenharmony_ci        # 当前编译平台信息
12654568cb3Sopenharmony_ci        self.getOsPlatform()
12754568cb3Sopenharmony_ci
12854568cb3Sopenharmony_ci    #调用cmake生成Makefile文件,需要
12954568cb3Sopenharmony_ci    def CMake(self):
13054568cb3Sopenharmony_ci        if self.UniProton_binary_dir:
13154568cb3Sopenharmony_ci            self.build_tmp_dir = '%s/output/tmp/%s' % (self.UniProton_binary_dir, self.kconf_dir)
13254568cb3Sopenharmony_ci        else:
13354568cb3Sopenharmony_ci            self.build_tmp_dir = '%s/output/tmp/%s' % (self.build_dir, self.kconf_dir)
13454568cb3Sopenharmony_ci        os.environ['BUILD_TMP_DIR'] = self.build_tmp_dir
13554568cb3Sopenharmony_ci
13654568cb3Sopenharmony_ci        if not os.path.exists(self.build_tmp_dir):
13754568cb3Sopenharmony_ci            os.makedirs(self.build_tmp_dir)
13854568cb3Sopenharmony_ci        if not os.path.exists(self.log_dir):
13954568cb3Sopenharmony_ci            os.makedirs(self.log_dir)
14054568cb3Sopenharmony_ci
14154568cb3Sopenharmony_ci        log_msg('info', 'BUILD_TIME_TAG %s' % self.build_time_tag)
14254568cb3Sopenharmony_ci        self.builder = BuilderNolog(os.path.join(self.log_dir, self.log_file))
14354568cb3Sopenharmony_ci        if self.make_phase in ['CREATE_CMAKE_FILE', 'ALL']:
14454568cb3Sopenharmony_ci            real_path = os.path.realpath(self.build_tmp_dir)
14554568cb3Sopenharmony_ci            if os.path.exists(real_path):
14654568cb3Sopenharmony_ci                shutil.rmtree(real_path)
14754568cb3Sopenharmony_ci            os.makedirs(self.build_tmp_dir)
14854568cb3Sopenharmony_ci            #拼接cmake命令
14954568cb3Sopenharmony_ci            if self.compile_option == 'fortify':
15054568cb3Sopenharmony_ci                cmd = '%s/cmake %s -DCMAKE_TOOLCHAIN_FILE=%s/cmake/tool_chain/uniproton_tool_chain.cmake ' \
15154568cb3Sopenharmony_ci                      '-DCMAKE_C_COMPILER_LAUNCHER="sourceanalyzer;-b;%sproject" ' \
15254568cb3Sopenharmony_ci                      '-DCMAKE_INSTALL_PREFIX=%s &> %s/%s' % (
15354568cb3Sopenharmony_ci                self.cmake_env_path, self.home_path, self.home_path, self.cpu_type,
15454568cb3Sopenharmony_ci                self.UniProton_packing_path, self.log_dir, self.log_file)
15554568cb3Sopenharmony_ci            elif self.compile_option == 'hllt':
15654568cb3Sopenharmony_ci                cmd = '%s/cmake %s -DCMAKE_TOOLCHAIN_FILE=%s/cmake/tool_chain/uniproton_tool_chain.cmake ' \
15754568cb3Sopenharmony_ci                      '-DCMAKE_C_COMPILER_LAUNCHER="lltwrapper" -DCMAKE_INSTALL_PREFIX=%s &> %s/%s' % (
15854568cb3Sopenharmony_ci                self.cmake_env_path, self.home_path, self.home_path, self.UniProton_packing_path, self.log_dir, self.log_file)
15954568cb3Sopenharmony_ci            else:
16054568cb3Sopenharmony_ci                cmd = '%s/cmake %s -DCMAKE_TOOLCHAIN_FILE=%s/cmake/tool_chain/uniproton_tool_chain.cmake ' \
16154568cb3Sopenharmony_ci                      '-DCMAKE_INSTALL_PREFIX=%s &> %s/%s' % (
16254568cb3Sopenharmony_ci                self.cmake_env_path, self.home_path, self.home_path, self.UniProton_packing_path, self.log_dir, self.log_file)
16354568cb3Sopenharmony_ci            #执行cmake命令
16454568cb3Sopenharmony_ci            if self.builder.run(cmd, cwd=self.build_tmp_dir, env=None):
16554568cb3Sopenharmony_ci                log_msg('error', 'generate makefile failed!')
16654568cb3Sopenharmony_ci                return False
16754568cb3Sopenharmony_ci
16854568cb3Sopenharmony_ci        log_msg('info', 'generate makefile succeed.')
16954568cb3Sopenharmony_ci        return True
17054568cb3Sopenharmony_ci
17154568cb3Sopenharmony_ci    def UniProton_clean(self):
17254568cb3Sopenharmony_ci        for foldername,subfoldernames,filenames in os.walk(self.build_dir):
17354568cb3Sopenharmony_ci            for subfoldername in subfoldernames:
17454568cb3Sopenharmony_ci                if subfoldername in ['logs','output','__pycache__']:
17554568cb3Sopenharmony_ci                    folder_path = os.path.join(foldername,subfoldername)
17654568cb3Sopenharmony_ci                    shutil.rmtree(os.path.relpath(folder_path))
17754568cb3Sopenharmony_ci            for filename in filenames:
17854568cb3Sopenharmony_ci                if filename == 'prt_buildef.h':
17954568cb3Sopenharmony_ci                    file_dir = os.path.join(foldername,filename)
18054568cb3Sopenharmony_ci                    os.remove(os.path.relpath(file_dir))
18154568cb3Sopenharmony_ci        if os.path.exists('%s/cmake/common/build_auxiliary_script/__pycache__'%self.home_path):
18254568cb3Sopenharmony_ci            shutil.rmtree('%s/cmake/common/build_auxiliary_script/__pycache__'%self.home_path)
18354568cb3Sopenharmony_ci        if os.path.exists('%s/output'%self.home_path):
18454568cb3Sopenharmony_ci            shutil.rmtree('%s/output'%self.home_path)
18554568cb3Sopenharmony_ci        if os.path.exists('%s/tools/SRE/x86-win32/sp_makepatch/makepatch'%self.home_path):
18654568cb3Sopenharmony_ci            os.remove('%s/tools/SRE/x86-win32/sp_makepatch/makepatch'%self.home_path)
18754568cb3Sopenharmony_ci        if os.path.exists('%s/build/prepare/__pycache__'%self.home_path):
18854568cb3Sopenharmony_ci            shutil.rmtree('%s/build/prepare/__pycache__'%self.home_path)
18954568cb3Sopenharmony_ci        return True
19054568cb3Sopenharmony_ci
19154568cb3Sopenharmony_ci
19254568cb3Sopenharmony_ci    def make(self):
19354568cb3Sopenharmony_ci        if self.make_phase in ['EXECUTING_MAKE', 'ALL']:
19454568cb3Sopenharmony_ci            self.builder.run('make clean', cwd=self.build_tmp_dir, env=None)
19554568cb3Sopenharmony_ci            tmp = sys.argv
19654568cb3Sopenharmony_ci            if self.builder.run(
19754568cb3Sopenharmony_ci                    'make all %s &>> %s/%s' % (
19854568cb3Sopenharmony_ci                    self.UniProton_make_jx, self.log_dir, self.log_file), cwd=self.build_tmp_dir, env=None):
19954568cb3Sopenharmony_ci                log_msg('error', 'make %s %s  failed!' % (self.cpu_type, self.plam_type))
20054568cb3Sopenharmony_ci                return False
20154568cb3Sopenharmony_ci            sys.argv = tmp
20254568cb3Sopenharmony_ci            if self.compile_option in ['normal', 'coverity', 'single']:
20354568cb3Sopenharmony_ci                if self.builder.run('make install %s &>> %s/%s' % (self.UniProton_make_jx, self.log_dir, self.log_file), cwd=self.build_tmp_dir, env=None):
20454568cb3Sopenharmony_ci                    log_msg('error', 'make install failed!')
20554568cb3Sopenharmony_ci                    return False
20654568cb3Sopenharmony_ci            if os.path.exists('%s/%s' % (self.log_dir, self.log_file)):
20754568cb3Sopenharmony_ci                self.builder.log_format()
20854568cb3Sopenharmony_ci
20954568cb3Sopenharmony_ci        log_msg('info', 'make %s %s succeed.' % (self.cpu_type, self.plam_type))
21054568cb3Sopenharmony_ci        return True
21154568cb3Sopenharmony_ci
21254568cb3Sopenharmony_ci    def SdkCompaile(self)->bool:
21354568cb3Sopenharmony_ci        # 判断该环境中是否需要编译
21454568cb3Sopenharmony_ci        if self.hcc_path == 'None':
21554568cb3Sopenharmony_ci            return True
21654568cb3Sopenharmony_ci
21754568cb3Sopenharmony_ci        self.MakeBuildef()
21854568cb3Sopenharmony_ci        if self.CMake() and self.make():
21954568cb3Sopenharmony_ci            log_msg('info', 'make %s %s lib succeed!' % (self.cpu_type, self.make_choice))
22054568cb3Sopenharmony_ci            return True
22154568cb3Sopenharmony_ci        else:
22254568cb3Sopenharmony_ci            log_msg('info', 'make %s %s lib failed!' % (self.cpu_type, self.make_choice))
22354568cb3Sopenharmony_ci            return False
22454568cb3Sopenharmony_ci
22554568cb3Sopenharmony_ci    # 对外函数,调用后根据类初始化时的值进行编译
22654568cb3Sopenharmony_ci    def UniProtonCompile(self):
22754568cb3Sopenharmony_ci        #清除UniProton缓存
22854568cb3Sopenharmony_ci        if self.cpu_type == 'clean':
22954568cb3Sopenharmony_ci            log_msg('info', 'UniProton clean')
23054568cb3Sopenharmony_ci            return self.UniProton_clean()
23154568cb3Sopenharmony_ci        # 根据cpu的编译平台配置相应的编译环境。
23254568cb3Sopenharmony_ci        if self.make_choice == "all":
23354568cb3Sopenharmony_ci            for make_choice in globle.cpu_plat[self.cpu_type]:
23454568cb3Sopenharmony_ci                self.prepare_env(self.cpu_type, make_choice)
23554568cb3Sopenharmony_ci                if not self.SdkCompaile():
23654568cb3Sopenharmony_ci                    return False
23754568cb3Sopenharmony_ci        else:
23854568cb3Sopenharmony_ci            self.prepare_env(self.cpu_type, self.make_choice)
23954568cb3Sopenharmony_ci            if not self.SdkCompaile():
24054568cb3Sopenharmony_ci                return False
24154568cb3Sopenharmony_ci        return True
24254568cb3Sopenharmony_ci
24354568cb3Sopenharmony_ci    def MakeBuildef(self):
24454568cb3Sopenharmony_ci
24554568cb3Sopenharmony_ci        if not make_buildef(globle.home_path,self.kconf_dir,"CREATE"):
24654568cb3Sopenharmony_ci            sys.exit(1)
24754568cb3Sopenharmony_ci        log_msg('info', 'make_buildef_file.sh %s successfully.' % self.kconf_dir)
24854568cb3Sopenharmony_ci
24954568cb3Sopenharmony_ci# argv[1]: cpu_plat 表示要编译的平台:
25054568cb3Sopenharmony_ci# argv[2]: compile_option 控制编译选项,调用不同的cmake参数,目前只有normal coverity hllt fortify single(是否编译安全c,组件化独立构建需求)
25154568cb3Sopenharmony_ci# argv[3]: lib_run_type lib库要跑的平台 faga sim等
25254568cb3Sopenharmony_ci# argv[4]: make_choice
25354568cb3Sopenharmony_ci# argv[5]: make_phase 全量构建选项
25454568cb3Sopenharmony_ci# argv[6]: UniProton_packing_path lib库的安装位置
25554568cb3Sopenharmony_ciif __name__ == "__main__":
25654568cb3Sopenharmony_ci    default_para = ("all", "normal", "FPGA", "ALL", "ALL", "")
25754568cb3Sopenharmony_ci    if len(argv) == 1:
25854568cb3Sopenharmony_ci        para = [default_para[i] for i in range(0, len(default_para))]
25954568cb3Sopenharmony_ci    else:
26054568cb3Sopenharmony_ci        para = [argv[i+1] if i < len(argv) - 1 else default_para[i] for i in range(0,len(default_para))]
26154568cb3Sopenharmony_ci
26254568cb3Sopenharmony_ci    cur_cpu_type = para[0].lower()
26354568cb3Sopenharmony_ci    cur_compile_option = para[1].lower()
26454568cb3Sopenharmony_ci    cur_lib_run_type = para[2]
26554568cb3Sopenharmony_ci    cur_make_choice = para[3]
26654568cb3Sopenharmony_ci    cur_make_phase = para[4]
26754568cb3Sopenharmony_ci    cur_UniProton_packing_path = para[5]
26854568cb3Sopenharmony_ci    for plat in globle.cpus_[cur_cpu_type]:
26954568cb3Sopenharmony_ci        UniProton_build = Compile(plat, cur_compile_option, cur_lib_run_type, cur_make_choice, cur_make_phase, cur_UniProton_packing_path)
27054568cb3Sopenharmony_ci        if not UniProton_build.UniProtonCompile():
27154568cb3Sopenharmony_ci            sys.exit(1)
27254568cb3Sopenharmony_ci    sys.exit(0)
27354568cb3Sopenharmony_ci
274