链接器工具警告 LNK4221

此对象文件未定义任何之前未定义的公共符号,因此任何耗用此库的链接操作都不会使用此文件

请思考以下两个代码片段:a.cpp

// a.cpp
#include <atlbase.h>

以及 b.cpp

// b.cpp
#include <atlbase.h>
int function()
{
   return 0;
}

若要编译文件并创建两个对象文件,请在命令提示符处运行 cl /c a.cpp b.cpp。 如果通过运行 link /lib /out:test.lib a.obj b.obj 链接对象文件,将收到 LNK4221 警告。 如果通过运行 link /lib /out:test.lib b.obj a.obj 链接对象,将不会收到警告。

第二个场景中没有发出警告,因为链接器以后进先出 (LIFO) 方式运行。 在第一个场景中,b.obja.obj 之前处理,并且 a.obj 没有要添加的新符号。 通过指示链接器先处理 a.obj,可以避免发出警告。

此错误的一个常见原因是,两个源文件指定选项 /Yc(创建预编译头文件),其头文件名与“预编译标头”字段中指定的头文件名相同。 此问题的一个常见原因涉及 pch.h,因为默认情况下,pch.cpp 包括 pch.h 且不会添加新符号。 如果另一个源文件包含 pch.h/Yc,并且在 pch.obj 之前处理关联的 .obj 文件,则链接器将引发 LNK4221。

此错误的一个常见原因是,两个源文件指定选项 /Yc(创建预编译头文件),其头文件名与“预编译标头”字段中指定的头文件名相同。 此问题的一个常见原因涉及 stdafx.h,因为默认情况下,stdafx.cpp 包括 stdafx.h 且不会添加新符号。 如果另一个源文件包含 stdafx.h/Yc,并且在 stdafx.obj 之前处理关联的 .obj 文件,则链接器将引发 LNK4221。

解决此问题的一种方法是确保对于每个预编译标头而言,只有一个源文件包含它和 /Yc。 所有其他源文件都必须使用预编译标头。 有关如何更改此设置的详细信息,请参阅 /Yu(使用预编译头文件)