在任何给定生成中,生成过程中生成的文件的行为与静态文件(如源文件)不同。 因此,请务必了解 MSBuild 如何生成项目。 这两个阶段是 评估阶段 和执行 阶段。 在评估阶段,MSBuild 会读取项目、导入所有内容、创建属性、扩展项的 glob,并设置生成过程。 在执行阶段,MSBuild 通过运行目标和任务来执行生成,并在评估阶段分析数据。
在执行期间生成的文件在评估阶段不存在,因此它们不包括在生成过程中。 若要解决此问题,必须手动将生成的文件添加到生成过程中。 建议执行此作的方法是在目标之前BeforeBuild将新文件添加到Content或None项,如以下示例所示:
<Target Name="MyTarget" BeforeTargets="BeforeBuild">
<!-- Some logic that generates your file goes here -->
<!-- Generated files should be placed in $(IntermediateOutputPath) -->
<WriteLinesToFile
File="$(IntermediateOutputPath)GeneratedFile.cs"
Lines='enum MyEnum { A, B }'
Overwrite="true" />
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)GeneratedFile.cs" />
</ItemGroup>
<ItemGroup>
<!-- If your generated file was placed in `obj\` -->
<None Include="$(IntermediateOutputPath)GeneratedFile.cs" TargetPath="GeneratedFile.cs" CopyToOutputDirectory="PreserveNewest"/>
<!-- If you know exactly where that file is going to be, you can hard code the path. -->
<None Include="some\specific\path\my-generatedfile" CopyToOutputDirectory="PreserveNewest"/>
<!-- If you want to capture "all files of a certain type", you can glob like so. -->
<None Include="some\specific\path\*.xyz" CopyToOutputDirectory="PreserveNewest"/>
<None Include="some\specific\path\*.*" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
</Target>
<Target Name="CleanGeneratedCode" AfterTargets="CoreClean">
<Delete Files="$(IntermediateOutputPath)GeneratedFile.cs" />
</Target>
将生成的文件添加到 None 生成过程或 Content 足以查看它。 你还希望确保它在正确的时间添加。 理想情况下,目标在之前 BeforeBuild运行。
AssignTargetPaths 是另一个可能的目标,因为它是在将项转换为新项之前修改 None 和 Content 项(等等)的最终机会。 请参阅 常见项类型。
复制上述内容,将其粘贴到文件中,并调用该文件 buildcodegen.targets。 然后,运行 dotnet new console、导入文件并生成该文件以查看其工作原理。
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="buildcodegen.targets"/>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
运行 msbuild.exe 并查看输出,验证文件是否已生成并复制到输出文件夹。 可以使用 ildasm.exe 来确认输出二进制文件是否包含生成的代码 MyEnum:
ildasm CodeGen.dll
后续步骤
可以改进此示例以支持更现实的用例。 例如,在生成的代码依赖于输入文件时支持 增量生成 , Inputs 应 Outputs 提供给目标。 仅当输入文件或文件的日期比输出文件更新时,此类目标才会重新生成文件。 通常,自定义代码生成时,建议创建自定义任务。 请参阅 创建自定义任务以生成代码。