LPT26x-HSF-4MB-Hilink_14.2..../build/script/cmake_builder.py
2025-05-13 22:00:58 +08:00

472 lines
20 KiB
Python
Executable File

#!/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)