# 构建系统

[English]

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

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

备注

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

### 如何解决孤立段错误

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

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

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

3. 通过设置 CONFIG_COMPILER_ORPHAN_SECTIONS 为 `warning` 或 `place` 来抑制错误。

警告

不推荐使用 方案 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` 替换为整数值。值越小，执行越早。当对执行顺序有特定要求时，这种方式是首选。

## 配置文件语法变更

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

## 编译器选项

默认的编译器警告将被视为报错。配置选项 CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS 已被更改为 N。

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。