Moc的文件被神秘地从Visual Studio项目中排除了

时间:2018-06-20 15:55:18

标签: c++ visual-studio qt qt-vs-addin

我有几个使用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下报告了该情况。

1 个答案:

答案 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文件名(如果不同):

    header file properties

  • 我有一些QRC文件被编译为二进制文件。默认情况下,为每个QRC文件设置二进制输出。我必须将全局属性更改为false才能解决该问题:

    <QtRcc>
      <BinaryOutput>false</BinaryOutput>
    </QtRcc>
    

    或使用.qrc属性:

    QRC properties

    此外,它们的输出文件是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>
    

    或使用GUI: DynamicSource

这些更改之后,它可以完美运行(在我的两个环境中,VS 2010和VS 2017)。

PS:这似乎是一个已知问题(或至少与其他问题有关),但没有提供更多信息。另一方面,Qt VS Tools不赞成使用自定义构建步骤,而推荐使用MSBuild,因此我不确定它是否将得到解决。