如何让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 的文件要好得多。
我正在修改一些使用 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 的文件要好得多。