【问题标题】:What is the best way to eliminate MS Visual C++ Linker warning : "warning LNK4221"?消除 MS Visual C++ 链接器警告的最佳方法是什么:“警告 LNK4221”?
【发布时间】:2010-12-21 19:52:12
【问题描述】:

我有一个 CPP 源文件,它使用 #if / #endif 在某些构建中完全编译出来。但是,这会产生以下警告。

warning LNK4221: no public symbols found; archive member will be inaccessible

我正在考虑创建一个宏来生成一个实际上不会使用的虚拟变量或函数,这样这个错误就会消失,但我想确保它不会导致问题,例如在多个中使用宏导致链接器轰炸多个定义的符号的文件。

消除此警告的最佳方法是什么(而不是简单地抑制链接器命令行上的警告)?

FWIW,我很想知道如何通过抑制链接器命令行上的警告来做到这一点,但是我在那里的所有尝试似乎都被链接器简单地忽略了并且仍然产生错误。

另一个要求:该修复程序必须能够经受住单个文件构建或统一构建(组合 CPP 文件构建),因为我们的构建配置之一是批量构建(类似于统一构建但批量文件组而不是单个主统一文件)。

【问题讨论】:

  • 您尝试过调用链接器的哪种语法(但对您不起作用)?
  • 我已经为链接器尝试了“/ignore:4221”,为 cpp 文件尝试了“#pragma warning(disable: 4221)”。都没有用。
  • 我们使用虚幻引擎进行开发。我们的游戏工作室(WB Games Chicago)和 Epic 都发现批量构建(每个系统/目录大约 1 个 Unity 构建)显着减少了编译时间和链接时间(快了约 4 倍)。它们还帮助编译器更好地内联代码并生成执行速度更快的代码。因此,我们将批量构建用于零售和开发构建,但不用于完整调试构建。
  • 作为旁注,谷歌搜索,似乎没有记录或已知的方法来禁用 VC 链接器警告 - /ignore 仅适用于 VC6。
  • @Adisak - 感谢有关统一构建的信息。

标签: c++ visual-c++ linker suppress-warnings


【解决方案1】:

使用匿名命名空间:

namespace { char dummy; };

此类命名空间中的符号具有外部链接,因此导出表中会有一些东西。另一方面,命名空间名称本身对于每个翻译单元都是不同的(您可以将其视为“随机生成的”),因此不会发生冲突。

【讨论】:

  • 我要测试一下。我需要它与统一构建一起使用,因此我可能必须使用“char dummy##__LINE__;”将其设为宏或类似的东西,所以我没有在单个翻译单元中复制符号。
  • 这里的修复按预期轰炸了我们的统一构建,但它应该适用于我描述的次要模块。
  • @GMan:无论我们是否进行批量构建(类似于统一构建),我们的翻译单元都会有所不同。您需要将其放在每个可能为空的单元中。但是,批量构建将在编译时动态绑定单元。
  • @Adisak,我仍然很好奇它为什么会“爆炸”,以及为什么添加 __LINE__ 会改变这一点。能详细解释一下吗?
  • 我认为他的“统一构建”将所有 cpp 文件组合在一起并将它们编译为单个翻译单元。因此(anonymous)::dummy 在每个符号中都是相同的符号,编译器会抱怨多个定义。他的解决方法是将dummy 对象与__LINE__ 区分开来。
【解决方案2】:

好的,我要使用的修复是 Pavel 的建议,稍作调整。我使用此修复程序的原因是它是一个易于插入的宏,它可以在批量构建/统一构建以及普通构建中工作:

共享标头:

// The following macro "NoEmptyFile()" can be put into a file
// in order suppress the MS Visual C++ Linker warning 4221
//
// warning LNK4221: no public symbols found; archive member will be inaccessible
//
// This warning occurs on PC and XBOX when a file compiles out completely
// has no externally visible symbols which may be dependant on configuration
// #defines and options.

#define NoEmptyFile()   namespace { char NoEmptyFileDummy##__LINE__; }

可以完全编译出来的文件:

NoEmptyFile()
#if DEBUG_OPTION
      // code
#endif // DEBUG_OPTION

【讨论】:

    【解决方案3】:

    (虽然讨论已经很老了,我不能直接评论@Adisak 的答案),我想这个工作需要一些额外的宏扩展魔法:

    #define TOKENPASTE(x, y) x ## y
    #define TOKENPASTE2(x, y) TOKENPASTE(x, y)
    #define NONEMPTY_TRANSLATION_UNIT char TOKENPASTE2(NoEmptyFileDummy, __LINE__);
    

    【讨论】:

      猜你喜欢
      • 2014-01-18
      • 1970-01-01
      • 2014-08-03
      • 2011-05-19
      • 2015-06-21
      • 1970-01-01
      • 2021-03-29
      • 2016-09-13
      • 2017-10-15
      相关资源
      最近更新 更多