Build project with multiple target - visual-studio

I have a project, which is actually build on Win32/.Net4.0 (VS2012).
Now I need to build this project also to x64/.Net4.0, as well as Win32/3.5 and x64/3.5.
I know it's possible with 4 projects, and build every project each time.But the code is always the same, so I want to know if it possible to have one project, which is build on every target on one build process?
Thanks kooki

You can invoke msbuild multiple times against the same project/solution to cover all your required configurations. Just pass the configuration via the command line. So, for a Release configuration for x86:
msbuild MySolution.sln /p:Configuration=Release /p:Platform=x86
You can then add a second call for another target platform.

Related

How can I make msbuild understand that a .csproj file depends on the availability of an exe built by another .csproj

I have a large VStudio solution whose .csproj files I'm porting over to the new .NET SDK format. I have integrated the github project with AppVeyor. When I work on the solution, my project is built by VStudio; AppVeyor uses msbuild to build my project.
All of the class library project files in the solution have been modified so that they specify <TargetFrameworks>netStandard2.0</TargetFrameworks>. For simplicity, let's represent the class library project files with classlib.csproj.
The solution also contains a few command-line tools, which need to be built in advance of some of the other projects, because those later projects need to run the command-line tools as a preprocessor before building themselves. These command-line projects are all specifying <TargetFrameworks>net472;netcoreapp2.0</TargetFrameworks>. Let's represent the tool project files with tool.csproj.
In order to build correctly, tool.csproj needs to be built before classlib.csproj. In the solution I've used the Build dependencies > Project dependencies command in the VStudio solution explorer to indicate this. This works fine when I'm working inside of VStudio.
However, when I push my changes to github, AppVeyor kicks off an msbuild process to build the projects. From the error spew, it's clear that the tool.csproj didn't get built in time. It seems msbuild doesn't understand the project dependency information in the .sln file.
Reading what's posted on the intertubes (e.g. https://devblogs.microsoft.com/visualstudio/incorrect-solution-build-ordering-when-using-msbuild-exe/), I attempted to add the following to classlib.csproj:
<ProjectReference Include="..\tool\tool.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
But when I do this I get the error:
Project '..\tool\tool.csproj' targets 'net472;netcoreapp2.0'. It cannot be referenced by a project that targets '.NETStandard,Version=v2.0'
which clearly makes sense.
Some other solutions I've read suggest editing the .sln file so that tool.csproj gets built first, and hope that building will be completed before classlib.csproj starts building. However, this is a race condition since msbuild is not aware of the dependency.
How, then, do I express that classlib.csproj depends on tool.csproj so that msbuild understands it?
EDIT
It turns out the issue was caused by an interaction between the target I'd written to start my tool and the globbing operation MSBuild does to resolve the <Compile> item collection using a pattern similar to **\*.cs. The tool generated the file after the globbing operation. Since the generated file isn't present when the globbing happens, it is missing from the <Compile> item collection, and the build failed. I mistakenly interpreted the error "foo.cs not found" as a failure to execute the tool, when in fact, it's a timing issue.
To make the build order works outside VS IDE, we need to use add reference
instead of BuildDependencies=>ProjectDependencies.
Right-click classlib project and choose add=>reference, in Project node choose the Tool Project you want like this:
Click ok to add it and save changes. After that, open the classlib.csproj you can find sentence like:
<ItemGroup>
<ProjectReference Include="..\xxx\Tools.csproj">
<Project>{6eaa430f-9793-4639-a84b-6ab767d57147}</Project>
<Name>Tools.csproj</Name>
</ProjectReference>
</ItemGroup>
This what the msbuild can understand. And I think that's what you want.
After that,you can use a single msbuild tool or Appveyor to check the
build order.
And in Appveyor, we can also disable the paralell builds(settings=>build=>msbuild options) to make sure it won't build classlib.csproj until the tools.csproj build ends.
The final build order in Appveyor will be what we defined in VS. Hope it helps.

How to create Target that always runs at the end of a build

I've got a vxcproj with configuration type Driver and am trying to edit the project file to add a custom target that will always run at the end of building the project. I want it to run even if the standard build system detects it doesn't need to build anything.
I'm having a hard time trying to work out where to attach my target. If I attach to AfterBuild or PostBuildEvent, my target won't run if there's nothing to build.
If you're interested, I need this target to run run StampInf and Inf2Cat tasks as the built in versions of those don't suit my purposes. The built in ones always run and dirty outputs, causing knock on rebuilding which I don't want in an incremental build.
Add a project of type General + Makefile. VS cannot optimize the build for these type of projects, the custom Build Command Line setting you specify always runs. You'll typically need to set the project dependencies to ensure it runs last.

How can I use build parameters from other projects in TeamCity?

I would like to use some build parameters from Project 1 in Project 2. I know that I can make Project 1 a dependency of Project 2 and then access its build parameters as described in Dependencies Properties, but I do not want Project 1 to be built in response to a build of Project 2. For example, suppose I want Project 2 to be built nightly, while I only want Project 1 built monthly.
Is there any way Project 2 can access Project 1's build parameters under these conditions?
I would use a build configuration template that is shared between the two projects.
This means you can share properties between the projects, but also override certain ones in each individual project.
We use this for hourly builds that are not tagged and nightly ones that are tagged.
Then use a different build trigger to set one off nightly and the other monthly.
EDIT
I'll just expand slightly as a result of your comment.
In TeamCity we have 2 build configuration for the same project. One that builds on every check-in to give developers quick feedback on their contribution (build within 15 minutes). It does the following:
Builds the project in Debug
Runs all unit tests
Checks results of build into Subversion
The other configuration runs every night at midnight; it build everything and as a result takes a long time (around 45 minutes). It does the following:
Build the project in Debug and Release
Runs all unit tests
Builds Sandcastle documentaion
Checks results of build into Subversion
Grabs the Sandcastle output at an artefact so developers can easily download it.
As you pointed out this isn't as straightforward as one would like; however you can use the following to achieve it:
We use the Autoincrementer to share build numbers between the two configurations (they both increment the same build number when built).
We have a property on template that defines what artefacts to collect and is referenced from the artefacts field. The property is overridden on the second build config to define the sandcastle output to grab.
Sharing VCS Roots is mentioned on the documentation. Both our builds get the source from the same place, and tag the results to the same place. One VCS is most definitely all we need.
Bit of a long edit but I think it goes exactly on the lines of what you're trying to achieve. I appreciate I should have included this in the original answer.
HTH
Dependency is different from Build Triggering in TeamCity. If you make one project dependent on another ( artifact dependency ), it does not mean that the the latter will trigger the former.
Even when one project has been defined as dependent on another ( and also, even if not ) you have to specify explicitly the build trigger ( in this case a Finish build trigger ) for the dependent project to be triggered.

MSBuild reports that build Failed however the log reports Build Successful

I'm having trouble with an MSBuild script as it's executing correctly, but in TFS Build Explorer it reports a Fail (red X icon). However, despite all the builds reporting failed, if I examine the logs, they look fine, and end with :
Done building target "EndToEndIteration" in project "TFSBuild.proj".
Done Building Project "C:\Builds\EDRM Development\CI_Development_IW471_UserGroup_CG3\BuildType\TFSBuild.proj" (EndToEndIteration target(s)).
Build succeeded.
0 Warning(s)
0 Error(s)
What exactly is Build Explorer using to determine the success of the build script ?
The script itself is using the MSBuild Extension Pack (from CodePlex) to build a solution containing 40+ VB6 projects. So that it can be run by team build, i've implemented target EndToEndIteration, with the build target as a 'DependsOnTargets'. EndToEndIteration is the only one of team build's targets that I have implemented in the script (it appears to be the only mandatory one ?).
When i run the script from the command line it reports success also, so it's only Build Explorer that's indicating a failure.
Any ideas why this is happening ?
The success of the build is determined by ALL Tasks ended with success pattern (if one fails it may be consider as partially succeed build, but the icon will still remain as a failure icon with small green success icon:)
Try to look at build log's, because it seems, that some pre or past run steps are failing (unable to copy sth, etc). The easiest way is to determine where the problem is, is to schedule the build from Visual Studio with maximum verbosity level for each Task.
Thanks for the reply. All tasks were ending with success.
I've just found out the solution though, so I'll add it here.
As I'm building a VB6 solution (comprising 40+ projects), I'd created a pure msbuild script, that i'd originally been running from the command line. To use it with team build for CI, i'd added a target "EndToEndIteration" as this is the only mandatory target for a new msbuild script in team build (i.e. a script not created via TFS's create build script wizard). This results in the problem above, where even if the script executes perfectly, build explorer still reports failure.
The solution is to create a build script using the TFS wizard (for any .Net .sln file - it doesn't matter - the reference to it will be deleted). Then take a copy of this tfsbuild.proj file and strip out the details relating to the .Net project and paste in your msbuild targets. Then implement target "CoreCompile" to initiate the targets you pasted in.

CruiseControl.NET: Building a project in Debug and Release configurations

I am using CruiseControl.NET to build a C# project. I am using an msbuild task to achieve this. I want to build the project in both Debug and Release mode irrespective of whether either mode fails. But If I put these as two msbuild tasks in the 'tasks' section of the project and if the first task fails, the second is not executed.
I could define them as two projects, but I want the Label to be synchronized across both the projects. Is there a way to do this?
One solution I have is make the 'Release' config project to trigger a build whenever the 'Debug' config project is built. But in that case, If someone force builds the 'Debug' config project then, the labels will get out of sync.
To achieve what you want, I think you will have to use a custom task to call MSBUILD from a CMD file and pass the debug/release mode into MSBUILD via cmd line args.
Use multiple tasks for the project.
Note: See CC.NET preprocessor if you want to reduce tags duplication.

Resources