codester
codester

Reputation: 63

How do I put a condition on msbuild built-in targets like Build/Rebuild?

I am working differentially building a huge monolithic solution that includes about 80 projects. In my build pipeline right now I include a step to build the entire solution. But what I'd like to do is to build the solution but provide conditions as msbuild arguments so that I can exclude some of the projects that might not have any changes associated with them. I already have scripts to go through my commits and realize what changed and which projects need to be built.

I just need a way to send that info to MSBuild so that it does not build all projects everytime. I tried building projects separately but that takes a whole lot more time than just building the solution together.

So, I'm looking for any solutions out there through which I can specify to MSBuild that skip a specific project would help a lot. Thanks much!

Upvotes: 2

Views: 5837

Answers (1)

Mengdi Liang
Mengdi Liang

Reputation: 18958

I already have scripts to go through my commits and realize what changed and which projects need to be built.

Since I could get clearly know that which script are you using to realize what changed and which projects need to be built. I am assuming that you are using MSbuildTarget script which in the xx.csproj to do these judgement.

=If I did not have misunderstanding, you can get help from this similar issue (See ilya's answer).

See this document and you'll find the build action is performed by these three targets, BeforeBuild,CoreBuild and AfterBuild. So assuming you have a target to go through my commits and realize what changed and if a project need to be built, you can add script like below to xx.csproj:

<PropertyGroup>
    <BuildWrapperDependsOn>$(BuildDependsOn)</BuildWrapperDependsOn>
    <BuildDependsOn>CheckIfBuildIsNeeded;BuildWrapper</BuildDependsOn>
  </PropertyGroup>

  <Target Name="CheckIfBuildIsNeeded">
    <!-- Execute command here that checks if proceed with the build and sets the exit code -->
    <Exec Command="exit /b 1" WorkingDirectory="$(SourcesPath)" IgnoreExitCode="true">   
      <Output TaskParameter="ExitCode" PropertyName="ExecExitCode"/>
    </Exec>
    <Message Text="Exit Code: $(ExecExitCode)" Importance="high" />
    <PropertyGroup Condition="'$(ExecExitCode)' == '1'">
      <DoBuild>false</DoBuild>
    </PropertyGroup>
  </Target>

  <Target Name="BuildWrapper" Condition=" '$(DoBuild)' != 'false' " DependsOnTargets="$(BuildWrapperDependsOn)" Returns="$(TargetPath)" />

Above is the script from ilys, and hope my description can help you understand it. With this script, when we start a build target, it will firstly run the targets it depends on, so it will run the CheckIfBuildIsNeeded target and BuildWrapper target. And only when the DoBuild property is true, the BuildWrapper will actually execute. And since buildwrapper depends on original $(BuildDependsOn), it will continue the real build process.

The total logic is: Run CheckIfBuildIsNeeded script and output value to indicates whether need to build=>Try to Run BuildWrapper=>IF need to build, then run the real build success(BeforeBuild, Corebuild,Afterbuild), if the value is false, finish the build process. So I think you can do some little changes to this script then it can work for your situation. (Not sure what your script looks like, I can't complete it for you)

And since you have many projects, you don't need to add this script to every project manually. You can create a Directory.Build.props file, copy the script into it, and place the file in solution folder, then it will work for all projects in the solution.

Upvotes: 3

Related Questions