csproj file settings for several build projects - visual-studio

I have this solution structute:
Solution.sln
|--WebUI.csproj (has Core.csproj as dependency)
|--Core.csproj
|--Tests
|--UnitTests
|--WebUI.UnitTest.csproj (has Core.csproj and WebUI.csproj as dependencies)
|--Core.UnitTest.csproj (has Core.csproj as dependency)
What should I add to WebUI.csproj to build WebUI.UnitTest.csproj and Core.UnitTest.csproj all together? (in my WebUI\bin folder I need these libs: WebUI.UnitTest.dll and Core.UnitTest.dll).
Thanks!

The direct method is that add WebUI.UnitTest project and Core.UnitTest project as dependencies for WebUI project. But the WebUI.UnitTest project already has WebUI.csproj as dependencies, this method does not work in your solution structure. If you just want to have WebUI.UnitTest.dll and Core.UnitTest.dll in your WebUI\bin folder, you can add a task in your WebUI.csproj to copy those files to the folder:
<Target Name="AfterBuild">
<PropertyGroup>
<SolutionDir>$([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))</SolutionDir>
</PropertyGroup>
<Exec Command=""$(MSBuildBinPath)\MSBuild.exe" "$(SolutionDir)\WebUI.UnitTest\WebUI.UnitTest.csproj"" />
<Exec Command=""$(MSBuildBinPath)\MSBuild.exe" "$(SolutionDir)\Core.UnitTest\Core.UnitTest.csproj"" />
<PropertyGroup>
<CopyFileOutput>$(SolutionDir)\WebUI.UnitTest\bin\Debug\WebUI.UnitTest.dll;$(SolutionDir)\Core.UnitTest\bin\Debug\Core.UnitTest.dll</CopyFileOutput>
</PropertyGroup>
<Copy
SourceFiles="$(CopyFileOutput)"
DestinationFolder="$(SolutionDir)\WebUI\bin"
/>
Note that: The stijn`s comment is right, you build the solution, WebUI.UnitTest.csproj and Core.UnitTest.csproj should get built already.
I have also added build steps of WebUI.UnitTest.csproj and Core.UnitTest.csproj in the WebUI.csproj so that you just only need to build the WebUI.csproj.

Related

How to add a project or target to msbuild solution that builds other projects in the same solution?

Wondering if there is an easy way to do what I want with Visual Studio solution.
I have a solution that has 10+ VC++ projects. These projects don't have any dependencies on each other. I want to create msbuild target on the solution that goes and builds all the sub projects.
Something like:
msbuild mysolution.sln /t:RebuildAll /p:Configuration=Debug
How do I add "RebuildAll" target to my solution that iterates all projects in the solution and invokes "Rebuild" target on them?
Thanks
According to your description I make some test, you can refer to the following steps:
Create a file named test.proj
Use this code in the file, remember to change your own solution path in the code:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectFile Include="Your solution path/**/*.vcxproj">
<Properties>Configuration=Release</Properties>
</ProjectFile>
</ItemGroup>
<Target Name="BuildAll">
<MSBuild Projects="#(ProjectFile)" BuildInParallel="true" />
</Target>
</Project>
Then use this msbuild command line to build your projects msbuild test.proj -t:BuildAll -v:normal -m:30.

How to build project in multiple configurations to automate the build process?

I have a solution, which contains a native project. For the main project to properly work, the following steps should be taken:
The native project has to be built in Release/x86 configuration
The native project has to be built in Release/x64 configuration
All .NET projects have to be built
Both binaries from steps 1 and 2 have to be placed in the main project's output folder.
Is there a way to configure project, so that all of those steps happen upon simply choosing "Build | Rebuild all"? I know of the batch build option, but I'd still have to execute step 4 manually.
I think you have to use msbuild script to build your project rather than VS IDE. Scripts are more flexible and can realize your requirements.
1) create a new file called build.proj and then add these on that file:
<Project>
<ItemGroup>
<!--include all c# csproj files to build these projects all at once-->
<NetProjectFile Include="**\*.csproj" />
<!--include the c++ proj files-->
<NativeProjectFile Include="**\*.vcxproj" />
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="#(NetProjectFile)" Targets="Restore;Build" Properties="Configuration=Debug;Platform=AnyCPU"/>
<!--OutDir is the path of the execute file ,pdb.... if you also want the intermediate files to be in the same folder, you should also use IntDir -->
<MSBuild Projects="#(NativeProjectFile)" Targets="Build" Properties="Configuration=Release;Platform=x86;OutDir=xxx\xxx\"/>
<MSBuild Projects="#(NativeProjectFile)" Targets="Build" Properties="Configuration=Release;Platform=x64;OutDir=xxx\xxx\"/>
</Target>
</Project>
3) Just run msbuild build.proj -t:Build to get what you want.

Adding umbraco folders to build with MsBuild

If I use msbuild to build my project, all the folders not included in my solution are not deployed. Is there a way of deploying the umbraco and umbraco_client folders using msbuild?
I have tried using Targets like:
https://gist.github.com/aaronpowell/6695293
How can we include the files created by ajaxmin in the msdeploy package created by MSBuild
https://blog.samstephens.co.nz/2010/10/18/msbuild-including-extra-files-multiple-builds/
But hey are not being copied to the output folder. Am I missing anything?
You can use a msbuild target(run after the build ends) in which it calls the msbuild copy task to copy necessary files or folders to output folder. Use AfterTargets="build" to let the target run after the build.
A target script which works in my machine looks like this:
<Target Name="Copyumbraco" AfterTargets="build">
<ItemGroup>
<UmbracoFiles Include="$(ProjectDir)**\umbraco\**\*" />
<Umbraco_ClientFiles Include="$(ProjectDir)**\umbraco_client\**\*" />
</ItemGroup>
<Copy SourceFiles="#(UmbracoFiles)" DestinationFolder="$(OutputPath)\%(RecursiveDir)"/>
<Copy SourceFiles="#(Umbraco_ClientFiles)" DestinationFolder="$(OutputPath)\%(RecursiveDir)"/>
</Target>
Using $(ProjectDir) property to define the path, so Msbuild can find those two folders if they are in project folder as you mentioned in comment.
The \%(RecursiveDir) set the msbuild copy task to copy the files to destination path with original folder structure. If what you want to just copy all files to Output folder, you don't need to set it, then the script should be:
<Target Name="Copyumbraco" AfterTargets="build">
<ItemGroup>
<UmbracoFiles Include="$(ProjectDir)**\umbraco\**\*" />
<Umbraco_ClientFiles Include="$(ProjectDir)**\umbraco_client\**\*" />
</ItemGroup>
<Copy SourceFiles="#(UmbracoFiles)" DestinationFolder="$(OutputPath)"/>
<Copy SourceFiles="#(Umbraco_ClientFiles)" DestinationFolder="$(OutputPath)"/>
</Target>
Add the target script into the your project's project file(xx.csproj), make sure you place the script in the format below, then it can work when you use msbuild to build the project.
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<Target Name="Copyumbraco" AfterTargets="build">
...
</Target>
</Project>
In addition:
For normal projects like console app, class library, the $(OutputPath) represents the output path. But for web site project, we can use $(WebProjectOutputDir) , hint from Mario!

Can I build multiple configurations of a project within one solution configuration?

I would like to build the same project twice in the same solution configuration, varying some #define flags to toggle features. Both binaries will be deployed with different names.
The solutions that I know could work:
Add a solution configuration - But I will then need to build the solution twice, which I would prefer to avoid. Both project configurations will always be built.
Copy the project - But then I have the overhead of maintaining a new project when I only want to maintain a different configuration.
Batch build - I avoid using batch build as I use both devenv for local development and msbuild for continuous integration.
Any other ideas or suggestions?
Just figured out a way to do what you asked for. Create one msbuild file (I named mine multiple.proj) and add the script below.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Choose>
<When Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<ItemGroup>
<ProjectToBuild Include="$(MSBuildProjectName).csproj">
<Properties>Configuration=Release</Properties>
</ProjectToBuild>
</ItemGroup>
</When>
</Choose>
<Target Name="BeforeBuild">
<Message Text="Building configuration $(Configuration)..." />
</Target>
<Target Name="AfterBuild">
<MSBuild Projects="#(ProjectToBuild)"/>
</Target>
</Project>
</type>
</this>
Import the script on your projects (csproj or vbproj):
<Import Project="..\multiple.proj" />
This script tells msbuild to build again your project with another configuration as an AfterBuild event. I used Debug/Release to make the example, but you can easily change the script to support other configurations, or make the decision to build again based on other variables.
Be careful because you're running two builds at once, so build errors can be harder to understand.
Hope this helps.

Copy built assemblies (including PDB, .config and XML comment files) to folder post build

Is there a generic way I can get a post-build event to copy the built assembly, and any .config and any .xml comments files to a folder (usually solution relative) without having to write a post-build event on each project in a solution?
The goal is to have a folder that contains the last successful build of an entire solution.
It would be nice to use the same build solution over multiple solutions too, possibly enabling/ disabling certain projects (so don't copy unit tests etc).
Thanks,
Kieron
You can set common OutputPath to build all projects in Sln in one temp dir and copy required files to the latest build folder. In copy action you can set a filter to copy all dlls without "test" in its name.
msbuild.exe 1.sln /p:Configuration=Release;Platform=AnyCPU;OutputPath=..\latest-temp
There exists more complicated and more flexible solution. You can setup a hook for build process using CustomAfterMicrosoftCommonTargets. See this post for example.
Sample targets file can be like that:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
PublishToLatest
</BuildDependsOn>
</PropertyGroup>
<Target Name="PreparePublishingToLatest">
<PropertyGroup>
<TargetAssembly>$(TargetPath)</TargetAssembly>
<TargetAssemblyPdb>$(TargetDir)$(TargetName).pdb</TargetAssemblyPdb>
<TargetAssemblyXml>$(TargetDir)$(TargetName).xml</TargetAssemblyXml>
<TargetAssemblyConfig>$(TargetDir)$(TargetName).config</TargetAssemblyConfig>
<TargetAssemblyManifest>$(TargetDir)$(TargetName).manifest</TargetAssemblyManifest>
<IsTestAssembly>$(TargetName.ToUpper().Contains("TEST"))</IsTestAssembly>
</PropertyGroup>
<ItemGroup>
<PublishToLatestFiles Include="$(TargetAssembly)" Condition="Exists('$(TargetAssembly)')" />
<PublishToLatestFiles Include="$(TargetAssemblyPdb)" Condition="Exists('$(TargetAssemblyPdb)')" />
<PublishToLatestFiles Include="$(TargetAssemblyXml)" Condition="Exists('$(TargetAssemblyXml)')" />
<PublishToLatestFiles Include="$(TargetAssemblyConfig)" Condition="Exists('$(TargetAssemblyConfig)')" />
<PublishToLatestFiles Include="$(TargetAssemblyManifest)" Condition="Exists('$(TargetAssemblyManifest)')" />
</ItemGroup>
</Target>
<Target Name="PublishToLatest"
Condition="Exists('$(LatestDir)') AND '$(IsTestAssembly)' == 'False' AND '#(PublishToLatestFiles)' != ''"
DependsOnTargets="PreparePublishingToLatest">
<Copy SourceFiles="#(PublishToLatestFiles)" DestinationFolder="$(LatestDir)" SkipUnchangedFiles="true" />
</Target>
</Project>
In that targets file you can specify any actions you want.
You can place it here "C:\Program Files\MSBuild\v4.0\Custom.After.Microsoft.Common.targets" or here "C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter\PublishToLatest.targets".
And third variant is to add to every project you want to publish import of custom targets. See How to: Use the Same Target in Multiple Project Files

Resources