如何解决Bazel 链接器找不到函数定义
我在尝试添加 Bazel 构建文件以在 ICU 中构建 gennorm2 工具方面取得了相当大的进展。这是使用 Bazel 目标 //icu4c/source/tools/gennorm2
的 my work-in-progress PR。
我目前在使用 these errors 运行 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
,该字段应该匹配
make VERBOSE=1
。
如果有帮助,这是使用当前基于自动工具的 configure + make build 在新的 ICU 结帐上运行 global
时的 verbose log output。
解决方法
一位队友能够查看并帮助我解释错误并最终修复它们。
首先要承认它确实是一个链接器错误,这可以通过注意 error message references the linker program ld
看出。
这很重要,因为我们之前在错误的地方调试编译配置,就好像问题发生在链接器阶段之前的编译阶段一样。 (但我了解到一种调试编译问题的方法是采用 --verbose_failures --sandbox_debug
给出的原始 GCC 命令并将 -c
替换为 -E
并将 -o
的参数更改为 . /tmp 中的 .txt 文件以保存编译器在递归内联所有包含之后对该文件看到的输出)。这意味着我通过为编译阶段指定预处理器定义来解决问题的尝试被误导了。
project's documentation on dependencies 表明我错误地指定了对其中一个目标的依赖,仅指定标头 (//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
日期库。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。