迁移构建系统至 ESP-IDF v6.0

[English]

链接器孤立段处理行为变更为报错

从 ESP-IDF v6.0 开始,构建系统不再允许最终 ELF 文件中存在孤立段。如果链接过程中发现任何孤立段,链接器将报错。

备注

孤立段 是指未被链接脚本显式放置到任何输出段,且在链接过程中未被丢弃的段。

如何解决孤立段错误

如果在链接时遇到孤立段错误,可通过以下任一方式解决:

  1. 移除导致孤立段的代码或数据(若未使用或不必要)。

  2. 使用 链接器片段文件 显式放置孤立段。

  3. 通过设置 CONFIG_COMPILER_ORPHAN_SECTIONSwarningplace 来抑制错误。

警告

方案 3 不推荐使用,因为孤立段可能意味着内存映射配置存在问题,或应用程序中存在非预期行为。

全局构造函数顺序变更

最初,ESP-IDF 使用内部函数 do_global_ctors() 执行全局构造函数,以兼容 Xtensa 架构,其编译器会生成按 降序 排列的 .ctors.* 段。

在 RISC-V 架构中,工具链会生成 .init_array.* 段,并采用标准的 升序 排列。虽然优先级构造函数(位于 .init_array.*)能正确执行,但此前未指定优先级的 .init_array 段却是按 降序 方式处理,从而与 Xtensa 的 .ctors 行为保持一致。

从 ESP-IDF v6.0 起,启动代码改用标准工具链函数 __libc_init_array()。该函数会按 升序 执行带优先级和不带优先级的构造函数。

因此,我们引入了以下重大变更:

  • 对于 Xtensa 架构,.ctors.* 项现在会被转换为升序,以确保与 __libc_init_array() 的行为兼容。

  • 非优先级的 .init_array 和旧版 .ctors 段的执行顺序从 降序 改为 升序

这些变更使 ESP-IDF 的行为与工具链的预期保持一致,并提升了跨架构的兼容性。

若应用程序依赖原有构造函数的执行顺序(降序),并因此受到影响,可参考以下解决方案。

更新构造函数注册逻辑

有些数据结构是基于“构建函数按相反顺序运行”的假设来构建的。现在为了不改变原有行为,可将注册新项的逻辑从“插入头部”改为“插入尾部”。

示例(来自 components/unity/unity_runner.c):

-    // 插入到链表头部
-    desc->next = s_unity_tests_first;
-    s_unity_tests_first = desc;
+    // 插入到链表尾部
+    _unity_tests_last->next = desc;
+    s_unity_tests_last = desc;

备注

此方案仅适用于特定场景。

使用构造函数优先级

若需显式控制构造函数执行顺序,可使用带数值优先级的 constructor() 函数属性:

__attribute__((constructor(PRIO)))
void foo(void);
PRIO 替换为整数值。值越小,执行越早。当对执行顺序有特定要求时,这种方式是首选。

方案3 不推荐使用,因为孤立段可能意味着内存映射配置存在问题,或应用程序中存在非预期行为。

配置文件语法变更

ESP-IDF v6 使用了 esp-idf-kconfig v3,对配置文件 Kconfig 的语法进行了若干变更。完整变更列表请参阅 Migration Guide From esp-idf-kconfig v2.x to v3.x


此文档对您有帮助吗?