链接器(ld)发出的奇怪警告

32
我们正在构建一个Mac OSX应用程序,它主要是用Obj-C/Cocoa编写的。 然后该应用程序会静态链接一些第三方库,这些库是用C/C++编写的,并由我们编译(在命令行上,使用MacPorts或通常的"./configure && make";所有都是通用二进制文件)。
该应用程序运行得非常完美,但在编译时我们总是会收到这些奇怪的链接器警告:
ld: warning: direct access in ___cxx_global_var_init17 to global weak symbol __ZGVN4i18n12phonenumbers9SingletonINS0_15PhoneNumberUtilEE8instanceE means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
ld: warning: direct access in ___cxx_global_var_init17 to global weak symbol __ZGVN4i18n12phonenumbers9SingletonINS0_15PhoneNumberUtilEE8instanceE means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
ld: warning: direct access in ___cxx_global_var_init17 to global weak symbol __ZN5boost10scoped_ptrIN4i18n12phonenumbers15PhoneNumberUtilEED1Ev means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
ld: warning: direct access in ___cxx_global_var_init17 to global weak symbol __ZN4i18n12phonenumbers9SingletonINS0_15PhoneNumberUtilEE8instanceE means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
ld: warning: direct access in ___cxx_global_var_init17 to global weak symbol __ZGVN4i18n12phonenumbers9SingletonINS0_15PhoneNumberUtilEE8instanceE means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.

这是来自于一个C/C++库。我们正在链接以下这些库:

  1. libphonenumber,它似乎引起了其中4个警告。通过“cmake”由我们编译。
  2. boost(libboost_thread-mt),负责其中1个警告。通过MacPorts编译。
  3. ICU(libicudata、libicuuc、libicui18n),通过MacPorts编译。
  4. Protocol Buffers,通过“./configure && make”编译。

请注意:

  1. 尽管有警告,但应用程序仍然可以正常工作,但我们希望摆脱这些烦人的警告。
  2. xcode with boost : linker(Id) Warning about visibility settings提出的解决方案不起作用:“默认情况下隐藏符号”始终为“是”。

你可以通过使用C标志-DUSE_RE2=1来使用"re2"正则表达式库而不是完整的ICU库,从而使libphonenumber更小。 - Matt Connolly
@MattConnolly,ICU仍然需要吗?它可以使用re2进行正则表达式匹配,但其他方面仍需要ICU... 最终,我找到了一个“解决方案”。它肯定很不好,但是有效:使用JS(是的,JavaScript)版本并从Cocoa中调用它。它也比我预期的要快! - ItalyPaleAle
您可以链接到iOS提供的icucore库。难道不需要设置webview来运行javascript吗?如果使用v8优化器,那应该可以...我也会去看一下git。 - Matt Connolly
@MattConnolly 不需要设置 Web 视图来运行 JS 代码。您可以使用 JavaScriptCore 框架,它是 WebKit 的一部分并捆绑在操作系统中... 实际上性能还不错! - ItalyPaleAle
4个回答

29
xcode提出的与boost相关的解决方案:有关可见性设置的链接器(Id)警告无效:“默认情况下隐藏符号”始终是“YES”。这与设置为“YES”有较少关系,更多地与在所有项目中设置为相同值有关。依赖其他库的库/项目需要具有类似的“默认情况下隐藏符号”设置,以便正确链接并无错误/警告地释放。我之前也遇到过这个问题,通过在Xcode中简单更改所有项目以确保设置匹配通常可以解决问题。由于您似乎也在命令行上编译,因此需要查看gcc-fvisibility参数。

2
是的,如果您正在使用gcc编译它们,那就从这里开始吧。添加-fvisibility=default将使所有符号“公开”。当然,对于您的项目来说,最终的正确选择取决于您的需求,因此我建议通过在终端中运行man gcc或在Google上搜索相关文档来了解-fvisibility。但是,正如我所提到的,确保所有项目使用相同的-fvisibility设置通常可以解决此问题。从default(基本上是“public”)开始。 - inspector-g
1
我刚刚检查了使用静态库的Xcode项目,其中大多数实际上将“默认情况下隐藏符号”设置为“NO”。我不确定Xcode如何将此翻译为-fvisibility设置,因为当设置为“YES”时,它似乎仅在命令行输出中包含它(在这种情况下,它会执行-fvisibility=hidden,这本质上是-fvisibility=default的相反)。最坏的情况是,在您的makefile中使用-fvisibility=default并将其添加到您的Xcode项目的“其他C标志”中。 - inspector-g
1
好的,我已经使用开关重新编译了libphonenumber,但是没有任何变化。然而,在您建议的情况下,我将“默认隐藏符号”更改为“否”,现在所有与libphonenumber相关的警告都消失了。只有与boost相关的警告仍然存在(但重新编译boost需要1小时,所以我稍后再做 :))。谢谢! - ItalyPaleAle
-fvisibility=default 是一个非常好的建议。省了我很多时间。非常感谢! - valvoline
非常感谢你的回答!非常感激! - AgnosticDev
显示剩余2条评论

9

简而言之,无论您编译什么东西,包括依赖库,都应该使用 -fvisibility=hidden 作为gcc和llvm编译器的开关。除非您有理由不这样做。

关于 -fvisibility 和 -fvisibility-inline-hidden 编译标志的介绍,请参阅苹果网站,本文撰写时该文章还详细介绍了 __attribute__((visibility("hidden")))__attribute__((visibility("default"))) 声明。


1
是的。有时如果您使用-fvisibility=hidden,您必须使用属性(或推送/弹出,如链接中所述)公开一些符号。 - Yoav

6

我在Xcode中加入了-fvisibility=hidden -fvisibility-inlines-hidden到其他C++标志,从而消除了警告。


这是一个有点无聊的补充,但将它们放在“其他C标志”中,因为C++标志通常设置为继承自C标志。 - Joel Teply

4

1
尝试了inspector-g的答案,但它没有起作用,但这个解决方案消除了我的警告。看起来是相同的概念,只是不同的设置。 - alk3ovation

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接