12

I want to inhibit the building of certain projects within a solution from building (within a TeamCity Build Configuration in order to optimize the speed of my Commit Build feedback if you must know).

I'm aware of the Solution Configurations mechanism but don't want to have to force lots of .sln files to end up with every permutation of things I want to be able to switch off. I have Convention based rule where I want to say "If I'm doing the Commit Build, I dont want to do the final installer packaging". (And I don't want to break it out into a separate solution).

I'd prefer not to use a solution involving find and replace in the .sln file or in a .proj file created via [MsBuildEmitSolution][1]. I'm aware of questions here which cover the out of the box solution and this slightly related question.

I see MSBuild /v:diag is saying:

 2>Target "Build" in file "Z.sln.metaproj" from project "Z.sln" (entry point):
   Using "MSBuild" task from assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
   Task "MSBuild"
     Global Properties:
       BuildingSolutionFile=true
         CurrentSolutionConfigurationContents=<SolutionConfiguration>
   <ProjectConfiguration Project="{C83D035D-169B-4023-9BEE-1790C9FE22AB}" AbsolutePath="X.csproj" BuildProjectInSolution="True">Debug|AnyCPU</ProjectConfiguration>
   <ProjectConfiguration Project="{15E7887D-F1DB-4D85-8454-E4EF5CBDE6D5}" AbsolutePath="Y.csproj" BuildProjectInSolution="True">Debug|AnyCPU</ProjectConfiguration>
 </SolutionConfiguration>

So the question is:

Is there a neat way of me getting to do an XPath replace or similar to have the effect of changing BuildProjectInSolution="True" to BuildProjectInSolution="False" for Project Y above

Failing that, is there a relatively simple edit I can do within a .ccproj (An Azure 1.4 Package) or a .csproj (a general project) file to cause the effects (including triggering of dependent projects) of the project being enabled within a commandline msbuild Z.sln solution build to be nullified?

Community
  • 1
  • 1
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • 1
    There's nothing wrong with a custom MSBuild file. I'm not sure why that doesn't qualify as a neat solution. – Ritch Melton May 12 '11 at 15:11
  • @Ritch Melton: I already have a fantastic custom msbuild file building the set of solutions (in parallel etc. achieving fantastic throughput). I *am* after something where subsytems within the product can be loaded into VS and have projects added and taken away - hence `.sln` files. I was pointing out that its sad if the only thing I can do is force MSBuild to emit a .proj file equivalent as that just feels liek storing up trouble for whenever MSBuild 5 changes the game (or when the VS team finally get that having .sln files not being special cases is kinda, well, important for real projects!) – Ruben Bartelink May 12 '11 at 19:29
  • I feel ya. The sln file problem is ridiculous. There's a few msbuild issues and its integration with visual studio that I just don't understand. That rant is too long to post here. – Ritch Melton May 12 '11 at 20:32
  • @Ritch Melton: I generally don't let such minor issues as length prevent me from venting :D Thanks for the responses. – Ruben Bartelink May 13 '11 at 07:47

3 Answers3

4

Not sure it qualifies as neat, but you can set CustomAfterMicrosoftCommonTargets to import an msbuild file to over-ride the BuildDependsOn property, pointing it to your own custom build task. Basically, by setting CustomAfterMicrosoftCommonTargets you get msbuild to import an msbuild file containing the following:

<PropertyGroup>
    <OldBuildDependsOn>$(BuildDependsOn)</OldBuildDependsOn>
    <BuildDependsOn>MyBuild</BuildDependsOn>
</PropertyGroup>

<Target Name="OldBuild" DependsOnTargets="$(OldBuildDependsOn)" />

<Target Name="MyBuild">
    <CallTarget Targets="OldBuild" Condition="<IfIWantThis>" /> 
</Target>

Edit

You can use the following MyBuild target to Include/Exclude projects based on regular expressions passed in as IncludeInBuild and ExcludeFromBuild properties. (If you want complex regexes, you may fall foul of MSBuild special character escaping, but this works well enough for simple matching)

> msbuild /p:ExcludeFromBuild="Tests|Install|Azure"

<Target Name="MyBuild">
    <CallTarget Targets="OldBuild" Condition="('$(IncludeInBuild)'=='' OR
    '$([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectFullPath),
    $(IncludeInBuild), 
    System.Text.RegularExpressions.RegexOptions.IgnoreCase))'=='True') AND 
    ('$(ExcludeFromBuild)'=='' OR 
    '$([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectFullPath), 
    $(ExcludeFromBuild),  
    System.Text.RegularExpressions.RegexOptions.IgnoreCase))'=='False')" /> 
</Target>
Rob
  • 4,327
  • 6
  • 29
  • 55
  • +1 Interesting technique. Don't see how it is particularly appropriate as a way to selectively affect the building or not of a subset of project in a solution based on some declarative rules - I'd have to generate the CustomAfterMicrosoftTargets on the fly to be able to achieve that using this angle of attack... – Ruben Bartelink Sep 20 '13 at 00:27
  • I'm not sure that's true. The approach I use is to have a static msbuild file `ShouldBuild`. This file contains a `UsingTask` (so I can use c# inline as I hate msbuild) that returns true or false based on some input properties. Currently I only take the `$(MSBuildProjectFullPath)`, and return false if it's an installer or has `prototype` in the path. But I could take multiple properties, including say a regular expression string, or an XPath string, or anything that I can use to determine whether to build the project or not. – Rob Sep 20 '13 at 06:47
  • What I mean is, I omitted the logic for defining ``. I just use `String.Contains`, which is fairly crude, but you can make this as simple or as complex as you want. – Rob Sep 20 '13 at 07:00
  • Right, it makes sense now you've provided the missing link (which I should have thought of had this been front of mind for me) and can be used as the base for a general approach (one could use `String.Split` and then batching to do the matching etc.). Thanks for the solution! – Ruben Bartelink Sep 20 '13 at 12:47
4

You could always pass the particular projects you want to build as parameters to the MSBuild.

The MSBuild command line would look like this:

MSBuild /t:<Project Name>:Rebuild;<Another Project Name>:Rebuild

In TeamCity, you would put <Project Name>:<Target Action> in the target field in the MSBuild runner.

Eric
  • 466
  • 6
  • 9
  • Are you saying this (MSBuild being passed a set of top level projects) is something native or (as @Ritch Melton [appears to] has said) that I could cruft something up to use instead of `.sln` files. For a start, even splitting the above up would require custom tasks (be that a compiled one or a PS or C# TaskFactory-based one). I'm probably missing your point thoughh and remain all ears as to how me, sitting with 5 .sln files can get the 50 `.csproj`/`.ccproj`s therein built without the projects named `*.AzurePackage`(or maybe without the `*.ccproj`s) without chucking VS slns as grouping – Ruben Bartelink May 12 '11 at 19:36
  • @Ruben Bartelink: I believe that you can pass a set of top level projects in natively. This would require a large amount of typing (passing 50 targets into an msbuild command line), but would not require you to create new targets or modify a sln/csproj file. – Eric May 13 '11 at 12:57
  • I'd like to see an example of that. In terms of whether it solves my problem, I still dont end up with the ability to have a sln file with e.g. 14 projects in it and have someone add a new project in and disable another for a given configuration and have that reflected in what happens when I run the build – Ruben Bartelink May 20 '11 at 18:27
-2

I add a system parameter under Parameters

  • Name: system.ExcludeFromBuild
  • Kind: System property (system.)
  • Value: path to your csproj

parameter pass

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • 1
    Are you suggesting this as a way to apply the scheme in [the other answer](http://stackoverflow.com/a/18900915/11635) or are you suggesting this is an intrinsic capability of the default project system? – Ruben Bartelink May 17 '17 at 10:12