Как заставить Qt автоматически находить файлы для MOC'd - PullRequest
0 голосов
/ 13 ноября 2018

Я изменяю некоторые существующие проекты, использующие QT (версия 5.10).Я обновляю их, чтобы использовать лучший, более лаконичный синтаксис msbuild (Target Visual Studio 2015) для Windows.

В одном проекте имеется около 170 заголовочных файлов, из которых около 135 заголовочных файлов необходимо запускать через MOC.exe.Поэтому я написал собственную цель для отправки 135 файлов в moc.exe.Но синтаксис msbuild для указания Moc, какие файлы обрабатывать, довольно длинный.то есть

        <QtMocs Include="A.h;
                    B.h;
                    C.h;
                    D.h;
                    etc...

Я попытался отправить ВСЕ файлы заголовков через moc.exe.Но если заголовочный файл не имеет Q_OBJECT, то moc.exe выдает предупреждение о том, что нет необходимости перемещать заголовочный файл.И чтобы добавить оскорбление к травме, он по-прежнему испускает файл cpp, хотя ничего не требуется для moc'd.

Так что я хотел бы написать хороший короткий (одна строка?) Краткий способ сказать QTmoc только те заголовки, которые нужны.

Возможно ли это?

1 Ответ

0 голосов
/ 15 ноября 2018

Так что после двух дней без ответа я решил написать свое собственное решение, которое работает очень хорошо. Я написал пользовательское задание для MSBuild. Он принимает массив ProjectItem, который должен указывать на все файлы заголовков в вашем проекте. Затем для каждого файла в массиве он открывает файлы, ищет Q_OBJECT и, если найден, сохраняет элемент в выходной массив. Этот выходной массив затем запрашивается и отправляется в moc.exe.

    <!-- Task to automatically discover header files that need to be run through QT's MOC.exe compiler.
     It does this by examing each file and checking if 'Q_OBJECT' is in the file. -->
<UsingTask TaskName="FindFilesForQtMoc" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
    <ParameterGroup>
        <Files    ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
        <MocFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
    </ParameterGroup>
    <Task>
        <Using Namespace="System" />
        <Using Namespace="System.IO" />
        <Using Namespace="System.Diagnostics" />
        <Code Type="Fragment" Language="cs">
        <![CDATA[
        var result = new List<Microsoft.Build.Framework.ITaskItem>();
        foreach(var item in Files)
        {
            String filePath = item.GetMetadata("FullPath");
            var content = File.ReadAllText(filePath);
            if (content.Contains("Q_OBJECT"))
            {
                result.Add(item);
            }
        }
        MocFiles = result.ToArray();
        ]]>
        </Code>
    </Task>
</UsingTask>

Я называю задачу так:

<FindFilesForQtMoc Files="@(ClInclude)" >
        <Output ItemName="FileForMoc" TaskParameter="MocFiles" />
</FindFilesForQtMoc>
<Message Text="Moc: %(FileForMoc.Identity)" />

Поэтому мне нужно только объявить все мои заголовочные файлы в моем .vcxproj следующим образом:

<ClInclude Include="*.h" />

Что лучше, чем явное объявление каждого файла, для которого требуется moc.exe.

...