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