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