初始提交
This commit is contained in:
471
build/script/cmake_builder.py
Executable file
471
build/script/cmake_builder.py
Executable file
@@ -0,0 +1,471 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import re
|
||||
|
||||
from utils.build_utils import exec_shell, root_path, output_root, sdk_output_path, pkg_tools_path
|
||||
from utils.build_utils import compare_bin
|
||||
from enviroment import TargetEnvironment, BuildEnvironment
|
||||
from pack_tool import packTool
|
||||
from sdk_generator.sdk_generator import SdkGenerator
|
||||
from rom_ram_callback.gen_rom_ram_callback import gen_rom_ram_callback
|
||||
from rom_ram_callback.strip_undef_symbols import strip_undefined_symbols
|
||||
from usr_config import mconfig
|
||||
from custom_cmd import run_custom_cmd
|
||||
from target_config.common_config import CommonConfig
|
||||
def copy_file(src, dst):
|
||||
try:
|
||||
shutil.copy2(src, dst)
|
||||
except FileNotFoundError:
|
||||
print(f"error 01") #文件不存在
|
||||
except PermissionError:
|
||||
print(f"error 02") #没有权限复制
|
||||
except Exception as e:
|
||||
print(f"error 03 [{e}]") #复制文件时发生错误
|
||||
|
||||
class CMakeBuilder(BuildEnvironment):
|
||||
""" cmake builder, 接收并解析参数,启动构建
|
||||
"""
|
||||
def __init__(self, param_list):
|
||||
super(CMakeBuilder, self).__init__(param_list)
|
||||
self.cmake_cmd = []
|
||||
self.sdk = None
|
||||
self.pack_tool = None
|
||||
|
||||
def get_component(self, env):
|
||||
com_config = CommonConfig(env.get('arch'))
|
||||
components = []
|
||||
if env.get('just_build_components', False):
|
||||
just_build_components = env.get('just_build_components', False)
|
||||
else:
|
||||
just_build_components = self.component
|
||||
for component in just_build_components:
|
||||
if component in env.get('ram_component', False):
|
||||
components.append(component)
|
||||
continue
|
||||
if component not in env.get('ram_component_set', False):
|
||||
continue
|
||||
for comm in com_config.get_component_set(component):
|
||||
if comm in env.get('ram_component', False):
|
||||
components.append(comm)
|
||||
return components
|
||||
|
||||
def get_build_cmd(self, env):
|
||||
ext_cmd = []
|
||||
components = self.get_component(env)
|
||||
ext_cmd.extend(components)
|
||||
if self.generator == 'Ninja':
|
||||
return ['ninja'] + ext_cmd + ['-j%d' % self.thread]
|
||||
else:
|
||||
return ['make'] + ext_cmd + ['-j%d' % self.thread]
|
||||
|
||||
def build(self):
|
||||
"""
|
||||
"""
|
||||
built_targets = []
|
||||
for group in self.group_names:
|
||||
need_pack = False
|
||||
if group.startswith('pack'):
|
||||
need_pack = True
|
||||
chip = self.get_chip_name(group)
|
||||
if os.path.exists(os.path.join(output_root, 'package', chip, group)):
|
||||
shutil.rmtree(os.path.join(output_root, 'package', chip, group))
|
||||
|
||||
for target in self.get_target_names_by_group_name(group):
|
||||
self.pack_tool = packTool(group, target)
|
||||
if self.is_group(target):
|
||||
self.group_names.append(target)
|
||||
continue
|
||||
|
||||
if self.is_copy_target(target):
|
||||
self.pack_tool.pack()
|
||||
continue
|
||||
|
||||
if target == 'fwpkg' and need_pack:
|
||||
self.pack_fwpkg(chip, group)
|
||||
continue
|
||||
|
||||
if not self.is_target(target):
|
||||
print("Invalid target %s" % target)
|
||||
raise
|
||||
if not target in built_targets:
|
||||
self.build_target(target)
|
||||
built_targets.append(target)
|
||||
else:
|
||||
print("%s has built, skip" % target)
|
||||
target_env = TargetEnvironment(target, self.extr_defines)
|
||||
if target_env.get('build_type') == 'SDK':
|
||||
continue
|
||||
if need_pack:
|
||||
self.pack_tool.pack()
|
||||
|
||||
if len(self.target_names) == 1 and self.open_kconfig == True:
|
||||
self.menuconfig_to_build(self.target_names[0])
|
||||
return
|
||||
|
||||
for target in self.target_names:
|
||||
self.build_target(target)
|
||||
|
||||
def menuconfig_to_build(self, target):
|
||||
env = TargetEnvironment(target)
|
||||
mconfig(self.kconfig_param, env.get("chip"), env.get("core"), target, None)
|
||||
|
||||
def build_target(self, target):
|
||||
env = TargetEnvironment(target, self.extr_defines)
|
||||
if env.get('build_type') == 'SDK':
|
||||
self.build_sdk(env)
|
||||
return
|
||||
if not run_custom_cmd(env, target, 'build_pre'):
|
||||
self.print_build_result(target, 1)
|
||||
sys.exit(1)
|
||||
|
||||
self.compile_target(target, env)
|
||||
|
||||
if env.get('just_build_components'):
|
||||
return
|
||||
|
||||
if env.get("fs_image"):
|
||||
fs_image_path = os.path.join(root_path, 'build', 'config', 'target_config', env.get('chip'), 'mk_fs_image')
|
||||
fs_script_path = os.path.join(fs_image_path, 'mkyaffs2tool.py')
|
||||
output_path = env.get_output_path()
|
||||
print(output_path)
|
||||
errcode = exec_shell([self.python_path, fs_script_path, output_path], None, True)
|
||||
if errcode != 0:
|
||||
print("creat fs image error!")
|
||||
self.print_build_result(target, errcode)
|
||||
sys.exit(1)
|
||||
print("fs image success!")
|
||||
|
||||
if env.get('upg_pkg'):
|
||||
self.pack_fota(env.get('chip'), target, env.get('upg_pkg'))
|
||||
|
||||
if not run_custom_cmd(env, target, 'build_post'):
|
||||
self.print_build_result(target, 1)
|
||||
sys.exit(1)
|
||||
|
||||
if env.get('packet') :
|
||||
self.pack_fwpkg(env.get('chip'), target)
|
||||
|
||||
def build_sdk(self, env):
|
||||
self.sdk = SdkGenerator(env, sdk_output_path)
|
||||
if os.path.exists(sdk_output_path):
|
||||
print("Cleaning SDK output path")
|
||||
shutil.rmtree(sdk_output_path)
|
||||
sdk_pkg_target_name = env.get('pkg_target_name', cmake_type=False)
|
||||
|
||||
for sdk_target in sdk_pkg_target_name:
|
||||
sdk_target_env = TargetEnvironment(sdk_target, self.extr_defines)
|
||||
output_path = sdk_target_env.get_output_path()
|
||||
self.compile_target(sdk_target, sdk_target_env)
|
||||
self.sdk.copy_depends('%s/cmake_trace.txt' % output_path)
|
||||
if self.sdk.env.get('reload_kconfig'):
|
||||
cwd = os.getcwd()
|
||||
os.chdir(sdk_output_path)
|
||||
mconfig('reloadconfig', sdk_target_env.get("chip"), sdk_target_env.get("core"), sdk_target, None, root=sdk_output_path)
|
||||
os.chdir(cwd)
|
||||
|
||||
if env.get('config') and 'lib_gen' in env.get('config'):
|
||||
lib_gen_tasks = env.get('config')['lib_gen']
|
||||
print(lib_gen_tasks)
|
||||
for libs in lib_gen_tasks:
|
||||
task = lib_gen_tasks[libs]
|
||||
target_name = task['base_target_name']
|
||||
defines = task.get("defines", [])
|
||||
self.component = task['components']
|
||||
target_env = TargetEnvironment(target_name, extra_defines=defines)
|
||||
target_env.add("LIB_GEN_NAME", libs)
|
||||
target_env.extend("SDK_LIBGEN_COMPONENTS", self.component)
|
||||
self.compile_target(target_name, target_env)
|
||||
self.sdk.sdk_build(self.build_time, self.no_hso, self.build_level)
|
||||
self.sdk = None
|
||||
self.component = []
|
||||
|
||||
def compile_target(self, target_name, env):
|
||||
start_time = time.time()
|
||||
self.deal_symbol_link(env)
|
||||
env.add('build_level', self.build_level)
|
||||
if self.build_level == "debug":
|
||||
env.extend("ccflags", ['-funwind-tables', '-fasynchronous-unwind-tables'])
|
||||
env.extend("defines", "NO_TIMEOUT")
|
||||
if self.build_as_lib:
|
||||
env.add("GEN_ONLY_LIB_PATH")
|
||||
self.cmake_cmd = ['cmake', '-G', self.generator, '-Wno-dev', '--no-warn-unused-cli', '-DCMAKE_C_COMPILER_WORKS=TRUE', '-DCMAKE_CXX_COMPILER_WORKS=TRUE']
|
||||
if env.get('fp_enable'):
|
||||
env.append('defines', 'SUPPORT_CALLSTACK')
|
||||
env.append('ccflags', '-fno-omit-frame-pointer')
|
||||
self.add_build_param(env)
|
||||
|
||||
output_path = env.get_output_path()
|
||||
self.pre_sdk(output_path, env)
|
||||
if env.get('libstd_option'):
|
||||
self.add_cmake_def(env, 'std_libs')
|
||||
self.cmake_cmd.append(root_path)
|
||||
|
||||
if env.get('product_type'):
|
||||
self.cmake_cmd.append('-DPRODUCT_TYPE={0}'.format(env.get('product_type')))
|
||||
else:
|
||||
self.cmake_cmd.append('-DPRODUCT_TYPE=default')
|
||||
|
||||
if self.dump:
|
||||
env.dump()
|
||||
|
||||
if self.rom_callback(env, target_name, output_path):
|
||||
if not os.path.exists(output_path):
|
||||
os.makedirs(output_path)
|
||||
env.set('build_rom_callback', False)
|
||||
env.append('defines', '_PRE_FEATURE_VENEER_ROM')
|
||||
env.append('ram_component', 'rom_callback')
|
||||
self.redef_cmake_def(env, 'build_rom_callback')
|
||||
self.redef_cmake_def(env, 'defines')
|
||||
self.redef_cmake_def(env, 'ram_component')
|
||||
self.add_cmake_param("-DROM_CHECK=False")
|
||||
self.start(env, target_name, output_path, clean=self.need_clean, nhso=self.no_hso)
|
||||
self.rom_check(env, target_name, output_path)
|
||||
|
||||
end_time = time.time()
|
||||
print("%s takes %f s" % (target_name, end_time - start_time))
|
||||
|
||||
def deal_symbol_link(self, env):
|
||||
if "rom_sym_path" not in env.config:
|
||||
return
|
||||
if self.no_symbol_link and not self.sdk:
|
||||
env.config["rom_sym_path"] = ""
|
||||
else:
|
||||
env.config["rom_sym_path"] = env.config["rom_sym_path"].replace("<root>", root_path)
|
||||
if os.path.exists(env.config["rom_sym_path"]):
|
||||
env.config["linkflags"].append("-Wl,--just-symbols=" + env.config["rom_sym_path"])
|
||||
env.config["defines"].append("ROM_SYMBOL_LINK")
|
||||
else:
|
||||
print("ERROR: rom_sym_path %s is not exists" % env.config["rom_sym_path"])
|
||||
if "bootrom_sym_path" not in env.config:
|
||||
return
|
||||
if env.config["bootrom_sym_path"] != "":
|
||||
env.config["bootrom_sym_path"] = env.config["bootrom_sym_path"].replace("<root>", root_path)
|
||||
if os.path.exists(env.config["bootrom_sym_path"]):
|
||||
env.config["linkflags"].append("-Wl,--just-symbols=" + env.config["bootrom_sym_path"])
|
||||
env.config["defines"].append("BOOTROM_SYMBOL_LINK")
|
||||
else:
|
||||
print("ERROR: bootrom_sym_path %s is not exists" % env.config["bootrom_sym_path"])
|
||||
|
||||
def add_build_param(self, env):
|
||||
for item in env.config:
|
||||
self.add_cmake_def(env, item)
|
||||
self.add_cmake_param('-DCMAKE_TOOLCHAIN_FILE=%s' % env.get_tool_chain())
|
||||
self.add_cmake_param('-DPY_PATH=%s' % self.python_path)
|
||||
if self.build_time != '':
|
||||
self.add_cmake_param('-DBUILD_TIME=%s' % self.build_time)
|
||||
|
||||
def pre_sdk(self, output_path, env):
|
||||
if not self.sdk:
|
||||
return
|
||||
|
||||
self.sdk.register_org_target_path(output_path)
|
||||
self.add_cmake_param('-DSDK_OUTPUT_PATH=%s' % sdk_output_path)
|
||||
self.add_cmake_def(self.sdk.env, 'sdk_type')
|
||||
# closed_components takes precedence over open_components
|
||||
closed_components = self.sdk.env.get('closed_components', cmake_type=False)
|
||||
open_components = self.sdk.env.get('open_components', cmake_type=False)
|
||||
if None not in (closed_components, open_components):
|
||||
raise Exception(f'ERROR! closed_components and open_components cannot be set together!')
|
||||
self.add_cmake_def(self.sdk.env, 'closed_components')
|
||||
if not closed_components:
|
||||
self.add_cmake_def(self.sdk.env, 'open_components')
|
||||
|
||||
self.add_cmake_def(env, 'main_component')
|
||||
|
||||
# export trace of cmake invocation
|
||||
cmake_trace_file = os.path.join(output_path, 'cmake_trace.txt')
|
||||
self.cmake_cmd.append('--trace-format=json-v1')
|
||||
self.cmake_cmd.append('--trace-redirect=%s' % cmake_trace_file)
|
||||
|
||||
def print_build_result(self, target_name, fail):
|
||||
print("######### Build target:%s %s" % (target_name, "failed" if fail else "success"))
|
||||
if self.sdk:
|
||||
print("######### Build sdk %s!!" % ("failed" if fail else "success"))
|
||||
|
||||
def rom_callback(self, env, target_name, output_path):
|
||||
if not env.get('build_rom_callback'):
|
||||
return False
|
||||
if env.get('fixed_rom'):
|
||||
return True
|
||||
self.start(env, target_name, output_path, nhso=True, clean=self.need_clean)
|
||||
print("GENERATING AUTO ROM BIN FILE!!!")
|
||||
chip = env.get("chip")
|
||||
core = env.get("core")
|
||||
board = env.get('board')
|
||||
application = env.get('application')
|
||||
arch = env.get('arch')
|
||||
rom_config = os.path.join(root_path, 'drivers', 'chips', chip, 'rom_config', core)
|
||||
rom_output = os.path.join(rom_config, 'output')
|
||||
if not os.path.exists(rom_output):
|
||||
os.makedirs(rom_output)
|
||||
|
||||
shutil.copy(os.path.join(output_path, "rom_bin_raw.undef"), rom_output)
|
||||
shutil.copy(os.path.join(output_path, "rom_symbol.list"), rom_output)
|
||||
shutil.copy(os.path.join(output_path, "rom_bin.rel"), rom_output)
|
||||
shutil.copy(os.path.join(output_path, "image_symbol.list"), rom_output)
|
||||
shutil.copy(os.path.join(rom_config, "undef_rom_filter.list"), rom_output)
|
||||
shutil.copy(os.path.join(rom_config, "region.list"), rom_output)
|
||||
|
||||
strip_undefined_symbols(rom_output)
|
||||
if arch[:5] == "riscv":
|
||||
target = "riscv32"
|
||||
elif arch[:3] == "arm":
|
||||
target = "arm32"
|
||||
gen_rom_ram_callback(target, rom_output)
|
||||
print("ROM CALLBACK BUILD SUCCESSFULLY!!!")
|
||||
shutil.rmtree(output_path)
|
||||
return True
|
||||
|
||||
def start(self, env, target_name, output_path, nhso=None, clean=None):
|
||||
# remember the root folder
|
||||
def _excute(cmd, log_file, is_dump):
|
||||
errcode = exec_shell(cmd, log_file, is_dump)
|
||||
if errcode != 0:
|
||||
self.print_build_result(target_name, errcode)
|
||||
sys.exit(1)
|
||||
org_work_path = os.getcwd()
|
||||
self.cmake_cmd.append('-DPKG_TARGET_NAME=%s' % target_name)
|
||||
target_name = target_name.replace('-', "_")
|
||||
if clean and os.path.exists(output_path):
|
||||
shutil.rmtree(output_path)
|
||||
if not os.path.exists(output_path):
|
||||
os.makedirs(output_path)
|
||||
self.cmake_cmd.append('-DBUILD_TARGET_NAME=%s' % (target_name))
|
||||
self.cmake_cmd.append('-DNHSO=%s' %nhso)
|
||||
chip = env.get('chip')
|
||||
core = env.get('core')
|
||||
|
||||
# Generate the menuconfig header.
|
||||
mconfig_file_path = os.path.join(root_path, 'build', 'config', 'target_config', chip, 'menuconfig', core, f"{target_name}.config")
|
||||
if os.path.exists(mconfig_file_path):
|
||||
if env.get('reload_kconfig'):
|
||||
print("build reload %s" %mconfig_file_path)
|
||||
mconfig("reloadconfig", chip, core, target_name, output_path)
|
||||
mconfig("savemenuconfig", chip, core, target_name, output_path)
|
||||
|
||||
os.chdir(output_path)
|
||||
log_file_name = "build_%s.log" % target_name
|
||||
log_file = os.path.join(output_root, chip, log_file_name)
|
||||
|
||||
# run 'make'
|
||||
if self.is_command_refresh(output_path):
|
||||
self.dump_cmake_command(output_path)
|
||||
_excute(self.cmake_cmd, log_file, self.dump)
|
||||
_excute(self.get_build_cmd(env), log_file, self.dump)
|
||||
else:
|
||||
ext_cmd = []
|
||||
components_target = self.get_component(env)
|
||||
print(components_target)
|
||||
if components_target:
|
||||
ext_cmd = ['--target'] + components_target
|
||||
_excute(["cmake", "--build", output_path, '-j%d' % self.thread] + ext_cmd, log_file, self.dump)
|
||||
|
||||
if len(self.get_component(env)) > 0:
|
||||
os.chdir(org_work_path)
|
||||
print("######### Build target:%s, component:[%s] success" % (target_name, ' '.join(self.get_component(env))))
|
||||
return 0
|
||||
|
||||
if env.is_enable_hso() and not nhso:
|
||||
cmd = self.get_build_cmd(env)
|
||||
cmd.append("HSO_DB")
|
||||
_excute(cmd, log_file, self.dump)
|
||||
|
||||
# switch the work folder back
|
||||
os.chdir(org_work_path)
|
||||
self.print_build_result(target_name, 0)
|
||||
return 0
|
||||
|
||||
def add_cmake_param(self, param):
|
||||
"""
|
||||
accept string only
|
||||
"""
|
||||
self.cmake_cmd.append(param)
|
||||
|
||||
def add_cmake_def(self, env, item):
|
||||
if env.get(item) is None or env.get(item) == '':
|
||||
return
|
||||
self.cmake_cmd.append('-D%s=%s' % (item.upper(), env.get(item)))
|
||||
|
||||
def redef_cmake_def(self, env, item):
|
||||
if env.get(item) is None or env.get(item) == '':
|
||||
return
|
||||
val = env.get(item)
|
||||
item = item.upper()
|
||||
for i, para in enumerate(self.cmake_cmd):
|
||||
if not para.startswith('-D%s=' % item):
|
||||
continue
|
||||
self.cmake_cmd[i] = '-D%s=%s' % (item, val)
|
||||
break
|
||||
|
||||
def rom_check(self, env, target_name, output_path):
|
||||
if env.get('rom_sym_path'):
|
||||
return True
|
||||
|
||||
if env.get('fixed_rom'):
|
||||
fix_path = env.get('fixed_rom_path').replace('<root>', root_path)
|
||||
bin1 = os.path.join(output_path, '%s_rom.bin' % env.get('bin_name'))
|
||||
bin2 = fix_path
|
||||
if not compare_bin(bin1, bin2):
|
||||
print(f"ERROR! :{bin1} is not same with {bin2}")
|
||||
sys.exit(1)
|
||||
return True
|
||||
|
||||
if env.get('rom_ram_check'):
|
||||
self.add_cmake_param("-DROM_CHECK=True")
|
||||
self.start(env, target_name, output_path, clean=False, nhso=True)
|
||||
if not env.get('rom_ram_compare'):
|
||||
return True
|
||||
bin1 = os.path.join(output_path, '%s_rom.bin' % env.get('bin_name'))
|
||||
bin2 = os.path.join(output_path, '%s_romcheck_rom.bin' % env.get('bin_name'))
|
||||
if not compare_bin(bin1, bin2):
|
||||
print(f"ERROR! :{bin1} is not same with {bin2}")
|
||||
sys.exit(1)
|
||||
|
||||
def pack_fwpkg(self, chip, target_name):
|
||||
# bin packet all in one
|
||||
packet_script_path = os.path.join(pkg_tools_path, 'packet.py')
|
||||
print("packet ing...")
|
||||
errcode = exec_shell([self.python_path, packet_script_path, chip, target_name, " ".join(self.extr_defines)], None, True)
|
||||
if errcode != 0:
|
||||
print("packet error!")
|
||||
self.print_build_result(target_name, errcode)
|
||||
sys.exit(1)
|
||||
|
||||
os.system('python3 build/config/target_config/ws63/build_ws63_update.py --pkt=app_iot') #BY _HSF_ Hilink OTA
|
||||
|
||||
copy_file("output/ws63/fwpkg/ws63-liteos-app-iot/ws63-liteos-app-iot_mfg_all.fwpkg", "output/LPT262_hilink_MFG.fwpkg") # ====>BY _HSF
|
||||
copy_file("output/ws63/fwpkg/ws63-liteos-app-iot/ws63-liteos-app-iot_all.fwpkg", "output/LPT262_hilink.fwpkg")
|
||||
copy_file("output/ws63/upgrade/update.fwpkg", "output/LPT262_hilink_UPGRADE.bin")
|
||||
|
||||
print("packet success!")
|
||||
print (time.strftime("%Y年%m月%d日")+" ("+time.strftime("%H:%M:%S")+")")
|
||||
|
||||
|
||||
|
||||
def pack_fota(self, chip, target_name, option):
|
||||
fota_script_path = os.path.join(root_path, 'build', 'config', 'target_config', chip, 'build_' + chip + '_update.py')
|
||||
print("fota packet generating...")
|
||||
errcode = exec_shell([self.python_path, fota_script_path, target_name, option], None, True)
|
||||
if errcode != 0:
|
||||
print("fota packet error!")
|
||||
self.print_build_result(target_name, errcode)
|
||||
sys.exit(1)
|
||||
print("fota packet success!")
|
||||
|
||||
def dump_cmake_command(self, output_path):
|
||||
with open(os.path.join(output_path, 'cmake_command.txt'), "w") as f:
|
||||
f.write("\n".join(self.cmake_cmd))
|
||||
|
||||
def is_command_refresh(self, output_path):
|
||||
cmd_path = os.path.join(output_path, 'cmake_command.txt')
|
||||
if not os.path.exists(cmd_path):
|
||||
return True
|
||||
with open(cmd_path, "r") as f:
|
||||
text = f.read()
|
||||
return text != "\n".join(self.cmake_cmd)
|
||||
Reference in New Issue
Block a user