【发布时间】:2016-10-10 00:09:24
【问题描述】:
我正在尝试编写一个 MSBuild 脚本,我可以从现有脚本(使用 Visual Studio 生成)导入该脚本,并通过 MSBuild 运行以提取配置信息(CLCompile、Link、Lib 等)
我的想法是,SEN_EXTRACT_CONFIG_GetProjectConfiguration 目标将在每个配置/平台组合中运行一次,并且对于每一个,它将在项目文件上递归运行 MSBuild 多次,每次从每个提到的项目列表中获取 1 个项目。该项目应具有为该配置设置的“默认”元数据(感谢项目的ItemDefinitionGroups)
我对 MSBuild 还很陌生,到目前为止,我已经掌握了以下内容,但它似乎并没有像我预期的那样工作。在内联任务中,我得到 4 个项目,而不是只有 1 个(我猜我不正确理解目标/任务批处理......),它们只有默认元数据,而不是 CLCompile、@ 987654328@等会有。他们的身份是“XXX_SHOULD_BE_UNIQUE”...
如果有更好的方法来解决这个问题,不涉及 Visual Studio GUI,那也很好。
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<UsingTask TaskName="LogItem" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup>
<Items ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<ItemName Required="true" />
<ItemKey Required="true" />
<ItemLog Output="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
System.Diagnostics.Debugger.Break(); // So I can debug, comment out to prevent the build from failing.
bool found = false;
foreach (var item in Items)
{
if (item.GetMetadata("Identity") == ItemKey)
{
if (found) return false;
found = true;
ItemLog = ItemName + "\n";
foreach (var key in item.MetadataNames)
{
if ("Identity" == key) continue;
ItemLog = ItemLog + (String)key + ": " + item.GetMetadata((String)key) + "\n";
}
}
}
return found;
]]>
</Code>
</Task>
</UsingTask>
<PropertyGroup>
<UniqueKey>XXX_SHOULD_BE_UNIQUE</UniqueKey>
</PropertyGroup>
<Target Name="SEN_EXTRACT_CONFIG_GetProjectConfiguration" Outputs="@(ProjectConfiguration->'%(Configuration)|%(Platform)')" >
<Message Text="%(ProjectConfiguration.Configuration)|%(ProjectConfiguration.Platform)" />
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetCLCompile"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="CLCompileTemplate" />
</MSBuild>
<LogItem Items="@(CLCompileTemplate)" ItemKey="$(UniqueKey)" ItemName="CLCompile" >
<Output TaskParameter="ItemLog" PropertyName="CLCompileTemplateLog" />
</LogItem>
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetLink"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="LinkTemplate" />
</MSBuild>
<LogItem Item="@(LinkTemplate)" ItemKey="$(UniqueKey)" ItemName="Link" >
<Output TaskParameter="ItemLog" PropertyName="LinkTemplateLog" />
</LogItem>
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetLib"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="LibTemplate" />
</MSBuild>
<LogItem Item="@(LibTemplate)" ItemKey="$(UniqueKey)" ItemName="Lib" >
<Output TaskParameter="ItemLog" PropertyName="LibTemplateLog" />
</LogItem>
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetResourceCompile"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="ResourceCompileTemplate" />
</MSBuild>
<LogItem Item="@(ResourceCompileTemplate)" ItemKey="$(UniqueKey)" ItemName="ResourceCompile" >
<Output TaskParameter="ItemLog" PropertyName="ResourceCompileTemplateLog" />
</LogItem>
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetProjectReference"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="ProjectReferenceTemplate" />
</MSBuild>
<LogItem Item="@(ProjectReferenceTemplate)" ItemKey="$(UniqueKey)" ItemName="ProjectReference" >
<Output TaskParameter="ItemLog" PropertyName="ProjectReferenceTemplateLog" />
</LogItem>
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetPostBuildEvent"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="PostBuildEventTemplate" />
</MSBuild>
<LogItem Item="@(PostBuildEventTemplate)" ItemKey="$(UniqueKey)" ItemName="PostBuildEvent" >
<Output TaskParameter="ItemLog" PropertyName="PostBuildEventTemplateLog" />
</LogItem>
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Targets="SEN_EXTRACT_CONFIG_GetMidl"
Properties="Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform)" >
<Output TaskParameter="TargetOutputs" ItemName="MidlTemplate" />
</MSBuild>
<LogItem Item="@(MidlTemplate)" ItemKey="$(UniqueKey)" ItemName="Midl" >
<Output TaskParameter="ItemLog" PropertyName="MidlTemplateLog" />
</LogItem>
<Message Text="%(ProjectConfiguration.Configuration)|%(ProjectConfiguration.Platform)" />
<Message Text="$(CLCompileTemplateLog)" />
<Message Text="$(LinkTemplateLog)" />
<Message Text="$(LibTemplateLog)" />
<Message Text="$(ResourceCompileTemplateLog)" />
<Message Text="$(ProjectReferenceTemplateLog)" />
<Message Text="$(PostBuildEventTemplateLog)" />
<Message Text="$(MidlTemplateLog)" />
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetCLCompile" Returns="@(CLCompileTemplate)" >
<ItemGroup>
<CLCompile Include="$(UniqueKey)" />
<CLCompileTemplate Include="%(CLCompile.Identity)" Condition="'%(CLCompile.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetLink" Returns="@(LinkTemplate)" >
<ItemGroup>
<Link Include="$(UniqueKey)" />
<LinkTemplate Include="%(Link.Identity)" Condition="'%(Link.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetLib" Returns="@(LibTemplate)" >
<ItemGroup>
<Lib Include="$(UniqueKey)" />
<LibTemplate Include="%(Lib.Identity)" Condition="'%(Lib.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetResourceCompile" Returns="@(ResourceCompileTemplate)" >
<ItemGroup>
<ResourceCompile Include="$(UniqueKey)" />
<ResourceCompileTemplate Include="%(ResourceCompile.Identity)" Condition="'%(ResourceCompile.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetProjectReference" Returns="@(ProjectReferenceTemplate)" >
<ItemGroup>
<ProjectReference Include="$(UniqueKey)" />
<ProjectReferenceTemplate Include="%(ProjectReference.Identity)" Condition="'%(ProjectReference.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetPostBuildEvent" Returns="@(PostBuildEventTemplate)" >
<ItemGroup>
<PostBuildEvent Include="$(UniqueKey)" />
<PostBuildEventTemplate Include="%(PostBuildEvent.Identity)" Condition="'%(PostBuildEvent.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
<Target Name="SEN_EXTRACT_CONFIG_GetMidl" Returns="@(MidlTemplate)" >
<ItemGroup>
<Midl Include="$(UniqueKey)" />
<MidlTemplate Include="%(Midl.Identity)" Condition="'%(Midl.Identity)'=='$(UniqueKey)'" />
</ItemGroup>
</Target>
</Project>
您可以通过Importing 这个文件在您要使用的项目文件底部进行测试。
【问题讨论】:
-
你得到的详细结果是什么,你期望什么?我修改了代码,你可以在这里查看:1drv.ms/t/s!AresBGZVYryjhR3aJ9-CHelZMBst
-
好吧,一方面,我希望 CLCompileTemplate 项目具有“AdditionalIncludeDirectories”元数据等,但它没有。
-
如何使用此代码获取 AdditionalIncludeDirectories 元数据? var collection = new ProjectCollection(); var project = collection.LoadProject(Item.GetMetadata("Identity")); var d= project.ItemDefinitions.Where(id => id.Key == "ClCompile").First().Value.Metadata.FirstOrDefault(idm=>idm.Name== "AdditionalIncludeDirectories");字符串 s = d == null ? “空”:d.EvaluatedValue;项目日志=s;返回真;
-
你用我的代码试试吗?符合您的要求吗?
-
抱歉,没有时间处理这个问题。
标签: visual-studio visual-c++ msbuild