MSBuild Post-Build
Asked Answered
P

3

6

I've got an MSBuild script that is just about doing everything that I need it to do apart from my post-build step (see a previous question that I asked: MSBuild conditional Exec?).

What I'm looking to do is build many csproj files and optionally perform post-build steps if and only if the project was built. I don't want to perform my post-build step all the time or else the timestamp on my final output will be modified unnecessarily (and it makes the build process very time consuming for no reason).

In my MSBuild script I've got something like the following for each of my csproj files:

<Target Name="ProjectName">
   <MSBuild Projects="PathToProject" Properties="Configuration=$(buildtype)" />
</Target>

Edit: I think what I really want to do is detect when the CoreCompile task runs for each project. If there were some way to check for this in a condition?

Any ideas?

I'm new to MSBuild so maybe I'm on completely the wrong track!

Thanks, Alan

Pruchno answered 26/11, 2010 at 12:12 Comment(0)
P
1

After much searching for a simple solution to this problem I didn't find one and ended up coming up with a solution of my own that works but may not be the best solution. However, I wanted to share it with anyone else that is having the same problem so that you can at least have a working solution and hopefully saving you a lot of head banging.

To recap, what I wanted to do was run a command line tool after my project was built but only if the assembly was updated (i.e. the timestamp changed). I didn't want to put this into the post-build section of every project because I only wanted the post-build to happen on our build server (not development machines).

I didn't find any way of doing this externally in my main .proj file and did end up altering the post-build section of each .csproj file. However, I prefixed it with an if condition something like this:

if '$(ExecuteCommand)' == 'true' command.exe

This means that the command will never be executed on the development machine but when I invoke the build from my .proj file I can set that flag to true like this:

<!-- Define common properties -->
<PropertyGroup>
    <ExecuteCommand>true</ExecuteCommand>
</PropertyGroup>

<Target Name="YourTarget">
    <!-- Build project -->
    <MSBuild Projects="Path to project" Properties="ExecuteCommand=$(ExecuteCommand)" />
</Target>

As I said, I don't think it is the most graceful solution but it certainly works and will be sufficient for me for the time being. However, I'd still be interested to hear what the proper way of achieving this is so that I can improve my script.

Thanks, Alan

Pruchno answered 28/11, 2010 at 20:46 Comment(0)
M
6

You can also do it based on the configuration selected in your build process. For CI, you should always use "Release" or "Production" (you can define your own).

<Exec Condition="'$(ConfigurationName)'=='Release'" Command="your command goes here ..."/>
Maya answered 28/2, 2014 at 1:13 Comment(2)
It's weird that the documentation implies this will not work, but it seems to work for me!Rashid
UPDATE: This seems to half work - the documentation says Condition is not supported with Exec but this seems to work. However, any later Exec segments also seem to be affected by the Condition, even if they do not include it.Rashid
P
1

After much searching for a simple solution to this problem I didn't find one and ended up coming up with a solution of my own that works but may not be the best solution. However, I wanted to share it with anyone else that is having the same problem so that you can at least have a working solution and hopefully saving you a lot of head banging.

To recap, what I wanted to do was run a command line tool after my project was built but only if the assembly was updated (i.e. the timestamp changed). I didn't want to put this into the post-build section of every project because I only wanted the post-build to happen on our build server (not development machines).

I didn't find any way of doing this externally in my main .proj file and did end up altering the post-build section of each .csproj file. However, I prefixed it with an if condition something like this:

if '$(ExecuteCommand)' == 'true' command.exe

This means that the command will never be executed on the development machine but when I invoke the build from my .proj file I can set that flag to true like this:

<!-- Define common properties -->
<PropertyGroup>
    <ExecuteCommand>true</ExecuteCommand>
</PropertyGroup>

<Target Name="YourTarget">
    <!-- Build project -->
    <MSBuild Projects="Path to project" Properties="ExecuteCommand=$(ExecuteCommand)" />
</Target>

As I said, I don't think it is the most graceful solution but it certainly works and will be sufficient for me for the time being. However, I'd still be interested to hear what the proper way of achieving this is so that I can improve my script.

Thanks, Alan

Pruchno answered 28/11, 2010 at 20:46 Comment(0)
H
0

If you can add the following to each of your projects:

<Target Name="DoStuffWithNewlyCompiledAssembly">
    <Exec Command="command.exe" />
</Target>

... then you only need to add a property:

<Target Name="Name">
  <MSBuild Projects="" Properties="TargetsTriggeredByCompilation=DoStuffWithNewlyCompiledAssembly" />
</Target>

This works because someone smart at Microsoft added the following line at the end of the CoreCompile target in Microsoft.[CSharp|VisualBasic][.Core].targets (the file name depends on the language and MSBuild/Visual Studio version).

<CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''"/>

So if you specify a target name in the TargetsTriggeredByCompilation property, your target will run if CoreCompile runs-- and your target will not run if CoreCompile is skipped (e.g. because the output assembly is already up-to-date with respect to the code).

Hurry answered 4/1, 2018 at 20:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.