gpt4 book ai didi

c++ - 如何从 MSBuild 目标修改 ItemDefinitionGroup?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:29:59 25 4
gpt4 key购买 nike

我编写了一个 msbuild 脚本来编译 Google Protocol Buffers 文件:

<ItemGroup>
<ProtocolBuffer Include="Whitelist.proto" />
<ProtocolBuffer Include="Whitelist2.proto" />
</ItemGroup>
<ItemDefinitionGroup>
<ProtocolBuffer>
<ProtoPath>$(ProjectDir)</ProtoPath>
</ProtocolBuffer>
</ItemDefinitionGroup>
<PropertyGroup>
<ProtoC>$([System.IO.Path]::GetFullPath($(ProjectDir)..\ThirdParty\protobuf-2.4.1\protoc.exe))</ProtoC>
<ProtoOutPath>$(IntDir)CompiledProtocolBuffers</ProtoOutPath>
</PropertyGroup>
<Target Name="CompileProtocolBuffers"
BeforeTargets="ClCompile"
Inputs="@(ProtocolBuffer)"
Outputs="@(ProtocolBuffer->'$(ProtoOutPath)\%(FileName).pb.cc');@(ProtocolBuffer->'$(ProtoOutPath)\%(FileName).pb.h')">
<MakeDir Directories="$(ProtoOutPath)" />
<Exec
Command="&quot;$(ProtoC)&quot; --proto_path=&quot;$([System.IO.Path]::GetDirectoryName(%(ProtocolBuffer.ProtoPath)))&quot; --cpp_out=&quot;$(ProtoOutPath)&quot; &quot;%(ProtocolBuffer.FullPath)&quot; --error_format=msvs"
/>
<ItemGroup>
<ClInclude Include="$(ProtoOutPath)\%(ProtocolBuffer.FileName).pb.h" />
<ClCompile Include="$(ProtoOutPath)\%(ProtocolBuffer.FileName).pb.cc">
<AdditionalIncludeDirectories>$(MSBuildThisDirectory)..\ThirdParty\protobuf-2.4.1\src</AdditionalIncludeDirectories>
<PrecompiledHeader></PrecompiledHeader>
<DisableSpecificWarnings>4244;4276;4018;4355;4800;4251;4996;4146;4305</DisableSpecificWarnings>
<PreprocessorDefinitions>GOOGLE_PROTOBUF_NO_RTTI</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemGroup>
</Target>

这完美地编译了 Protocol Buffer 文件,并将它们添加到编译器的输入中(耶!)。但是,我的其他源文件想要包含 .pb.h files 需要知道这些文件是在哪里生成的——生成位置需要放在包含路径上。

因此,当且仅当用户包含了 <ProtocolBuffer item 在他们脚本的某处,我想添加生成位置(在本例中为 $(ProtoOutPath) 到 ClCompile 的 <AdditionalIncludeDirectories>

这是可能的还是我需要让想要使用这些生成的位的 .cpp 文件跳过箍?

最佳答案

阅读您的问题并认为“不可能那么难”。伙计,我错了。首先我想只是给它加上一个条件,但是由于评估顺序,当然不能在顶级条件下使用 ItemGroups。然后我认为也不可能将 ItemDefinitionGroup 放入目标中(因为可以使用条件)并在那里修改它。然后,在我意识到这可能就是你问这个问题的原因后,我在键盘上敲了几次头:](顺便说一句,你知道包含一个不存在的目录并不是真正的问题,因为编译器会很乐意忽略它?)

也许有一个更简单的解决方案,但最后我想到:如果没有任何效果,我最喜欢的 msbuild 玩具 aka CodeTaskFactory 必须能够修复它。它确实如此(我希望,没有完全测试结果),但它一点也不简单。好了,确保在 C++ 构建开始之前 某处调用测试目标。

<!--Uncomment the below to define some ProtocolBuffers-->  
<!--<ItemGroup>
<ProtocolBuffer Include="Whitelist.proto" />
<ProtocolBuffer Include="Whitelist2.proto" />
</ItemGroup>-->

<!--Suppose these are your default include files defined in your C++ project-->
<ItemDefinitionGroup Label="DefaultIncludes">
<ClCompile>
<AdditionalIncludeDirectories>/path/to/x;/path/to/y</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>

<!--Include at least one item so we can play with it-->
<ItemGroup>
<ClCompile Include="iamaninclude"/>
</ItemGroup>

<!--Use code to append to AdditionalIncludeDirectories-->
<UsingTask TaskName="AppendMetadata" TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<Append ParameterType="System.String" Required="true"/>
<ItemList ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true"/>
<OutputItemList ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
</ParameterGroup>
<Task>
<Code>
<![CDATA[
const string dirz = "AdditionalIncludeDirectories";
foreach( var item in ItemList )
{
var cur = item.GetMetadata( dirz );
item.SetMetadata( dirz, cur + ";" + Append );
}
OutputItemList = ItemList;
]]>
</Code>
</Task>
</UsingTask>

<!--Main target-->
<Target Name="Test">
<!--stage 1: copy the itemgroup, then clear it:
if an Output TaskParameter is an Itemgroup, apparently the content
gets appended to the group instead of replacing it.
Found no documentation about this whatsoever though???-->
<ItemGroup Condition="@(ProtocolBuffer) != ''">
<ClCompileCopy Include="@(ClCompile)"/>
<ClCompile Remove="@(ClCompile)"/>
</ItemGroup>

<!--stage 2: append 'ProtoBufIncludeDir' to AdditionalIncludeDirectories,
and append the result to the origiginal again-->
<AppendMetadata ItemList="@(ClCompileCopy)" Append="ProtoBufIncludeDir" Condition="@(ProtocolBuffer) != ''">
<Output ItemName="ClCompile" TaskParameter="OutputItemList"/>
</AppendMetadata>

<!--stage 3: use modified itemgroup-->
<Message Text="@(ClCompile->'%(Identity): %(AdditionalIncludeDirectories)')"/>
</Target>

这打印

iamaninclude: /path/to/x;/path/to/y

除非 ProtocolBuffer 不为空,否则它会打印

iamaninclude: /path/to/x;/path/to/y;ProtoBufIncludeDir

关于c++ - 如何从 MSBuild 目标修改 ItemDefinitionGroup?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18304911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com