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

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.

Related

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.

Compile a list of projects with msbuild.exe

I have a VS solution which contains n-C++ projects. Is there any way to let msbuild.exe compile a specific subset of projects via command line?
msbuild.exe foo.sln /thisFlagWouldBeCool:project1;project2
I tried the /t flag for targets, but that doesn't seem to do it, since targets are not projects?
1.See How to: Build specific targets in solutions by using MSBuild.exe. As it states, you can use command like:
msbuild SlnFolders.sln -target:NotInSlnfolder:Rebuild;NewFolder\InSolutionFolder:Clean
More specific, if you have Project A, B, C in same solution(Test.sln), to build only A and B, you can use command like:
msbuild Test.sln /t:A;B /p:Configuration="xx" /p:Platform="xx"
Note: To build in this way, we should make sure the A.xxproj and B.xxproj are defined in xx.sln file. At least for VS, if we create a new Project C, the xx.sln won't be updated until we click the save all button.
2.And here's another direction which is suitable for some specific scenario:
We can right-click the Solution node in VS, choose add project=>empty project to add an empty project into the solution, let's name it MyBuildTool project.Unload it to edit its MyBuildTool.vcxproj file, add this kind of script into the bottom of it(within the Project tab):
<!--If you're trying to build subset of the solution, any build the projects with different settings-->
<Target Name="CustomBuild" AfterTargets="build">
<MSBuild Projects="..\**\B2.vcxproj" Properties="Configuration=Debug;Platform=x64;OutDir=xxx"/>
<MSBuild Projects="..\**\A2.vcxproj" Properties="Configuration=Release"/>
...
</Target>
<!--If you're building several projects in same settings-->
<Target Name="CustomBuild" AfterTargets="build">
<ItemGroup>
<ProjectsToBuild Include="..\**\A1.vcxproj"/>
<ProjectsToBuild Include="..\**\B1.vcxproj"/>
</ItemGroup>
<MSBuild Projects="#(ProjectsToBuild)" Properties="Configuration=Debug" BuildInParallel="true"/>
</Target>
</Project>
Then the MyBuildTool.vcxproj is now our build script, if in some specific situation we need to build several project, we can just run command msbuild.exe MyBuildTool.vcxproj. It depends on the usage of MSBuild Task.

Is it possible to run a post build event when the whole compilation finishes in Visual Studio 2013?

I have a solution with multiple projects and we use FxCop. We want to run it once the compilation requested finishes (it may be one project, a folder with several folders or the whole solution).
Is there a way of doing this? We currently do it per project but this has some drawbacks.
Yes, there is a way to do it by putting a file next to your solution file with a specific naming pattern: after.{Your solution name here}.sln.targets
<!--?xml version="1.0" encoding="utf-8"?-->
<project toolsversion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<target name="AtTheStart" beforetargets="Build">
<message text="GenerateCode target running" importance="high">
</message>
</target>
<target name="AtTheEnd" aftertargets="Build">
<message text="GenerateCode target running" importance="high">
</message>
</target>
</project>
But if you want to run FxCop effectively and have visualstudio installed, you can actually activate it during the build by including /p:RunCodeAnalysis=true or /p:RunCodeAnalysis=always on the call to MsBuild. This will run the configured ruleset file during the build. /p:CodeAnalysisRuleSet=PathTo.ruleset will let you specify a specific ruleset file.
The commandline will always overwrite the project's own configuration. And it will run in the most optimal way.
I would put the FxCop project set (with all the dll's in all your projects) and call it after all the projects are built in VS.

How do I use an MSBuild file from Visual Studio 2012?

I have a simple MSBuild file that I'm learning with.
Here it is:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Clean" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{D5A16164-962E-4A6D-9382-240F31AB6C50}</ProjectGuid>
</PropertyGroup>
<Target Name="Clean">
<ItemGroup>
<BinFiles Include="bin\*.*" />
<fff Include="f\*.*" />
</ItemGroup>
<Delete Files="#(BinFiles)" />
<Delete Files="#(fff)" />
</Target>
</Project>
Now I want to include this in a Visual Studio solution and be able to run the "clean" target from Visual Studio 2012. I tried naming it testproject.msbuildproj like the internet seems to suggest "works", but it doesn't work. When I run the clean command I just get "unexpected error".
If I rename the project to testproject.csproj, it does some unintuitive things like creating compilation directories, but it does actually run my clean command properly. However, this is undesireable because it creates obj and bin/x86/debug type directories. It also looks goofy in Visual Studio because it still gives the References drop down.
How can I use just a plain vanilla MSBuild project from Visual Studio without random errors or false assumptions?
Note I only am having a problem with this from Visual Studio. Using msbuild from the command line it works perfectly
Visual Studio creates bin / obj folders when it opens csproj file. When you click Build / Rebuild / Clean it just uses appropriate targets from the project file.
You cannot stop VS from creating these folders, but you can ask it to create them in say temp folder by setting appropriate properties - refer this MSDN article for details.
So the steps are to rename your project to csproj, and add the following lines into project:
<PropertyGroup>
<OutputPath>$(Temp)\bin</OutputPath>
<IntermediateOutputPath>$(Temp)\obj</IntermediateOutputPath>
</PropertyGroup>
I usually use a bit different approach to work with MSBUILD files from VS:
I use regular csproj file with removed Import ... CSharp.targets part as pure container for my Build projects.
I add actual build files with targets and logic, and all properties, necessary artifacts like XSLT etc using "Include into project", so I can manage hierarchy and change any file from within VS.Net.
I redefine Build / Rebuild targets in csproj file for whatever I need, for example Build may contain minimum output, and while rebuild diagnostic one.
Like this:
<Target Name="Build">
<Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe Builds\build.proj /t:Build /v:m" />
</Target>
<Target Name="Rebuild">
<Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe Builds\build.proj /t:Build /v:d" />
</Target>

How can I exclude a project from a build in MSBuild?

I need to build a solution, but exclude one project. How should I do it?
I searched a lot about this issue, but nothing could help.
An ItemGroup section rises the following exception:
Invalid element . Unknown task or datatype.
PropertyGroup also rises the exception.
Below is my code sample:
<project name="TI 8.1.6 build script">
<ItemGroup>
<Solution Include="${ROOT}\Core\TI Core.sln" Exclude="${ROOT}\Utilities\DTS Indexing Service\Tdi.Origami.IndexUpdaterServiceSetup\Tdi.Origami.IndexUpdaterServiceSetup.wixproj"/>
</ItemGroup>
...
</project>
How can I do this?
You can exclude projects at the solution level for a specific build configuration by using the Configuration Manager Dialog in Visual Studio:
Then you can simply invoke msbuild on the solution file specifying the build configuration to use:
msbuild /property:Configuration=Release MySolution.sln
The solution suggested by Enrico is the most versatile solution that would work always. An alternative solution might be to use a <MSBuild> task directly. This will work for you if you have all your project files under a particular directory, or be able to easily enumerate all projects you want to build (i.e. number of projects in your solution is not very big).
For example, this MSBuild file will build every project under your current directory except for a specific project:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MyProjectReferences Include="**\*.*proj" />
<MyProjectReferences Exclude="Utilities\DTS Indexing Service\Tdi.Origami.IndexUpdaterServiceSetup\Tdi.Origami.IndexUpdaterServiceSetup.wixproj" />
</ItemGroup>
<Target Name="BuildAllExceptWixProject">
<MSBuild Projects="#(MyProjectReferences)" Targets="Build" />
</Target>
</Project>
Then you can build that using command line msbuild <myproject> /t:BuildAllExceptWixProject
In your solution file (.sln), remove the Build.0 entries. For example:
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyProject", "MyProject.vcxproj", "{2281D9E7-5261-433D-BB04-176A61500CA3}"
EndProject
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2281D9E7-5261-433D-BB04-176A61500CA3}.Debug|x86.Build.0 = Debug|x64
If you delete this "Build.0" entry, it will load in the solution fine, but will not be built, either through the GUI or via external MSBuild.
Since VS 2019 and MSBuild 16.7, the right way is to use Solution filters. Ref
create a master.proj file:
in another ItemGroup add DefaultExclude properties for programs - put it in front of the solution
-- BA was Canadian
Configuration=Release
Release
drop the master.proj into the directory with the programs and msbuild the master.proj
compiles everything except... that HelloWorld

Resources