Moc’-файл загадочным образом исключается из проекта Visual Studio

У меня есть несколько проектов Visual Studio, созданных с помощью инструментов Qt Visual Studio (всегда последняя версия, доступная на момент создания проекта, некоторые датируются первыми версиями, поддерживающими Qt 5, теперь это 2.2.1). Все проекты скомпилированы с VS 2010, хотя IDE — VS 2017 (пока 15.7.4).

С некоторых пор некоторые проекты начали сообщать об ошибках ссылок, таких как

ошибка LNK2001: неразрешенный внешний символ «public: static struct 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, чтобы удалить исключение из конфигурации отладки, тогда проект будет работать.

Проблема возникает только тогда, когда главный .cpp файл, связанный с Q_OBJECTРедактируемый класс изменен (MyQtClass.cpp в моем примере). Во время сохранения такого файла файл .vcxproj изменяется с исключениями.

Эта проблема не появляется в каждом проекте Qt, который у меня есть, но как только он запускается, он появляется каждый раз, когда изменяется связанный файл .cpp. Я не смог найти образец для этого. Кроме того, это происходит в нескольких системах разработки в компании, так что это не проблема моего компьютера.

Единственный обходной путь, который я нашел, — это отменить изменения из файла проекта, но это головная боль, от которой нужно отказаться и перезапустить проект. каждый раз эти файлы изменены (что, оказывается, много раз).

Кто-нибудь испытывал такую ​​же проблему? Есть идеи как это решить?


Обновление: проблема возникает, только когда измененный файл является .cpp файлом с идентичным базовым именем относительно файла заголовка (MyQtClass.cpp в моем примере). Если я изменил другой файл, который также определяет больше методов MyQtClass класс (такой как MyQtClass_more_definitions.cpp), ошибки не выдается.


Поскольку это кажется ошибкой в ​​инструментах Qt Visual Studio без обходного пути, я сообщил об этом в QTVSADDINBUG-555.

0

Решение

После обсуждения этого вопроса с командой Qt VS Tools мне удалось решить проблему. Я протестировал его, используя последнюю версию плагина, доступную в настоящее время (2.2.1).

Решение состояло в преобразовании пользовательских шагов сборки в команды Qt / MSBuild (подробнее об этом Вот). Для этого я использовал опцию меню Qt VS Tools / Конвертировать пользовательские шаги сборки в Qt / MSBuild.

После конвертации мне пришлось столкнуться с какой-то проблемой. Я документирую их здесь:

  • Я должен был удалить все файлы заголовков с Q_OBJECT макрос и повторно добавить их вручную, чтобы иметь возможность их moc’ed (я также удалил / заново добавил все файлы .ui, не уверен, если это как-то повлияло).

  • Параметр предварительно скомпилированных заголовков (с использованием PCH) не учитывался при добавлении существующих файлов (.h с 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 / Force Include возможность StdAfx.h;../../%(Filename)%(Extension) (менять StdAfx.h с вашим именем PCH, если оно отличается):

    свойства заголовочного файла

  • У меня было несколько QRC-файлов, скомпилированных в двоичный файл. Двоичный вывод был установлен для каждого файла QRC по умолчанию. Мне пришлось изменить глобальное свойство на false решить это:

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

    Или используя свойства .qrc:

    QRC свойства

    Кроме того, выходные файлы для них были источниками C ++ (qrc_*.cppвместо имени вывода в исходном проекте, *.rcc). Просто измените набор DynamicSource в false иOutputFile элементы в соответствующем ItemGroups:

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

    Или используя графический интерфейс:
    DynamicSource

После этих изменений он работал отлично (в двух моих средах, VS 2010 и VS 2017).

PS: Кажется, это известная проблема (или, по крайней мере, связанная с другими), но больше информации предоставлено не было. С другой стороны, пользовательские этапы сборки в настоящее время не рекомендуется использовать Qt VS Tools в пользу MSBuild, поэтому я не уверен, будет ли он исправлен.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]