首页 > 解决方案 > Bazel 链接器未找到函数定义

问题描述

在尝试添加 Bazel 构建文件以在 ICU 中构建 gennorm2 工具方面,我已经取得了相当大的进展。这是我使用 Bazel target进行中的 PR//icu4c/source/tools/gennorm2

我目前在运行这些错误时遇到bazelisk build //icu4c/source/tools/gennorm2 --verbose_failures --sandbox_debug困难

它们引用定义在urename.h. 据我了解,它urename.h也用于通过附加带有版本号 ( _68) 的后缀来重命名某些函数,但我定义了一个预处理器常量U_DISABLE_RENAMING来禁用该特定行为。这只会改变错误输出中未定义函数名称的名称,但不会改变它(例如:错误现在抱怨u_errorName而不是u_errorName_68)。

令我困惑的部分是为什么错误输出声称找不到这些符号。如您所见,目标//icu4c/source/tools/gennorm2取决于//icu4c/source/common:platform,而后者又取决于,其中包括应该匹配 //icu4c/source/common:headers的字段。hdrs = glob(["unicode/*.h", "unicode/*.h",])/icu4c/source/common/unicode/urename.h

如果有帮助,这是使用当前基于 autotools 的 configure + make build 在重新检出 ICU时运行时的详细日志输出。make VERBOSE=1

标签: c++bazel

解决方案


一位队友能够查看并帮助我解决错误并最终修复它们。

第一件事是承认它确实是一个链接器错误,这可以通过注意到错误消息引用链接器程序ld来看到。

这很重要,因为我们之前在调试编译配置时花时间在错误的地方,就好像问题发生在链接器阶段之前的编译阶段一样。(但我了解了调试编译问题的一种方法是使用 给出的原始 GCC 命令--verbose_failures --sandbox_debug并将其替换-c为/tmp 中的 .txt 文件-E并将其更改为-o/tmp 中的 .txt 文件,以保存编译器在所有包含后对该文件看到的输出是递归内联的)。这意味着我通过为编译阶段指定预处理器定义来解决问题的尝试被误导了。

项目关于依赖项的文档显示,我错误地指定了对其中一个目标的依赖项,仅指定标头 ( //icu4c/source/common:headers) 而不是相关的定义和标头 ( //icu4c/source/common:platform)。

之后,我们解决了另一个小而有趣的问题。gennorm2目标取决于获取当前年份的代码(例如:用于打印包含年份范围的版权声明的帮助消息)。作为一个 i18n 库,ICU 在//icu4c/source/i18n:icu4ci18n. 这会为一个孤立的用例创建过多的代码依赖项(并将导致后续工作出现问题),因此我们将gennorm2调用那些日历年 fns ( ucal_open, ucal_getNow, ucal_setMillis, ucal_get, ucal_close) 的代码块替换为 libc 日期库函数给我们年份作为数字,并添加linkopts = ["-ldl"]dl日期库中的链接。


推荐阅读