已合并
[installation] 支持msot按需打包 #104
wanghaopeng创建于 7月6日
[installation] 支持msot按需打包 #104
已合并
共 4 个文件变更+161-26
| @@ -34,12 +34,52 @@ if(BUILD_TESTS) | |||
| 34 | set(BUILD_ARG test) | 34 | set(BUILD_ARG test) |
| 35 | endif() | 35 | endif() |
| 36 | 36 | ||
| 37 | -include(cmake/module/msdebug.cmake) | 37 | +# 顶层总包支持的子工具列表。排除能力按这些 CMake 模块粒度生效, |
| 38 | -include(cmake/module/mskl.cmake) | 38 | +# 其中 msopgen 模块会同时产出 msopgen 与 msopst 两个 whl。 |
| 39 | -include(cmake/module/mskpp.cmake) | 39 | +set(MSOT_VALID_TOOLS msdebug mskl mskpp msopgen msopprof mssanitizer) |
| 40 | -include(cmake/module/msopgen.cmake) | 40 | + |
| 41 | -include(cmake/module/msopprof.cmake) | 41 | +# CMake 直接调用时也可以使用该变量;build.py 的 --exclude-tools 会透传到这里。 |
| 42 | -include(cmake/module/mssanitizer.cmake) | 42 | +set(MSOT_EXCLUDE_TOOLS "" CACHE STRING "Comma-separated msOT sub-tools excluded from build/package") |
| 43 | + | ||
| 44 | +# 将用户传入的逗号分隔字符串归一化为列表:去空、转小写、去重,并做白名单校验。 | ||
| 45 | +set(MSOT_EXCLUDED_TOOL_LIST "") | ||
| 46 | +if(MSOT_EXCLUDE_TOOLS) | ||
| 47 | + string(REPLACE "," ";" MSOT_EXCLUDE_TOOL_RAW_LIST "${MSOT_EXCLUDE_TOOLS}") | ||
| 48 | + foreach(TOOL_NAME IN LISTS MSOT_EXCLUDE_TOOL_RAW_LIST) | ||
| 49 | + string(STRIP "${TOOL_NAME}" TOOL_NAME) | ||
| 50 | + string(TOLOWER "${TOOL_NAME}" TOOL_NAME) | ||
| 51 | + if(TOOL_NAME STREQUAL "") | ||
| 52 | + continue() | ||
| 53 | + endif() | ||
| 54 | + list(FIND MSOT_VALID_TOOLS "${TOOL_NAME}" TOOL_INDEX) | ||
| 55 | + if(TOOL_INDEX EQUAL -1) | ||
| 56 | + message(FATAL_ERROR "Unsupported MSOT_EXCLUDE_TOOLS item: ${TOOL_NAME}. Supported tools: ${MSOT_VALID_TOOLS}") | ||
| 57 | + endif() | ||
| 58 | + list(FIND MSOT_EXCLUDED_TOOL_LIST "${TOOL_NAME}" EXISTING_TOOL_INDEX) | ||
| 59 | + if(EXISTING_TOOL_INDEX EQUAL -1) | ||
| 60 | + list(APPEND MSOT_EXCLUDED_TOOL_LIST "${TOOL_NAME}") | ||
| 61 | + endif() | ||
| 62 | + endforeach() | ||
| 63 | +endif() | ||
| 64 | + | ||
| 65 | +# 归一化后的字符串用于传给 parser,也写入配置依赖文件,保证排除项变化会重新触发打包。 | ||
| 66 | +string(JOIN "," MSOT_EXCLUDE_TOOLS_NORMALIZED ${MSOT_EXCLUDED_TOOL_LIST}) | ||
| 67 | +if(MSOT_EXCLUDE_TOOLS_NORMALIZED) | ||
| 68 | + message(STATUS "Exclude msOT sub-tools: ${MSOT_EXCLUDE_TOOLS_NORMALIZED}") | ||
| 69 | +endif() | ||
| 70 | + | ||
| 71 | +# 只 include 未排除的子工具模块。被排除模块不会创建对应 package_* target, | ||
| 72 | +# 因而既不会构建,也不会作为 package_msot 的前置依赖。 | ||
| 73 | +set(MSOT_PACKAGE_TARGETS "") | ||
| 74 | +foreach(TOOL_NAME IN LISTS MSOT_VALID_TOOLS) | ||
| 75 | + list(FIND MSOT_EXCLUDED_TOOL_LIST "${TOOL_NAME}" TOOL_INDEX) | ||
| 76 | + if(TOOL_INDEX EQUAL -1) | ||
| 77 | + include(cmake/module/${TOOL_NAME}.cmake) | ||
| 78 | + list(APPEND MSOT_PACKAGE_TARGETS package_${TOOL_NAME}) | ||
| 79 | + else() | ||
| 80 | + message(STATUS "Skip msOT sub-tool target: ${TOOL_NAME}") | ||
| 81 | + endif() | ||
| 82 | +endforeach() | ||
| 43 | 83 | ||
| 44 | # 根据构建环境信息生成scene.info | 84 | # 根据构建环境信息生成scene.info |
| 45 | string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM) | 85 | string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM) |
| @@ -73,6 +113,18 @@ set(installShell share/info/${NAME}/script/install.sh) | |||
| 73 | set(comments "ASCEND MINDSTUDIO SANITIZER RUN PACKAGE") | 113 | set(comments "ASCEND MINDSTUDIO SANITIZER RUN PACKAGE") |
| 74 | file(GLOB_RECURSE PACAKGE_SCRIPT_FILES ${ROOT_DIR}/package/**/*) | 114 | file(GLOB_RECURSE PACAKGE_SCRIPT_FILES ${ROOT_DIR}/package/**/*) |
| 75 | 115 | ||
| 116 | +# 自定义命令的 DEPENDS 需要一个可跟踪文件;排除列表变化时更新该文件, | ||
| 117 | +# 避免 CMake 认为 package.flag 已经是最新而复用上一次的总包内容。 | ||
| 118 | +set(MSOT_PACKAGE_CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/msot_package_config.txt) | ||
| 119 | +file(WRITE "${MSOT_PACKAGE_CONFIG_FILE}" "MSOT_EXCLUDE_TOOLS=${MSOT_EXCLUDE_TOOLS_NORMALIZED}\n") | ||
| 120 | + | ||
| 121 | +# parser 负责生成 filelist.csv 并复制总包内容;这里把同一份排除列表传进去, | ||
| 122 | +# 让最终 run 包目录也跳过对应 whl/run 文件。 | ||
| 123 | +set(MSOT_PARSER_EXCLUDE_ARGS "") | ||
| 124 | +if(MSOT_EXCLUDE_TOOLS_NORMALIZED) | ||
| 125 | + list(APPEND MSOT_PARSER_EXCLUDE_ARGS --exclude_tools ${MSOT_EXCLUDE_TOOLS_NORMALIZED}) | ||
| 126 | +endif() | ||
| 127 | + | ||
| 76 | file(GLOB_RECURSE MAKESELF_TAR_FILE_GLOB ${ROOT_DIR}/thirdparty/makeself/makeself-*.tar.gz) | 128 | file(GLOB_RECURSE MAKESELF_TAR_FILE_GLOB ${ROOT_DIR}/thirdparty/makeself/makeself-*.tar.gz) |
| 77 | file(GLOB_RECURSE MAKESELF_PATCH_FILE_GLOB ${ROOT_DIR}/thirdparty/makeself/makeself-*.patch) | 129 | file(GLOB_RECURSE MAKESELF_PATCH_FILE_GLOB ${ROOT_DIR}/thirdparty/makeself/makeself-*.patch) |
| 78 | list(GET MAKESELF_TAR_FILE_GLOB 0 MAKESELF_TAR_FILE) | 130 | list(GET MAKESELF_TAR_FILE_GLOB 0 MAKESELF_TAR_FILE) |
| @@ -96,20 +148,18 @@ add_custom_command( | |||
| 96 | # 解析打包配置文件filelist.xml,并完成打包 | 148 | # 解析打包配置文件filelist.xml,并完成打包 |
| 97 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/package.flag | 149 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/package.flag |
| 98 | COMMAND ${CMAKE_COMMAND} -E copy "${ROOT_DIR}/package/conf/version.info" ${CMAKE_INSTALL_PREFIX} | 150 | COMMAND ${CMAKE_COMMAND} -E copy "${ROOT_DIR}/package/conf/version.info" ${CMAKE_INSTALL_PREFIX} |
| 151 | + # 清理总包 staging 目录,防止前一次构建留下的已排除子包被 makeself 再次打入 run 包。 | ||
| 152 | + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/${NAME} | ||
| 99 | COMMAND cd ${ROOT_DIR}/package/script/ && ${PYTHON} parser.py -x ${ROOT_DIR}/package/conf/filelist.xml | 153 | COMMAND cd ${ROOT_DIR}/package/script/ && ${PYTHON} parser.py -x ${ROOT_DIR}/package/conf/filelist.xml |
| 100 | - --delivery_path ${CMAKE_INSTALL_PREFIX} -o ${CMAKE_SYSTEM_PROCESSOR} | 154 | + --delivery_path ${CMAKE_INSTALL_PREFIX} -o ${CMAKE_SYSTEM_PROCESSOR} ${MSOT_PARSER_EXCLUDE_ARGS} |
| 101 | COMMAND cd ${CMAKE_INSTALL_PREFIX} && ${makeselfTool} --header ${makeselfHeader} --help-header ${helpInfo} --pigz | 155 | COMMAND cd ${CMAKE_INSTALL_PREFIX} && ${makeselfTool} --header ${makeselfHeader} --help-header ${helpInfo} --pigz |
| 102 | --complevel 4 --nocrc --nomd5 --sha256 --chown --tar-quietly ${NAME} ${packageName} ${comments} ${installShell} | 156 | --complevel 4 --nocrc --nomd5 --sha256 --chown --tar-quietly ${NAME} ${packageName} ${comments} ${installShell} |
| 103 | COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/package.flag | 157 | COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/package.flag |
| 104 | COMMAND chmod 750 ${CMAKE_INSTALL_PREFIX}/*.run | 158 | COMMAND chmod 750 ${CMAKE_INSTALL_PREFIX}/*.run |
| 105 | - DEPENDS ${PACAKGE_SCRIPT_FILES} ${ROOT_DIR}/package/conf/version.info ${makeselfTool} ${makeselfHeader} | 159 | + # package.flag 依赖未排除子工具 target,确保保留的子包产物先生成,再执行总包打包。 |
| 160 | + DEPENDS ${MSOT_PACKAGE_TARGETS} ${PACAKGE_SCRIPT_FILES} ${ROOT_DIR}/package/conf/version.info | ||
| 161 | + ${MSOT_PACKAGE_CONFIG_FILE} ${makeselfTool} ${makeselfHeader} | ||
| 106 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | 162 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| 107 | ) | 163 | ) |
| 108 | -add_custom_target(package_msot ALL DEPENDS | 164 | +# ALL 目标也只挂未排除子工具,避免 excluded 子工具在默认 make 中被构建。 |
| 109 | - package_msdebug | 165 | +add_custom_target(package_msot ALL DEPENDS ${MSOT_PACKAGE_TARGETS} ${CMAKE_CURRENT_BINARY_DIR}/package.flag) |
| 110 | - package_mskl | ||
| 111 | - package_mskpp | ||
| 112 | - package_msopgen | ||
| 113 | - package_msopprof | ||
| 114 | - package_mssanitizer | ||
| 115 | - ${CMAKE_CURRENT_BINARY_DIR}/package.flag) | ||
| @@ -28,6 +28,31 @@ from pathlib import Path | |||
| 28 | 28 | ||
| 29 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | 29 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') |
| 30 | 30 | ||
| 31 | +# 子工具排除粒度与顶层 CMake 模块保持一致;这里做第一层白名单校验, | ||
| 32 | +# 避免非法名字继续传到 CMake 后才失败。 | ||
| 33 | +SUPPORTED_TOOLS = ("msdebug", "mskl", "mskpp", "msopgen", "msopprof", "mssanitizer") | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +def normalize_excluded_tools(exclude_tools): | ||
| 37 | + """归一化 --exclude-tools 输入,输出稳定的 CMake 逗号分隔参数来源。""" | ||
| 38 | + if not exclude_tools: | ||
| 39 | + return [] | ||
| 40 | + | ||
| 41 | + normalized_tools = [] | ||
| 42 | + for tool in exclude_tools.split(','): | ||
| 43 | + # 支持用户输入空格和大小写混用;空片段来自尾逗号或连续逗号,直接忽略。 | ||
| 44 | + tool_name = tool.strip().lower() | ||
| 45 | + if not tool_name: | ||
| 46 | + continue | ||
| 47 | + if tool_name not in SUPPORTED_TOOLS: | ||
| 48 | + raise argparse.ArgumentTypeError( | ||
| 49 | + "Unsupported tool '%s'. Supported tools: %s" | ||
| 50 | + % (tool_name, ", ".join(SUPPORTED_TOOLS)) | ||
| 51 | + ) | ||
| 52 | + if tool_name not in normalized_tools: | ||
| 53 | + normalized_tools.append(tool_name) | ||
| 54 | + return normalized_tools | ||
| 55 | + | ||
| 31 | 56 | ||
| 32 | class BuildManager: | 57 | class BuildManager: |
| 33 | """ | 58 | """ |
| @@ -41,6 +66,7 @@ class BuildManager: | |||
| 41 | python build.py -r <revision> 指定依赖的内部源码仓(例如msopcom)的 Git 分支/标签/commit | 66 | python build.py -r <revision> 指定依赖的内部源码仓(例如msopcom)的 Git 分支/标签/commit |
| 42 | python build.py -v <version> 指定构建版本号,同时覆盖 --build-version 和 --whl-version | 67 | python build.py -v <version> 指定构建版本号,同时覆盖 --build-version 和 --whl-version |
| 43 | python build.py -e KEY=VALUE 指定额外构建选项,可多次使用 | 68 | python build.py -e KEY=VALUE 指定额外构建选项,可多次使用 |
| 69 | + python build.py --exclude-tools msdebug,msopprof 排除指定子工具 | ||
| 44 | 70 | ||
| 45 | 参数说明: | 71 | 参数说明: |
| 46 | - 参数: command : 构建动作: 为空时为全构建, local 为跳过依赖下载, test 为运行单元测试。 | 72 | - 参数: command : 构建动作: 为空时为全构建, local 为跳过依赖下载, test 为运行单元测试。 |
| @@ -48,6 +74,7 @@ class BuildManager: | |||
| 48 | - 参数: -v, --version : 指定构建版本号;若设置,则同时覆盖 --build-version 和 --whl-version 的值。 | 74 | - 参数: -v, --version : 指定构建版本号;若设置,则同时覆盖 --build-version 和 --whl-version 的值。 |
| 49 | - 参数: --build-version, --whl-version : 历史参数,保留用于兼容;设置了 --version 时以 --version 为准。 | 75 | - 参数: --build-version, --whl-version : 历史参数,保留用于兼容;设置了 --version 时以 --version 为准。 |
| 50 | - 参数: -e, --extra : 额外构建选项,格式为 KEY=VALUE,可多次指定。 | 76 | - 参数: -e, --extra : 额外构建选项,格式为 KEY=VALUE,可多次指定。 |
| 77 | + - 参数: --exclude-tools : 不构建且不打包指定子工具,逗号分隔。 | ||
| 51 | 78 | ||
| 52 | 产物归档: | 79 | 产物归档: |
| 53 | 产品构建完成后,归档到 artifacts/ 目录中。 | 80 | 产品构建完成后,归档到 artifacts/ 目录中。 |
| @@ -68,6 +95,11 @@ class BuildManager: | |||
| 68 | help='Build version, overrides --build-version and --whl-version if set') | 95 | help='Build version, overrides --build-version and --whl-version if set') |
| 69 | argument_parser.add_argument('-e', '--extra', metavar='KEY=VALUE', action='append', default=[], | 96 | argument_parser.add_argument('-e', '--extra', metavar='KEY=VALUE', action='append', default=[], |
| 70 | help='Extra build options in KEY=VALUE format, can be specified multiple times') | 97 | help='Extra build options in KEY=VALUE format, can be specified multiple times') |
| 98 | + # build.py 是用户入口,CMake 是实际构建入口;这里先完成校验和归一化, | ||
| 99 | + # run 阶段只需要把稳定列表透传给 MSOT_EXCLUDE_TOOLS。 | ||
| 100 | + argument_parser.add_argument('--exclude-tools', metavar='TOOLS', type=normalize_excluded_tools, default=[], | ||
| 101 | + help='Comma-separated tools excluded from build/package. Supported tools: %s' | ||
| 102 | + % ', '.join(SUPPORTED_TOOLS)) | ||
| 71 | self.parsed_arguments = argument_parser.parse_args() | 103 | self.parsed_arguments = argument_parser.parse_args() |
| 72 | 104 | ||
| 73 | if self.parsed_arguments.version is not None: | 105 | if self.parsed_arguments.version is not None: |
| @@ -77,6 +109,9 @@ class BuildManager: | |||
| 77 | if self.parsed_arguments.build_version is not None: | 109 | if self.parsed_arguments.build_version is not None: |
| 78 | logging.info("--build-version: %s", self.parsed_arguments.build_version) | 110 | logging.info("--build-version: %s", self.parsed_arguments.build_version) |
| 79 | 111 | ||
| 112 | + if self.parsed_arguments.exclude_tools: | ||
| 113 | + logging.info("--exclude-tools: %s", ",".join(self.parsed_arguments.exclude_tools)) | ||
| 114 | + | ||
| 80 | def _execute_command(self, command_sequence, timeout_seconds=36000, cwd=None, env=None): | 115 | def _execute_command(self, command_sequence, timeout_seconds=36000, cwd=None, env=None): |
| 81 | logging.info("Running: %s", " ".join(command_sequence)) | 116 | logging.info("Running: %s", " ".join(command_sequence)) |
| 82 | subprocess.run(command_sequence, timeout=timeout_seconds, check=True, cwd=cwd, env=env) | 117 | subprocess.run(command_sequence, timeout=timeout_seconds, check=True, cwd=cwd, env=env) |
| @@ -146,7 +181,14 @@ class BuildManager: | |||
| 146 | product_build_dir.mkdir(exist_ok=True) | 181 | product_build_dir.mkdir(exist_ok=True) |
| 147 | os.chdir(product_build_dir) | 182 | os.chdir(product_build_dir) |
| 148 | 183 | ||
| 149 | - self._execute_command(["cmake", ".."]) | 184 | + # 始终显式传递 MSOT_EXCLUDE_TOOLS,包括空值;否则 CMake 会复用 |
| 185 | + # build/CMakeCache.txt 中上一次的排除列表,导致后续默认构建仍跳过旧工具。 | ||
| 186 | + cmake_command = [ | ||
| 187 | + "cmake", | ||
| 188 | + "..", | ||
| 189 | + "-DMSOT_EXCLUDE_TOOLS=%s" % ",".join(self.parsed_arguments.exclude_tools), | ||
| 190 | + ] | ||
| 191 | + self._execute_command(cmake_command) | ||
| 150 | self._execute_command(["make", "-j", str(self.build_jobs)]) | 192 | self._execute_command(["make", "-j", str(self.build_jobs)]) |
| 151 | 193 | ||
| 152 | self._archive_artifacts() | 194 | self._archive_artifacts() |
| @@ -29,13 +29,15 @@ | |||
| 29 | </file_info> | 29 | </file_info> |
| 30 | 30 | ||
| 31 | <file_info value="package" copy_type="source" src_path="${OUTPUT}" dst_path="mindstudio-operator-tools" install_path="mindstudio-operator-tools" install_mod="550"> | 31 | <file_info value="package" copy_type="source" src_path="${OUTPUT}" dst_path="mindstudio-operator-tools" install_path="mindstudio-operator-tools" install_mod="550"> |
| 32 | - <file value="mskpp/mindstudio_kpp-*.whl" /> | 32 | + <!-- tool 属性用于排除工具参数过滤;未设置 tool 的公共文件始终打入总包。 --> |
| 33 | - <file value="mskl/mindstudio_kl-*.whl" /> | 33 | + <!-- msopgen 同时产出 mindstudio_opgen 与 mindstudio_opst,因此两个 whl 使用同一个 tool 标记。 --> |
| 34 | - <file value="msopgen/mindstudio_opgen-*.whl" /> | 34 | + <file value="mskpp/mindstudio_kpp-*.whl" tool="mskpp" /> |
| 35 | - <file value="msopgen/mindstudio_opst-*.whl" /> | 35 | + <file value="mskl/mindstudio_kl-*.whl" tool="mskl" /> |
| 36 | - <file value="msdebug/mindstudio-debugger_*.run" /> | 36 | + <file value="msopgen/mindstudio_opgen-*.whl" tool="msopgen" /> |
| 37 | - <file value="mssanitizer/mindstudio-sanitizer_*.run" /> | 37 | + <file value="msopgen/mindstudio_opst-*.whl" tool="msopgen" /> |
| 38 | - <file value="msopprof/mindstudio-opprof_*.run" /> | 38 | + <file value="msdebug/mindstudio-debugger_*.run" tool="msdebug" /> |
| 39 | + <file value="mssanitizer/mindstudio-sanitizer_*.run" tool="mssanitizer" /> | ||
| 40 | + <file value="msopprof/mindstudio-opprof_*.run" tool="msopprof" /> | ||
| 39 | </file_info> | 41 | </file_info> |
| 40 | 42 | ||
| 41 | </config> | 43 | </config> |
| @@ -41,6 +41,9 @@ FAIL = -1 | |||
| 41 | LOG_E = "ERROR" | 41 | LOG_E = "ERROR" |
| 42 | LOG_W = "WARNING" | 42 | LOG_W = "WARNING" |
| 43 | LOG_I = "INFO" | 43 | LOG_I = "INFO" |
| 44 | +# 与顶层 CMake 的 MSOT_VALID_TOOLS 保持一致;parser 只负责“总包内容过滤”, | ||
| 45 | +# 构建阶段是否跳过由 CMake 控制。 | ||
| 46 | +SUPPORTED_TOOLS = ("msdebug", "mskl", "mskpp", "msopgen", "msopprof", "mssanitizer") | ||
| 44 | 47 | ||
| 45 | def log_print_element(log_element): | 48 | def log_print_element(log_element): |
| 46 | print("[" + log_element + "]", end=' ') | 49 | print("[" + log_element + "]", end=' ') |
| @@ -62,11 +65,14 @@ class Xmlparser(object): | |||
| 62 | """ | 65 | """ |
| 63 | 功能描述: 解析xml配置文件。 | 66 | 功能描述: 解析xml配置文件。 |
| 64 | """ | 67 | """ |
| 65 | - def __init__(self, xml_file, delivery_dir, os_arch): | 68 | + def __init__(self, xml_file, delivery_dir, os_arch, excluded_tools=None): |
| 66 | self.xml_file = xml_file | 69 | self.xml_file = xml_file |
| 67 | self.delivery_dir = delivery_dir | 70 | self.delivery_dir = delivery_dir |
| 68 | self.default_config = {} | 71 | self.default_config = {} |
| 69 | self.target_env="{0}-{1}".format(os_arch, "linux") | 72 | self.target_env="{0}-{1}".format(os_arch, "linux") |
| 73 | + # excluded_tools 只过滤带 tool 属性的文件项;公共安装脚本和基础信息不设置 tool, | ||
| 74 | + # 因此始终会进入总包。 | ||
| 75 | + self.excluded_tools = set(excluded_tools or []) | ||
| 70 | 76 | ||
| 71 | self._cache_dir_info = {} | 77 | self._cache_dir_info = {} |
| 72 | self._dir_install_list = [] | 78 | self._dir_install_list = [] |
| @@ -132,6 +138,10 @@ class Xmlparser(object): | |||
| 132 | for sub_item in list(item.iter())[1:]: | 138 | for sub_item in list(item.iter())[1:]: |
| 133 | file_info = file_config.copy() | 139 | file_info = file_config.copy() |
| 134 | file_info.update(sub_item.attrib) | 140 | file_info.update(sub_item.attrib) |
| 141 | + # filelist.xml 中的 tool 属性表示该文件属于哪个子工具。 | ||
| 142 | + # 命中排除列表时,既不生成 filelist.csv 记录,也不执行后续复制。 | ||
| 143 | + if self.is_tool_excluded(file_info.get('tool')): | ||
| 144 | + continue | ||
| 135 | # 添加路径验证 | 145 | # 添加路径验证 |
| 136 | self._validate_path_component(file_info.get('src_path'), 'src_path') | 146 | self._validate_path_component(file_info.get('src_path'), 'src_path') |
| 137 | self._validate_path_component(file_info.get('value'), 'value') | 147 | self._validate_path_component(file_info.get('value'), 'value') |
| @@ -152,6 +162,12 @@ class Xmlparser(object): | |||
| 152 | file_info['hash'] = hash_value | 162 | file_info['hash'] = hash_value |
| 153 | self._package_content_list.append(file_info) | 163 | self._package_content_list.append(file_info) |
| 154 | 164 | ||
| 165 | + def is_tool_excluded(self, tool_name): | ||
| 166 | + """判断 XML 文件项是否属于被排除的子工具。""" | ||
| 167 | + if not tool_name: | ||
| 168 | + return False | ||
| 169 | + return tool_name.strip().lower() in self.excluded_tools | ||
| 170 | + | ||
| 155 | def get_src_target(self, file_info): | 171 | def get_src_target(self, file_info): |
| 156 | """ | 172 | """ |
| 157 | 获取文件的实际路径 | 173 | 获取文件的实际路径 |
| @@ -400,6 +416,26 @@ def safe_join(base_dir, user_path): | |||
| 400 | ) | 416 | ) |
| 401 | return joined | 417 | return joined |
| 402 | 418 | ||
| 419 | +def normalize_excluded_tools(exclude_tools): | ||
| 420 | + """归一化 parser 入参,保证直接调用 parser.py 时也有白名单校验。""" | ||
| 421 | + if not exclude_tools: | ||
| 422 | + return [] | ||
| 423 | + | ||
| 424 | + normalized_tools = [] | ||
| 425 | + for tool in exclude_tools.split(','): | ||
| 426 | + # 兼容 CMake/build.py 传入的逗号分隔字符串;忽略空片段,保留首次出现顺序。 | ||
| 427 | + tool_name = tool.strip().lower() | ||
| 428 | + if not tool_name: | ||
| 429 | + continue | ||
| 430 | + if tool_name not in SUPPORTED_TOOLS: | ||
| 431 | + raise ValueError( | ||
| 432 | + "Unsupported tool '%s'. Supported tools: %s" | ||
| 433 | + % (tool_name, ", ".join(SUPPORTED_TOOLS)) | ||
| 434 | + ) | ||
| 435 | + if tool_name not in normalized_tools: | ||
| 436 | + normalized_tools.append(tool_name) | ||
| 437 | + return normalized_tools | ||
| 438 | + | ||
| 403 | def do_copy(target_conf={}, delivery_dir='', release_dir=''): | 439 | def do_copy(target_conf={}, delivery_dir='', release_dir=''): |
| 404 | ''' | 440 | ''' |
| 405 | 功能描述: 根据拷贝类型来执行文件或目录拷贝 | 441 | 功能描述: 根据拷贝类型来执行文件或目录拷贝 |
| @@ -560,7 +596,9 @@ def main(args=None): | |||
| 560 | log_msg(LOG_E, "Input xml_file is None, please check paramters!") | 596 | log_msg(LOG_E, "Input xml_file is None, please check paramters!") |
| 561 | return FAIL | 597 | return FAIL |
| 562 | 598 | ||
| 563 | - xmlparser = Xmlparser(pkg_xml_file, delivery_dir, args.os_arch) | 599 | + # args 可能来自命令行,也可能来自单测/其他脚本构造;getattr 保持旧调用兼容。 |
| 600 | + excluded_tools = normalize_excluded_tools(getattr(args, 'exclude_tools', '')) | ||
| 601 | + xmlparser = Xmlparser(pkg_xml_file, delivery_dir, args.os_arch, excluded_tools=excluded_tools) | ||
| 564 | if xmlparser.parse(): | 602 | if xmlparser.parse(): |
| 565 | sys.exit(FAIL) | 603 | sys.exit(FAIL) |
| 566 | 604 | ||
| @@ -600,6 +638,9 @@ def args_prase(): | |||
| 600 | help="This parameter define the delivery path for all module." ) | 638 | help="This parameter define the delivery path for all module." ) |
| 601 | parser.add_argument('-o', '--os_arch', metavar='os_arch', required=False, dest='os_arch', nargs='?', const='', | 639 | parser.add_argument('-o', '--os_arch', metavar='os_arch', required=False, dest='os_arch', nargs='?', const='', |
| 602 | default=None, help="This parameter define the package's os_arch") | 640 | default=None, help="This parameter define the package's os_arch") |
| 641 | + # 由顶层 CMake 传入,用于过滤 filelist.xml 中带 tool 属性的子工具产物。 | ||
| 642 | + parser.add_argument('--exclude_tools', metavar='tools', required=False, dest='exclude_tools', nargs='?', const='', | ||
| 643 | + default='', help="Comma-separated tools excluded from package.") | ||
| 603 | return parser.parse_args() | 644 | return parser.parse_args() |
| 604 | 645 | ||
| 605 | 646 | ||
🟡 Medium Priority
问题链:
cmake_command = ["cmake", ".."]仅在self.parsed_arguments.exclude_tools非空时才追加-DMSOT_EXCLUDE_TOOLS=...。build/通过mkdir(exist_ok=True)复用,因此 CMakeCache.txt 在多次构建间持久存在。MSOT_EXCLUDE_TOOLS定义为 CACHE 变量且无FORCE,命令行未传入时使用缓存值。触发条件:用户先执行
build.py --exclude-tools msdebug,再执行build.py(不带--exclude-tools)。失败模式:
self.parsed_arguments.exclude_tools为[],if条件为 False,不追加-DMSOT_EXCLUDE_TOOLS。建议:将
-DMSOT_EXCLUDE_TOOLS的追加从条件分支中提出,始终向 CMake 传递该参数。当排除列表为空时传入空字符串-DMSOT_EXCLUDE_TOOLS=以显式清空缓存。