tools: harden target generator serialization - #11557
Conversation
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
|
您好,请问这个 PR 是否还需要我补充更多验证信息或调整实现?我已经在本地完成了 Python 语法检查和回归测试,测试结果已写在 PR 描述中。谢谢。 |
|
各位维护者好,打扰了。 |
|
各位维护者好,打扰了。 |
There was a problem hiding this comment.
Pull request overview
English: This PR introduces a shared serialization helper (tools/targets/target_utils.py) and migrates multiple target/project generators to use it, aiming to make path/define/flag/linker-script serialization consistent and robust across output formats (CMake/Makefile/VSCode/IDE XML/Zig/Xmake/ESP-IDF, etc.).
中文:本 PR 引入公共序列化辅助模块(tools/targets/target_utils.py),并将多个工程/构建文件生成器迁移到统一的 helper 上,以统一并加固路径、宏、编译/链接参数、linker script 等字段在不同格式下的序列化行为。
Changes / 变更摘要:
- English: Add shared helpers for ordered de-duplication, CPPDEFINES normalization, quoting/escaping for multiple target formats, and flag parsing (includes/linker scripts).
中文:新增顺序稳定去重、宏定义归一化、各类格式的字符串/列表转义、以及 flags(含 include/linker script)解析的公共工具函数。 - English: Refactor many generators to use the shared helpers, removing per-generator ad-hoc serialization and Python 2/3 incompatibilities in a few places.
中文:多个生成器统一改用公共 helper,减少重复拼接逻辑,并修复部分 Python2/3 兼容问题。 - English: Harden VSCode and some IDE generators against edge cases (quoted include paths, empty compile_commands.json/tree).
中文:加强 VSCode 与部分 IDE 生成器的健壮性(例如带空格的 quoted include path、空 compile_commands.json 等边界情况)。
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/targets/target_utils.py | Adds centralized serialization/parsing helpers used by multiple generators. |
| tools/targets/cmake.py | Uses shared helpers for flags/paths/defines/lists in generated CMake output. |
| tools/targets/makefile.py | Quotes Makefile variables/paths/defines using shared helper routines. |
| tools/targets/vsc.py | Improves compile_commands parsing and replaces eval/set de-dup with stable logic. |
| tools/targets/eclipse.py | Normalizes CPPDEFINES, improves linker-script parsing, and tokenizes LINKFLAGS for exact matches. |
| tools/targets/esp_idf.py | Quotes/escapes SRCS and INCLUDE_DIRS items safely for CMake list semantics. |
| tools/targets/xmake.py | Switches to ordered unique lists and Lua-safe quoting for xmake.lua generation. |
| tools/targets/zigbuild.py | Uses shared helpers for quoting flags, normalizing lists, defines, and linker-script extraction. |
| tools/targets/ses.py | Fixes Python 3 I/O and stabilizes include/define serialization. |
| tools/targets/vs.py | Stabilizes XML path serialization and CPPDEFINES handling via shared helpers. |
| tools/targets/vs2012.py | Stabilizes XML Include paths and normalizes CPPDEFINES via shared helpers. |
| tools/targets/keil.py | Normalizes grouped file paths and macro/include serialization for MDK projects. |
| tools/targets/iar.py | Normalizes group paths, escapes raw-XML workspace interpolation, and normalizes defines/libs. |
| tools/targets/codeblocks.py | Fixes Python 3 decode issues, normalizes paths, and corrects per-macro emission. |
| tools/targets/cdk.py | Stabilizes file paths and CPPDEFINES serialization using shared helpers. |
| def cmake_list(values, indent='\t'): | ||
| """Format values as one indented, quote-safe CMake list element per line.""" | ||
| return "\n".join("{}{}".format(indent, cmake_quote(v)) for v in values) |
| # find the linker script in LFLAGS -- handles -Tfoo, -T foo, | ||
| # -T "dir with space/link.lds" and -Wl,-T,foo without truncating | ||
| link_scripts = target_utils.normalize_link_script_flags(LFLAGS) | ||
| link_script = link_scripts[0].replace("\\", "/") if link_scripts else "" | ||
| zig_file.write(" elf.setLinkerScript(b.path({}));\n".format( | ||
| target_utils.zig_quote(link_script))) |
|
拉取/合并请求描述:(PR description)
[
为什么提交这份PR (why to submit this PR)
本 PR 修复
tools/targets目录下多个目标工程生成器在序列化路径、宏定义、编译参数、链接参数以及工程文件字段时存在的不一致问题。tools/targets中的生成器用于根据 RT-Thread 工程信息生成 CMake、Makefile、VSCode、SES、Xmake、Zig、Eclipse、Visual Studio、VS2012、Keil、IAR、CodeBlocks、CDK、ESP-IDF 等工程或构建文件。修复前,不同生成器分别在各自文件中手工拼接宏定义、include path、source path、library path、linker script、XML 属性、CMake list、Lua / Zig 字符串等内容,导致同一类输入在不同生成器中处理结果不一致,部分合法输入会被错误序列化,从而生成语法错误或语义错误的工程文件。本 PR 修复的问题主要包括以下几类:
SCons 中常见的宏定义形式包括:
"FOO""FOO=1"("FOO", "1")["FOO", "1"]其中
("FOO", "1")和["FOO", "1"]的语义应当是FOO=1。修复前,部分生成器会将 tuple / list 形式的带值宏错误拆分为两个独立项,例如生成FOO;1、-DFOO -D1,或者只保留值而丢失宏名,导致生成的工程文件宏定义语义错误。set()去重导致顺序不稳定修复前,部分生成器使用
set()对宏定义、include path、source path 或 library path 去重。该方式会打乱原始顺序,导致生成文件内容不稳定,也可能改变 include path、library path 或宏定义的优先级。对于工程生成器来说,顺序稳定性很重要,因此本 PR 改为顺序稳定的去重方式。不同工程文件格式对特殊字符的处理规则不同。修复前,多个生成器直接拼接字符串,路径或宏定义中包含空格、分号、引号、反斜杠、
#、$、XML 特殊字符等内容时,可能生成错误文件。例如:#、$等字符需要正确处理;&、<、>、引号等字符需要正确处理;compile_commands.json的解析不健壮tools/targets/vsc.py修复前对command字符串使用简单.split()解析。对于带空格的 include path,例如-I"dir with space/inc",该方式会错误拆分路径,导致 VSCode workspace 的 include path 不完整或错误。此外,空
compile_commands.json会导致空目录树访问list(...)[0],触发IndexError。eval()去重逻辑修复前,
vsc.py中通过str()+eval()对列表项去重。该方式不够稳健,也不适合处理包含特殊字符的数据结构。本 PR 将其替换为顺序稳定的普通去重逻辑。例如:
tools/targets/ses.py使用 Python 2 风格的file(),在 Python 3 下会触发NameError;tools/targets/codeblocks.py中存在对 Python 3str调用.decode()的情况,会触发AttributeError;ElementTree.tostring(..., encoding='utf-8')返回的 bytes,可能触发TypeError。修复前,CodeBlocks 生成器中存在遍历宏字符串字符的问题。例如对于
RT_USING_FINSH,旧逻辑可能逐字符遍历,最终只保留最后一个字符对应的错误宏选项。对于("STM32", "1")这类带值宏,也可能生成错误的-D1,丢失宏名。部分生成器对 linker script 参数的解析不完整,例如:
-Tfoo.lds-T foo.lds-T "dir with space/link.lds"-Wl,-T,foo.lds修复前,相关逻辑可能因为简单字符串拆分或正则不完整而截断路径或漏掉 linker script 参数。
esp_idf.py生成idf_component_register(SRCS ... INCLUDE_DIRS ...)时,如果 source path 或 include path 包含空格、分号等字符,旧逻辑可能破坏 CMake list 语义。本 PR 对相关路径进行统一序列化处理。以上问题均属于普通工具链 / 工程生成器的软件缺陷,会影响生成项目文件的正确性、稳定性和可用性,不涉及安全漏洞。
你的解决方案是什么 (what is your solution)
本 PR 的主要思路是引入公共序列化辅助模块,并将多个目标工程生成器中分散的手工拼接逻辑统一收敛到公共 helper 中,减少重复实现导致的不一致问题。
主要修改如下:
tools/targets/target_utils.py新增公共工具模块,用于统一处理目标工程生成器中的常见序列化逻辑,包括:
将多个生成器中分散的
CPPDEFINES/LOCAL_CPPDEFINES拼接逻辑改为使用公共 helper。现在可以稳定处理以下形式:"FOO"→FOO"FOO=bar"→FOO=bar("FOO", "1")→FOO=1["FOO", "1"]→FOO=1"FOO=\"a b\""→ 保持带值宏语义同时避免使用
set()破坏宏定义顺序。对 CMake / ESP-IDF 生成器中的 source path、include path、library path、宏定义和相关 list 项进行面向 CMake 的安全序列化,避免路径中的空格、分号、引号等字符破坏 CMake list 语义。
对 Makefile 中的
DEFINES、CPPPATHS、SRC_FILES、LIBS、LIBPATHS等字段进行 Makefile 语义下的转义,同时尽量保留$(BSP_ROOT)、$(RTT_ROOT)等已有 Make 变量语义。compile_commands.json;-Ifoo、-I foo、/Ifoo、/I foo等 include 参数形式;compile_commands.json不再触发IndexError;eval()去重逻辑,改为顺序稳定的去重实现。file()替换为 Python 3 可用的open();.decode()调用;对 Eclipse、Visual Studio、VS2012、Keil、IAR、CodeBlocks、CDK 等生成器中涉及 XML 属性、文件路径、include path、define list 的逻辑进行同主题修复:
-T相关形式处理不完整的问题;本 PR 当前保留实现代码修复,不新增
tools/testcases下的测试文件。验证方式以 Python 语法检查、diff 检查和开发过程中的边界输入验证为主,避免在本次 PR 中引入额外测试文件。请提供验证的bsp和config (provide the config and bsp)
本 PR 修改的是
tools/targets下的 Python 工程生成器,不涉及具体 BSP 源码修改。本 PR 不需要修改任何 BSP
.config选项。本 PR 已在本地完成 Python 语法检查和 diff 检查。提交 PR 后,可继续以 GitHub Actions 的结果为准。
本地验证命令如下:
验证结果:
]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up