2

I have several Visual Studio projects created with the Qt Visual Studio Tools (always the latest version available at the moment of the project creation, some dating from the first versions supporting Qt 5, now is the 2.2.1). All projects are compiled with VS 2010, although the IDE is VS 2017 (15.7.4 so far).

From some time on, some projects started to report link errors such as

error LNK2001: unresolved external symbol "public: static struct QMetaObject const MyQtClass::staticMetaObject" (?staticMetaObject@MyQtClass@@2UQMetaObject@@B)

For this example, MyQtClass.h file declares MyQtClass and has the Q_OBJECT macro. MyQtClass.cpp defines the methods.

After a quick inspection, I discovered that the problem came from fact that the associated moc'ed file (moc_MyQtClass.cpp for above example) was excluded from compilation for current configuration. Here the extract of the .vcxproj file:

<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>

If I modify the .vcxproj file to remove the exclusion from the Debug configuration, then the project works.

The problem only happens when the main .cpp file associated to the Q_OBJECTed class is modified (MyQtClass.cpp in my example). At the time such file is saved, the .vcxproj file is modified with the exclusions.

This issue doesn't appears in every Qt project I have, but once it starts it keeps appearing every time the associated .cpp file is modified. I haven't been able to discover a pattern for it. In addition, it happens in several development systems at the company, so it doesn't seem to be a problem of my computer.

The only workaround I've found is to discard the changes from the project file, but it is a headache to be discarding and relaunching the project every time those files are modified (which happens to be a lot of times).

Has anybody experienced the same issue? Any ideas how to solve it?


Update: the issue only happens when the modified file is the .cpp file with identical basename regarding the header file (MyQtClass.cpp in my example). If I modified another file that also defines more methods of the MyQtClass class (such as MyQtClass_more_definitions.cpp), no error is given.


As it seems to be a bug in the Qt Visual Studio Tools with no workaround, I've reported it under QTVSADDINBUG-555.

cbuchart
  • 10,847
  • 9
  • 53
  • 93
  • have your tried Full Rebuild (after clean)? – Dan M. Jun 20 '18 at 16:09
  • @DanM. Yes, the problem is that the project file is modified when the .cpp file is saved: subsequent builds, cleans, rebuilds do nothing. – cbuchart Jun 20 '18 at 16:13
  • do you build in Debug? Does it build in Release? I wonder why it excludes both Release and Debug mocs in Debug and only Debug in Release (as it probably should). Also, there is a chance you'll receive help faster if you try and ask this on qt forums directly. Maybe it's a bug in a new extension. – Dan M. Jun 20 '18 at 16:18
  • @DanM. If build in Debug (and the issue occurs) just fails in Debug, but when working in Release it may happen too. – cbuchart Jun 20 '18 at 16:20
  • seems related/duplicate: https://stackoverflow.com/questions/28455525/qt-vs-addin-obj-files-are-not-generated-for-moc-cpp-files or https://stackoverflow.com/questions/11941885/moc-ed-files-being-exluded-from-build-in-visual-studio-2010 (though it doesn't look like there was a definite solution to the 1st one) – Dan M. Jun 20 '18 at 16:23
  • @DanM. seems to be very similar (probably the same issue although no information about versions is given), but unfortunately no valid answers are given :( – cbuchart Jun 20 '18 at 16:26
  • @buchart, just to be sure: the project was created with the latest (2.2.0+) version of Qt Add-in? Same problem with 2.2.1. But yeah, I'm out of ideas. Maybe folks on Qt forums can help: https://forum.qt.io/ – Dan M. Jun 20 '18 at 16:32
  • @DanM. thanks for your help, the second question didn't help neither (actually, it was already applied). And sorry, yes, plugin is 2.2.1. I'll refer directly to plugin's project page and post the solution here (if any). Thanks again! – cbuchart Jun 20 '18 at 16:34
  • @DanM. I was discussing with the plugin's team and got a solution (with some tweaks), in case you were interested in this issue – cbuchart Jun 26 '18 at 15:34
  • Thanks. Nice knowing you've sorted this out. Was this some bug in the plugin or some problem with configuration? Will it be fixed in future versions? – Dan M. Jun 26 '18 at 19:56
  • @DanM. It seems to be a known issue (or at least related to other ones), but no more information was given. On the other hand, custom build steps are on their way to be deprecated by Qt VS Tools in favor of MSBuild, so I'm not sure if it's going to be fixed – cbuchart Jun 27 '18 at 07:03
  • Ah, OK. I thought latest addin already used MSBuild instead of custom steps. – Dan M. Jun 27 '18 at 11:33
  • @DanM. yes it does... for new projects, old ones are not automatically migrated, that was my case... and even though, migration can create new issues to be solved (see the answer for more detail). – cbuchart Jun 27 '18 at 11:40
  • That explains it. I though you answered positively to mu previous question regarding the version of Addin that was used to create the project, but I now see that you were only replying to the second part of the question, hence my confusion. – Dan M. Jun 27 '18 at 11:44

1 Answers1

6

After discussing it with the Qt VS Tools team, I managed to solve the problem. I've tested it using the latest version of the plugin currently available (2.2.1).

Solution consisted in converting the custom build steps into Qt/MSBuild commands (more about it here). To do so I used the menu option Qt VS Tools / Convert custom build steps to Qt/MSBuild.

After conversion, I had to deal with some issue tough. I document them here:

  • I had to remove all header files with the Q_OBJECT macro and re-add them manually in order to be able to moc'ed them (I also removed/re-added all .ui files, not sure if influenced in anyway).

  • Precompiled headers setting (using PCH) was not respected when adding existing files (.h with Q_OBJECT). Files were added through drag&drop. If I switched PCH off and then on it work for already added files, new ones still needed manual intervention (PCH off/on or editing the .vcxproj as shown below).

    Invalid entry in .vcxproj:

    <QtMoc Include="new_file_added.h" />
    

    Changed to:

    <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>
    

    Another way to solve it is to open the properties of the affected header file and change Qt Meta-Object Compiler / Force Include option to StdAfx.h;../../%(Filename)%(Extension) (change StdAfx.h with your PCH filename if different):

    header file properties

  • I had some QRC files being compiled to a binary file. The binary output was set for every QRC file by default. I had to change the global property to false to solve it:

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

    Or using .qrc properties:

    QRC properties

    Also, output files for them were C++ sources (qrc_*.cpp, instead of the output name in the original project, *.rcc). Just change set the DynamicSource to false and theOutputFile elements in the corresponding ItemGroups:

    <ItemGroup>
      <QtRcc Include="resources\resources.qrc">
        <BinaryOutput>true</BinaryOutput>
        <DynamicSource>false</DynamicSource>
        <OutputFile>$(SolutionDir)\output\resources.rcc</OutputFile>
      </QtRcc>
    </ItemGroup>
    

    Or using the GUI: DynamicSource

After those changes it worked perfectly (in my two environments, VS 2010 and VS 2017).

PS: It seems to be a known issue (or at least related to other ones), but no more information was given. On the other hand, custom build steps are on their way to be deprecated by Qt VS Tools in favor of MSBuild, so I'm not sure if it's going to be fixed.

cbuchart
  • 10,847
  • 9
  • 53
  • 93
  • All I had to do in my case was remove and re-add the header. It was working in Debug but not Release, and the project had been "upgraded" on import - something got missed along the way it seems. – Clifford Oct 07 '19 at 12:29
  • @Clifford that also happened to me, but after a _while_ (undetermined) it happened again, and again... – cbuchart Nov 14 '19 at 14:30