问题
我假设当 msbuild
即将编译源代码文件时,它会根据 Include
和 Exclude
生成要构建的文件列表项目规则。
有没有办法在评估要编译的文件列表之前执行任务?
这是为了能够生成源代码文件并在构建中使用它。
当前的研究和试验
我正在制作一个 .NET Core CLI 工具,该工具必须在构建使用它的项目之前运行,因为它(CLI 工具)生成一个必须包含在构建中的文件。
该项目是使用新的 .csproj
系统创建的,而不是旧的 project.json
系统。
除了我的 .NET Core CLI 工具项目之外,我还创建了一个用于测试目的的库项目。
如果我将其添加到测试库的 .csproj
中:
<ItemGroup>
<DotNetCliToolReference Include="MyCliTool" Version="x.x.x" />
<!-- here x.x.x is just a placeholder -->
</ItemGroup>
<Target Name="MyCliToolTarget" AfterTargets="Restore" BeforeTargets="BeforeBuild">
<Exec Command="dotnet my-cli-tool" />
</Target>
如果 CLI 工具生成的文件之前不存在,则编译时不会考虑该文件。这意味着当文件存在时,它是可以的,但这也意味着第一次构建(在克隆、清理或其他之后)将始终失败。
我为 BeforeTargets
尝试了几个不同的目标,但找不到使其工作的方法。我尝试在 Project
节点的 InitialTargets
中设置目标,但也不起作用。我尝试将 Target
节点的 Outputs
属性设置为 CLI 工具生成的文件名,但同样失败。
我发现唯一有效的解决方案是手动添加 Compile
指令,如下所示:
<ItemGroup>
<Compile Include="MyGeneratedFile.cs" />
</ItemGroup>
目前这个解决方案很好,但是文件名可能会根据 CLI 工具选项而改变,这将导致两个地方的文件名必须在更改时更新,如下所示:
<ItemGroup>
<Compile Include="PATH\TO\CUSTOM_FILENAME_HERE.CS" />
<DotNetCliToolReference Include="MyCliTool" Version="x.x.x" />
</ItemGroup>
<Target Name="MyCliToolTarget" AfterTargets="Restore" BeforeTargets="BeforeBuild">
<Exec Command="dotnet my-cli-tool --output PATH\TO\CUSTOM_FILENAME_HERE.CS" />
</Target>
(请参阅 CUSTOM_FILENAME_HERE.CS 出现两次)
我知道我可以使用一个常量,如下所示:
<PropertyGroup>
<MyFilename>PATH\TO\CUSTOM_FILENAME_HERE.CS</MyFilename>
</PropertyGroup>
<ItemGroup>
<Compile Condition="!Exists('$(MyFilename)')" Include="$(MyFilename)" />
<DotNetCliToolReference Include="MyCliTool" Version="x.x.x" />
</ItemGroup>
<Target Name="MyCliToolTarget" AfterTargets="Restore" BeforeTargets="BeforeBuild">
<Exec Command="dotnet my-cli-tool --output $(MyFilename)" />
</Target>
但我对这种方法并不满意,假设这仍然是一个简化版本,它会让 lambda 用户集成变得过于复杂,因为 CLI 工具可以采用其他几个选项,这意味着有其他变量,布拉布拉布拉。
我正在使用 .NET Core SDK 1.0.1。
抱歉这个冗长的问题以及我对 msbuild 的不懂。
预先感谢您的时间和帮助。
<小时/>
旁注:在预构建事件中调用 dotnet my-cli-tool
,如下所示:
<PropertyGroup>
<PreBuildEvent>dotnet my-cli-tool</PreBuildEvent>
</PropertyGroup>
根本不起作用,我收到以下错误:
代码:MSB3073 说明:命令“dotnet my-cli-tool”退出,代码为 1。 项目:测试库项目,而不是工具 文件:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets 线路:4935
不过,以下方法可以正常工作:
<PropertyGroup>
<PreBuildEvent>echo meh</PreBuildEvent>
</PropertyGroup>
所以这不是预构建事件的错误。
无论如何,这是另一个故事,我暂时不太关心。
最佳答案
.NET SDK 所称的“默认项”是项目文件静态评估的一部分 - 在任何目标运行之前。因此,您需要一个在需要 @(Compile)
项之前运行的目标。
诀窍是在运行自定义工具后包含添加到文件系统的文件。这可以通过重新扫描所有文件并排除那些在构建之前运行的目标内已经属于项目的文件来完成:
<Target Name="GenerateSomeFiles" BeforeTargets="BeforeBuild">
<Exec Command="dotnet my-tool" />
<ItemGroup>
<Compile Include="**/*$(DefaultLanguageSourceExtension)"
Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder);$(BaseIntermediateOutputPath)**;$(BaseOutputPath)**;@(Compile)" />
</ItemGroup>
</Target>
关于.net - 构建任务之前是否有 .NET Core CLI pre?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44818730/