如何让Qt自动找到要MOC的文件

How to make Qt automatically find files to be MOC'd

我正在修改一些使用 QT(5.10 版)的现有项目。我正在更新它们以在 windows.

上使用更好、更简洁的 msbuild 语法(目标 Visual Studio 2015)

一个项目约有170个header个文件,其中约有135个header个文件需要运行到MOC.exe。 因此我写了一个自定义目标来发送 135 个文件到 moc.exe。但是告诉 Moc 要处理哪些文件的 msbuild 语法相当长。 即

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

我尝试将所有 header 文件发送到 moc.exe。但是,如果 header 文件没有 Q_OBJECT,那么 moc.exe 会发出警告,说明不需要 moc header 文件。雪上加霜的是,它仍然会发出一个 cpp 文件,即使不需要 moc'd。

所以我想写一个简短的(一行?)简洁的方法来告诉 QT 仅 moc 需要的 headers。

这可能吗?

所以在两天没有回应之后,我决定编写自己的解决方案,效果非常好。我为 MSBuild 编写了一个自定义任务。它需要一个应该指向项目中所有头文件的 ProjectItem 数组。然后对于数组中的每个文件,它打开文件,搜索 Q_OBJECT,如果找到,则将 Item 保存到输出数组中。然后稍后查询该输出数组并将其发送到 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 的文件要好得多。