build_soc.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import os
  2. import shutil
  3. import logging
  4. import subprocess
  5. from pathlib import Path
  6. from typing import List
  7. logger = logging.getLogger(__name__)
  8. class BuildSOCError(Exception):
  9. """SOC 编译异常"""
  10. pass
  11. def prepare_soc(mcu_sdk_dir: str, soc_dir: str, soc_project: str):
  12. """
  13. 将 MCU 编译产物拷贝到 SOC 的 hbbin/mcubin/deploy/ (或 deploy_dv/)。
  14. 对应原 Shell 的 prepare_for_compile_soc()。
  15. """
  16. # MCU 输出目录
  17. mcu_output = os.path.join(mcu_sdk_dir, 'output', 'dbg')
  18. if not os.path.isdir(mcu_output):
  19. raise BuildSOCError(f"MCU output directory not found: {mcu_output}")
  20. # 确定目标目录:deploy 或 deploy_dv
  21. if 'DV' in soc_project.upper():
  22. deploy_dir = os.path.join(soc_dir, 'hbbin', 'mcubin', 'deploy_dv')
  23. else:
  24. deploy_dir = os.path.join(soc_dir, 'hbbin', 'mcubin', 'deploy')
  25. os.makedirs(deploy_dir, exist_ok=True)
  26. # 复制 J6_MCU.zip
  27. src_zip = os.path.join(mcu_output, 'J6_MCU.zip')
  28. if os.path.isfile(src_zip):
  29. shutil.copy2(src_zip, deploy_dir)
  30. logger.info("Copied %s to %s", src_zip, deploy_dir)
  31. else:
  32. raise BuildSOCError(f"Missing MCU archive: {src_zip}")
  33. # 复制 .map 和 .elf 文件
  34. for item in os.listdir(mcu_output):
  35. if item.endswith('.map') or item.endswith('.elf'):
  36. src = os.path.join(mcu_output, item)
  37. if os.path.isfile(src):
  38. shutil.copy2(src, deploy_dir)
  39. logger.info("Copied %s to %s", src, deploy_dir)
  40. def compile_soc(soc_dir: str, soc_project: str,
  41. secure_enable: bool = False,
  42. factory_emmc_img_enable: bool = False,
  43. profile_mode: str = 'Debug'):
  44. """
  45. 执行 SOC 编译和部署。
  46. 对应原 Shell 的 compile_soc()。
  47. """
  48. # 切换到 SOC 根目录
  49. original_cwd = os.getcwd()
  50. os.chdir(soc_dir)
  51. try:
  52. # 检查 QNX 工具链
  53. if not os.path.isdir('/opt/qnx800'):
  54. raise BuildSOCError("QNX toolchain not found: /opt/qnx800")
  55. # 建立软链接(如果不存在)
  56. target_link = os.path.join('build_tools', 'Compiler', 'qnx800')
  57. if not os.path.islink(target_link) and not os.path.exists(target_link):
  58. os.makedirs(os.path.dirname(target_link), exist_ok=True)
  59. os.symlink('/opt/qnx800', target_link)
  60. logger.info("Created symlink: %s -> /opt/qnx800", target_link)
  61. # 1. 编译镜像
  62. build_cmd = ['./build-tools/build.sh', '-c', 'invo-all-image']
  63. logger.info("SOC compile: %s", ' '.join(build_cmd))
  64. subprocess.run(build_cmd, check=True)
  65. # 2. 部署镜像(生成所有需要的镜像文件)
  66. deploy_cmd = ['./build-tools/build.sh'] + _build_deploy_args(soc_project,
  67. secure_enable,
  68. factory_emmc_img_enable,
  69. profile_mode) + ['-b', 'invo-all-image']
  70. logger.info("SOC deploy: %s", ' '.join(deploy_cmd))
  71. subprocess.run(deploy_cmd, check=True)
  72. except subprocess.CalledProcessError as e:
  73. raise BuildSOCError(f"SOC build failed: {e}") from e
  74. finally:
  75. os.chdir(original_cwd)
  76. def _build_deploy_args(soc_project: str, secure_enable: bool,
  77. factory_emmc_img_enable: bool, profile_mode: str) -> List[str]:
  78. """
  79. 构造部署命令的额外参数。
  80. 对应原 Shell 的 extra_para 逻辑。
  81. """
  82. args = []
  83. # DV 项目添加 -d
  84. if 'DV' in soc_project.upper():
  85. args.append('-d')
  86. # 安全编译
  87. if secure_enable:
  88. args.append('-s')
  89. # 工厂 eMMC 镜像
  90. if factory_emmc_img_enable:
  91. args.append('-f')
  92. # Release 模式
  93. if profile_mode == 'Release':
  94. args.append('-r')
  95. return args