c++ - Moc'ed 文件神秘地从 Visual Studio 项目中排除
问题描述
我有几个使用 Qt Visual Studio 工具创建的 Visual Studio 项目(始终是项目创建时可用的最新版本,有些可以追溯到支持 Qt 5 的第一个版本,现在是 2.2.1)。所有项目都是用 VS 2010 编译的,尽管 IDE 是 VS 2017(到目前为止是 15.7.4)。
从一段时间开始,一些项目开始报告链接错误,例如
错误 LNK2001:未解析的外部符号“公共:静态结构 QMetaObject const MyQtClass::staticMetaObject”(?staticMetaObject@MyQtClass@@2UQMetaObject@@B)
对于此示例,MyQtClass.h
文件声明MyQtClass
并具有Q_OBJECT
宏。MyQtClass.cpp
定义方法。
经过快速检查后,我发现问题来自关联的 moc'ed 文件(moc_MyQtClass.cpp
例如上面的示例)被排除在当前配置的编译之外。这里是 .vcxproj 文件的摘录:
<ClCompile Include="GeneratedFiles\Debug\moc_MyQtClass.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_MyQtClass.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
如果我修改 .vcxproj 文件以从调试配置中删除排除项,则该项目可以工作。
该问题仅在修改与 ed 类关联的主.cpp 文件时发生(在我的示例中)。保存此类文件时,会使用排除项修改 .vcxproj 文件。Q_OBJECT
MyQtClass.cpp
这个问题不会出现在我拥有的每个 Qt 项目中,但是一旦启动,每次修改关联的 .cpp 文件时都会出现此问题。我还没有找到它的模式。另外,公司的几个开发系统都出现这种情况,所以好像不是我电脑的问题。
我发现的唯一解决方法是丢弃项目文件中的更改,但是每次修改这些文件时丢弃并重新启动项目是一件令人头疼的事情(这恰好是很多次)。
有没有人遇到过同样的问题?任何想法如何解决它?
更新:仅当修改后的文件是与头文件(MyQtClass.cpp
在我的示例中)具有相同基本名称的 .cpp 文件时,才会出现此问题。如果我修改了另一个也定义了MyQtClass
类的更多方法的文件(例如MyQtClass_more_definitions.cpp
),则不会给出错误。
由于它似乎是 Qt Visual Studio Tools 中的一个错误,没有解决方法,我已经在QTVSADDINBUG-555下报告了它。
解决方案
在与 Qt VS Tools 团队讨论之后,我设法解决了这个问题。我已经使用当前可用的插件的最新版本(2.2.1)对其进行了测试。
解决方案包括将自定义构建步骤转换为 Qt/MSBuild 命令(更多信息请参见此处)。为此,我使用了菜单选项Qt VS Tools / Convert custom build steps to Qt/MSBuild。
转换后,我不得不处理一些棘手的问题。我在这里记录它们:
我必须使用
Q_OBJECT
宏删除所有头文件并手动重新添加它们以便能够对它们进行移动(我还删除/重新添加了所有 .ui 文件,不确定是否受到影响)。添加现有文件(.h 和 )时,不考虑预编译的标头设置(使用 PCH
Q_OBJECT
)。文件是通过拖放添加的。如果我关闭 PCH 然后再打开它来处理已添加的文件,新文件仍然需要手动干预(PCH 关闭/打开或编辑.vcxproj
如下所示)。输入无效
.vcxproj
:<QtMoc Include="new_file_added.h" />
变成:
<QtMoc Include="example.h"> <ForceInclude Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdAfx.h;../../%(Filename)%(Extension)</ForceInclude> <ForceInclude Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">StdAfx.h;../../%(Filename)%(Extension)</ForceInclude> </QtMoc>
另一种解决方法是打开受影响的头文件的属性并将Qt Meta-Object Compiler / Force Include选项
StdAfx.h;../../%(Filename)%(Extension)
更改为(StdAfx.h
如果不同,请使用您的 PCH 文件名更改):我有一些 QRC 文件被编译成二进制文件。默认情况下,为每个 QRC 文件设置二进制输出。我不得不改变全局属性
false
来解决它:<QtRcc> <BinaryOutput>false</BinaryOutput> </QtRcc>
或使用 .qrc 属性:
此外,它们的输出文件是 C++ 源代码(
qrc_*.cpp
,而不是原始项目中的输出名称,*.rcc
)。只需更改 setDynamicSource
tofalse
和OutputFile
相应ItemGroup
s 中的元素:<ItemGroup> <QtRcc Include="resources\resources.qrc"> <BinaryOutput>true</BinaryOutput> <DynamicSource>false</DynamicSource> <OutputFile>$(SolutionDir)\output\resources.rcc</OutputFile> </QtRcc> </ItemGroup>
经过这些更改后,它运行良好(在我的两个环境中,VS 2010 和 VS 2017)。
PS:这似乎是一个已知问题(或至少与其他问题有关),但没有提供更多信息。另一方面,自定义构建步骤正在被 Qt VS Tools 弃用,转而支持 MSBuild,所以我不确定它是否会得到修复。
推荐阅读
- python - SWIG 构建模块的 VSCode 自动完成功能
- python - 根据我在哪个文件夹中打开 vs 代码,在 VS 代码中打开文件或导入模块时遇到问题
- android - Jetpack 的不良行为构成 HorizontalPager
- google-cloud-platform - 当规则设置为“仅预览”时,Cloud Armor 日志不是很清楚
- python - 井字游戏问题
- python - 如何以最少的列值从其他数据框中唯一地定义一个数据框?
- javascript - 为什么要在官方文档中为诸如 react 之类的流行库使用函数声明
- python - 字典列表中重复(公共)键的总和值
- itfoxtec-identity-saml2 - 使用 .Net Framework CertificationValidationMode 被忽略?
- r - 当我添加一个新的情节时,R Markdown 没有编织