我有几个使用Qt Visual Studio Tools创建的Visual Studio项目(在创建项目时始终提供最新版本,有些可以追溯到支持Qt 5的第一个版本,现在是2.2.1)。所有项目都是使用VS 2010编译的,尽管IDE是VS 2017(到目前为止为15.7.4)。
一段时间以来,一些项目开始报告链接错误,例如
错误LNK2001:无法解析的外部符号“ public:静态结构QMetaObject const MyQtClass :: staticMetaObject”(?staticMetaObject @ MyQtClass @@ 2UQMetaObject @@ B)
在此示例中,MyQtClass.h
文件声明MyQtClass
并具有Q_OBJECT
宏。 MyQtClass.cpp
定义了方法。
经过快速检查,我发现问题出在以下事实:关联的运动文件(上述示例为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文件以从Debug配置中删除排除项,那么该项目将正常工作。
仅当修改与Q_OBJECT
ed类关联的 main .cpp文件(在我的示例中为MyQtClass.cpp
)时,才会发生此问题。保存此类文件时,.vcxproj文件将被排除在外。
这个问题并没有出现在我拥有的每个Qt项目中,但是一旦启动,它就会在每次修改相关的.cpp文件时不断出现。我还没有发现一种模式。此外,它发生在公司的多个开发系统中,因此这似乎不是我的计算机问题。
我发现的唯一解决方法是丢弃项目文件中的更改,但是每次修改这些文件时,每次 丢弃并重新启动项目都是一件令人头疼的事情(碰巧是很多次)。
有人遇到过同样的问题吗?有什么解决方法的想法吗?
更新:仅当修改后的文件是与头文件(在我的示例中为MyQtClass.cpp
)具有相同基本名称的.cpp文件时,才会发生此问题。如果我修改了另一个也定义了MyQtClass
类的更多方法的文件(例如MyQtClass_more_definitions.cpp
),则不会给出错误。
由于它似乎是Qt Visual Studio工具中的一个错误,没有解决方法,因此我在QTVSADDINBUG-555下报告了该情况。
答案 0 :(得分:1)
与Qt VS Tools团队讨论后,我设法解决了这个问题。我已经使用当前可用的最新版本的插件(2.2.1)对其进行了测试。
解决方案包括将自定义构建步骤转换为Qt / MSBuild命令(有关here的更多信息)。为此,我使用了菜单选项 Qt VS Tools /将自定义构建步骤转换为Qt / MSBuild 。
转换后,我不得不处理一些棘手的问题。我在这里记录它们:
我必须使用Q_OBJECT
宏删除所有头文件,然后手动重新添加它们,以便对其进行移动(我还删除/重新添加了所有.ui文件,不确定是否会受到影响)。
添加现有文件(带有Q_OBJECT
的.h)时,不遵循预编译标头设置(使用PCH)。通过拖放添加文件。如果我关闭了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元对象编译器/强制包含选项更改为StdAfx.h;../../%(Filename)%(Extension)
(将StdAfx.h
更改为您的PCH文件名(如果不同):
我有一些QRC文件被编译为二进制文件。默认情况下,为每个QRC文件设置二进制输出。我必须将全局属性更改为false
才能解决该问题:
<QtRcc>
<BinaryOutput>false</BinaryOutput>
</QtRcc>
或使用.qrc属性:
此外,它们的输出文件是C ++源(qrc_*.cpp
,而不是原始项目*.rcc
中的输出名称)。只需将DynamicSource
设置为false
并将相应的OutputFile
中的ItemGroup
元素设置为:
<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,因此我不确定它是否将得到解决。