Having a Project dependency in incremental Target #8077
-
Hello! I have some questions regarding incremental build targets. My targets are setup like this: <ItemGroup>
<Spec Include="..\spec.xml" />
<GeneratedFiles Include="files to generate" Exclude="manually edited files" />
</ItemGroup>
<!-- 'DispatchToInnerBuilds' is so that this target is only run once in contrast to task that run after 'PreBuildEvent' which get run multiple times for each target framework -->
<Target Name="Download spec" BeforeTargets="DispatchToInnerBuilds">
<!-- Here we check if spec.xml exists, if it doesn't we download the file. -->
<DownloadFile SourceUrl="url" DestinationFolder=".." SkipUnchangedFiles="true" Condition="Exists('../spec.xml') == 'false'" />
</Target>
<!-- We build this project once for the entire build, then we can call into the exe directly to avoid having multiple processes trying to build the project at the same time and failing. -->
<Target Name="Build bindings generator" BeforeTargets="DispatchToInnerBuilds">
<Exec Command="dotnet build ./src/Generator.Bind/Generator.Bind.csproj --framework netcoreapp3.1" WorkingDirectory="../../" StandardOutputImportance="low" StandardErrorImportance="low" />
</Target>
<!-- After we've downloaded the spec file we can generate the bindings if needed. By setting Inputs and Outputs msbuild decides when we need to generate the bindings. -->
<Target Name="Generate bindings" AfterTargets="Download spec" BeforeTargets="CoreCompile;CopyFilesToOutputDirectory" Inputs="@(Spec)" Outputs="@(GeneratedFiles)">
<Exec Command="echo Generating bindings..." />
<Exec Command=".\src\Generator.Bind\bin\$(Configuration)\netcoreapp3.1\Bind.exe" WorkingDirectory="../../" />
<Exec Command="echo Generated bindings!" />
<ItemGroup>
<Compile Include="@(GeneratedFiles)" Condition="'%(Compile.Identity)' != '%(GeneratedFiles.GeneratedFiles)'"/>
<!-- For clean to work properly -->
<FileWrites Include="@(GeneratedFiles)" />
</ItemGroup>
</Target> Any other tips on how to improve this project file setup would also be greatly appreciated. There are probably tons of features that I don't even know about. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 5 replies
-
One way that many projects think about this is not "were there any changes in the generator project" but "has the output of the generator project changed?" Would that work for you? If so, add the generator executable and any support files like DLLs or configuration to the inputs of the |
Beta Was this translation helpful? Give feedback.
-
You can accomplish this goal with lower overhead and cleaner logging by using the - <Exec Command="echo Generating bindings..." />
+ <Message Text="Generating bindings..." /> You may also wish to add |
Beta Was this translation helpful? Give feedback.
-
We have docs on a fairly closely related scenario: https://learn.microsoft.com/visualstudio/msbuild/tutorial-custom-task-code-generation. That uses a task to do the code generation, instead of calling a command-line tool, but much of the setup is similar so reading that will likely be helpful. As always with our docs, feedback is welcome! |
Beta Was this translation helpful? Give feedback.
-
It's almost always a bad idea to exec Here, you can replace that target with a I made some modifications to your logic before starting this but this is the diff I applied: diff --git a/ConsumesGeneratedFiles/ConsumesGeneratedFiles.csproj b/ConsumesGeneratedFiles/ConsumesGeneratedFiles.csproj
index 3ab3a7d..51f9003 100644
--- a/ConsumesGeneratedFiles/ConsumesGeneratedFiles.csproj
+++ b/ConsumesGeneratedFiles/ConsumesGeneratedFiles.csproj
@@ -12,12 +12,13 @@
<GeneratedFiles Include="..\Generated.cs" />
</ItemGroup>
-<!-- 'DispatchToInnerBuilds' is so that this target is only run once in contrast to task that run after 'PreBuildEvent' which get run multiple times for each target framework -->
-
-<!-- We build this project once for the entire build, then we can call into the exe directly to avoid having multiple processes trying to build the project at the same time and failing. -->
-<Target Name="Build bindings generator" BeforeTargets="DispatchToInnerBuilds">
- <Exec Command="dotnet build Generator/Generator.csproj --framework netcoreapp3.1" WorkingDirectory=".." StandardOutputImportance="low" StandardErrorImportance="low" />
-</Target>
+<ItemGroup>
+ <ProjectReference Include="..\Generator\Generator.csproj"
+ SkipGetTargetFrameworkProperties="true"
+ UndefineProperties="TargetFramework"
+ ReferenceOutputAssembly="false"
+ ExcludeAssets="all" />
+</ItemGroup>
<!-- After we've downloaded the spec file we can generate the bindings if needed. By setting Inputs and Outputs msbuild decides when we need to generate the bindings. -->
<Target Name="Generate bindings" AfterTargets="Download spec" BeforeTargets="CoreCompile;CopyFilesToOutputDirectory" Inputs="@(Spec)" Outputs="@(GeneratedFiles)"> Relevant metadata:
|
Beta Was this translation helpful? Give feedback.
It's almost always a bad idea to exec
dotnet build
within a build--it can create race conditions, the logging is mostly lost, and it's just generally clunky.Here, you can replace that target with a
ProjectReference
to the generator project, with some special properties to ensure that it builds "normally" instead of "how it would need to to be referenced here".I made some modifications to your logic before starting this but this is the diff I applied: