• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3# The build entrance of UniProton.
4# Copyright © Huawei Technologies Co., Ltd. 2010-2020. All rights reserved.
5
6import os
7import sys
8import time
9import shutil
10import subprocess
11import platform
12from sys import argv
13UniProton_home = os.path.dirname(os.path.abspath(__file__))
14sys.path.insert(0, "%s/cmake/common/build_auxiliary_script"%UniProton_home)
15from make_buildef import make_buildef
16sys.path.insert(0, "%s/build/uniproton_ci_lib"%UniProton_home)
17import globle
18from logs import BuilderNolog, log_msg
19from get_config_info import *
20
21
22class Compile:
23
24    # 根据makechoice获取config的配置的环境,compile_mode, lib_type,
25    def get_config(self, cpu_type, cpu_plat):
26        self.compile_mode = get_compile_mode()
27        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)
28        if not self.compile_mode and self.lib_type and self.plam_type and self.hcc_path and self.kconf_dir:
29            log_msg('error', 'load config.xml env error')
30            sys.exit(0)
31        self.config_file_path = '%s/build/uniproton_config/config_%s'%(self.home_path, self.kconf_dir)
32
33        self.objcopy_path = self.hcc_path
34
35    def setCmdEnv(self):
36        self.build_time_tag = time.strftime('%Y-%m-%d_%H:%M:00')
37        self.log_dir = '%s/logs/%s' % (self.build_dir, self.cpu_type)
38        self.log_file = '%s.log' % self.kconf_dir
39
40    def SetCMakeEnviron(self):
41        os.environ["CPU_TYPE"] = self.cpu_type
42        os.environ["PLAM_TYPE"] = self.plam_type
43        os.environ["LIB_TYPE"] = self.lib_type
44        os.environ["COMPILE_OPTION"] = self.compile_option
45        os.environ["HCC_PATH"] = self.hcc_path
46        os.environ["UNIPROTON_PACKING_PATH"] = self.UniProton_packing_path
47        os.environ["CONFIG_FILE_PATH"] = self.config_file_path
48        os.environ["LIB_RUN_TYPE"] = self.lib_run_type
49        os.environ["HOME_PATH"] = self.home_path
50        os.environ["COMPILE_MODE"] = self.compile_mode
51        os.environ["BUILD_MACHINE_PLATFORM"] = self.build_machine_platform
52        os.environ["SYSTEM"] = self.system
53        os.environ["CORE"] = self.core
54        os.environ["OBJCOPY_PATH"] = self.objcopy_path
55        os.environ['PATH'] = '%s:%s' % (self.hcc_path, os.getenv('PATH'))
56
57    # 环境准备,准备执行cmake,make,makebuildfile,CmakeList需要的环境
58    # 每次compile之前请调用该函数
59    def prepare_env(self, cpu_type, choice):
60        # makebuildfile需要的环境kconf_dir
61        # cmake需要的环境cmake_env_path,home_path(cmakelist所在的路径),home_path,
62        # make cmd拼接需要的环境:home_path,UniProton_make_jx,log_dir,log_file,build_time_tag, UniProton_make_jx
63
64        #根据cpu_type, choice从config文件中获取并初始化初始化hcc_path, plam_type, kconf_dir
65        #根据输入分支获取
66        #从编译镜像环境获取
67        self.get_config(cpu_type, choice)
68        self.setCmdEnv()
69        self.SetCMakeEnviron()
70
71    #获取编译环境是arm64还是x86,用户不感知,并将其写入环境变量。
72    def getOsPlatform(self):
73        self.cmake_env_path = get_tool_info('cmake', 'tool_path')
74
75        if platform.uname()[-1] == 'aarch64':
76            self.build_machine_platform = 'arm64'
77        else:
78            self.build_machine_platform = 'x86'
79
80    # 获取当前编译的路径信息,配置文件信息,编译选项信息
81    def __init__(self, cpu_type: str, make_option="normal", lib_run_type="FPGA", choice="ALL", make_phase="ALL",
82                 UniProton_packing_path=""):
83        # 当前路径信息
84        self.system = ""
85        self.objcopy_path = ""
86        self.builder = None
87        self.compile_mode = ""
88        self.core = ""
89        self.plam_type = ""
90        self.kconf_dir = ""
91        self.build_tmp_dir = ""
92        self.log_dir = ""
93        self.lib_type = ""
94        self.hcc_path = ""
95        self.log_file = ""
96        self.config_file_path = ""
97        self.build_time_tag = ""
98        self.build_dir = globle.build_dir
99        self.home_path = globle.home_path
100        self.kbuild_path = globle.kbuild_path
101        # 当前选项信息
102        self.cpu_type = cpu_type
103        self.compile_option = make_option
104        self.lib_run_type = lib_run_type
105        self.make_choice = choice.lower()
106        self.make_phase = make_phase
107        self.UniProton_packing_path = UniProton_packing_path if make_phase == "CREATE_CMAKE_FILE" else '%s/output'%self.home_path
108        self.UniProton_binary_dir = os.getenv('RPROTON_BINARY_DIR')
109        self.UniProton_install_file_option = os.getenv('RPROTON_INSTALL_FILE_OPTION')
110        self.UniProton_make_jx = 'VERBOSE=1' if self.UniProton_install_file_option == 'SUPER_BUILD' else 'VERBOSE=1 -j$(nproc)'
111        # 当前编译平台信息
112        self.getOsPlatform()
113
114    #调用cmake生成Makefile文件,需要
115    def CMake(self):
116        if self.UniProton_binary_dir:
117            self.build_tmp_dir = '%s/output/tmp/%s' % (self.UniProton_binary_dir, self.kconf_dir)
118        else:
119            self.build_tmp_dir = '%s/output/tmp/%s' % (self.build_dir, self.kconf_dir)
120        os.environ['BUILD_TMP_DIR'] = self.build_tmp_dir
121
122        if not os.path.exists(self.build_tmp_dir):
123            os.makedirs(self.build_tmp_dir)
124        if not os.path.exists(self.log_dir):
125            os.makedirs(self.log_dir)
126
127        log_msg('info', 'BUILD_TIME_TAG %s' % self.build_time_tag)
128        self.builder = BuilderNolog(os.path.join(self.log_dir, self.log_file))
129        if self.make_phase in ['CREATE_CMAKE_FILE', 'ALL']:
130            real_path = os.path.realpath(self.build_tmp_dir)
131            if os.path.exists(real_path):
132                shutil.rmtree(real_path)
133            os.makedirs(self.build_tmp_dir)
134            #拼接cmake命令
135            if self.compile_option == 'fortify':
136                cmd = '%s/cmake %s -DCMAKE_TOOLCHAIN_FILE=%s/cmake/tool_chain/uniproton_tool_chain.cmake ' \
137                      '-DCMAKE_C_COMPILER_LAUNCHER="sourceanalyzer;-b;%sproject" ' \
138                      '-DCMAKE_INSTALL_PREFIX=%s &> %s/%s' % (
139                self.cmake_env_path, self.home_path, self.home_path, self.cpu_type,
140                self.UniProton_packing_path, self.log_dir, self.log_file)
141            elif self.compile_option == 'hllt':
142                cmd = '%s/cmake %s -DCMAKE_TOOLCHAIN_FILE=%s/cmake/tool_chain/uniproton_tool_chain.cmake ' \
143                      '-DCMAKE_C_COMPILER_LAUNCHER="lltwrapper" -DCMAKE_INSTALL_PREFIX=%s &> %s/%s' % (
144                self.cmake_env_path, self.home_path, self.home_path, self.UniProton_packing_path, self.log_dir, self.log_file)
145            else:
146                cmd = '%s/cmake %s -DCMAKE_TOOLCHAIN_FILE=%s/cmake/tool_chain/uniproton_tool_chain.cmake ' \
147                      '-DCMAKE_INSTALL_PREFIX=%s &> %s/%s' % (
148                self.cmake_env_path, self.home_path, self.home_path, self.UniProton_packing_path, self.log_dir, self.log_file)
149            #执行cmake命令
150            if self.builder.run(cmd, cwd=self.build_tmp_dir, env=None):
151                log_msg('error', 'generate makefile failed!')
152                return False
153
154        log_msg('info', 'generate makefile succeed.')
155        return True
156
157    def UniProton_clean(self):
158        for foldername,subfoldernames,filenames in os.walk(self.build_dir):
159            for subfoldername in subfoldernames:
160                if subfoldername in ['logs','output','__pycache__']:
161                    folder_path = os.path.join(foldername,subfoldername)
162                    shutil.rmtree(os.path.relpath(folder_path))
163            for filename in filenames:
164                if filename == 'prt_buildef.h':
165                    file_dir = os.path.join(foldername,filename)
166                    os.remove(os.path.relpath(file_dir))
167        if os.path.exists('%s/cmake/common/build_auxiliary_script/__pycache__'%self.home_path):
168            shutil.rmtree('%s/cmake/common/build_auxiliary_script/__pycache__'%self.home_path)
169        if os.path.exists('%s/output'%self.home_path):
170            shutil.rmtree('%s/output'%self.home_path)
171        if os.path.exists('%s/tools/SRE/x86-win32/sp_makepatch/makepatch'%self.home_path):
172            os.remove('%s/tools/SRE/x86-win32/sp_makepatch/makepatch'%self.home_path)
173        if os.path.exists('%s/build/prepare/__pycache__'%self.home_path):
174            shutil.rmtree('%s/build/prepare/__pycache__'%self.home_path)
175        return True
176
177
178    def make(self):
179        if self.make_phase in ['EXECUTING_MAKE', 'ALL']:
180            self.builder.run('make clean', cwd=self.build_tmp_dir, env=None)
181            tmp = sys.argv
182            if self.builder.run(
183                    'make all %s &>> %s/%s' % (
184                    self.UniProton_make_jx, self.log_dir, self.log_file), cwd=self.build_tmp_dir, env=None):
185                log_msg('error', 'make %s %s  failed!' % (self.cpu_type, self.plam_type))
186                return False
187            sys.argv = tmp
188            if self.compile_option in ['normal', 'coverity', 'single']:
189                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):
190                    log_msg('error', 'make install failed!')
191                    return False
192            if os.path.exists('%s/%s' % (self.log_dir, self.log_file)):
193                self.builder.log_format()
194
195        log_msg('info', 'make %s %s succeed.' % (self.cpu_type, self.plam_type))
196        return True
197
198    def SdkCompaile(self)->bool:
199        # 判断该环境中是否需要编译
200        if self.hcc_path == 'None':
201            return True
202
203        self.MakeBuildef()
204        if self.CMake() and self.make():
205            log_msg('info', 'make %s %s lib succeed!' % (self.cpu_type, self.make_choice))
206            return True
207        else:
208            log_msg('info', 'make %s %s lib failed!' % (self.cpu_type, self.make_choice))
209            return False
210
211    # 对外函数,调用后根据类初始化时的值进行编译
212    def UniProtonCompile(self):
213        #清除UniProton缓存
214        if self.cpu_type == 'clean':
215            log_msg('info', 'UniProton clean')
216            return self.UniProton_clean()
217        # 根据cpu的编译平台配置相应的编译环境。
218        if self.make_choice == "all":
219            for make_choice in globle.cpu_plat[self.cpu_type]:
220                self.prepare_env(self.cpu_type, make_choice)
221                if not self.SdkCompaile():
222                    return False
223        else:
224            self.prepare_env(self.cpu_type, self.make_choice)
225            if not self.SdkCompaile():
226                return False
227        return True
228
229    def MakeBuildef(self):
230
231        if not make_buildef(globle.home_path,self.kconf_dir,"CREATE"):
232            sys.exit(1)
233        log_msg('info', 'make_buildef_file.sh %s successfully.' % self.kconf_dir)
234
235# argv[1]: cpu_plat 表示要编译的平台:
236# argv[2]: compile_option 控制编译选项,调用不同的cmake参数,目前只有normal coverity hllt fortify single(是否编译安全c,组件化独立构建需求)
237# argv[3]: lib_run_type lib库要跑的平台 faga sim等
238# argv[4]: make_choice
239# argv[5]: make_phase 全量构建选项
240# argv[6]: UniProton_packing_path lib库的安装位置
241if __name__ == "__main__":
242    default_para = ("all", "normal", "FPGA", "ALL", "ALL", "")
243    if len(argv) == 1:
244        para = [default_para[i] for i in range(0, len(default_para))]
245    else:
246        para = [argv[i+1] if i < len(argv) - 1 else default_para[i] for i in range(0,len(default_para))]
247
248    cur_cpu_type = para[0].lower()
249    cur_compile_option = para[1].lower()
250    cur_lib_run_type = para[2]
251    cur_make_choice = para[3]
252    cur_make_phase = para[4]
253    cur_UniProton_packing_path = para[5]
254    for plat in globle.cpus_[cur_cpu_type]:
255        UniProton_build = Compile(plat, cur_compile_option, cur_lib_run_type, cur_make_choice, cur_make_phase, cur_UniProton_packing_path)
256        if not UniProton_build.UniProtonCompile():
257            sys.exit(1)
258    sys.exit(0)
259
260