I am writing a utility for my company that will batch build a number of solutions in a one-click fashion. There are about 8 solutions in all, and each one has an average of 20 projects. The utility needs to be able to capture the build log and the total number of errors for each solution, just as is done when you build at the command line. I know I this is the command to accomplish that
msbuild mysolution.sln /t:build /verbosity:minimal /maxcpucount:xx
However, I would like to make use of the Microsoft.Build.Evaluation API's if possible. I know the Project object can load a single project, but is there anyway to build an entire solution? I intend to build this utility to make use of the all cpus/cores on the system and build multiple solutions simultaneously. I've looked at the MSDN page for Microsoft.Build.Evaluation, though the documentation is (still) abysmal.
Thanks for any help you can offer!
Jason
You do not need a Visual Studio solution file (sln) to build multiple projects. As you may know, Visual Studio project files are just MSBuild XML files and they can fall other project files. Therefore, build a project file that builds the other projects as required. This can be done in one of two ways.
First, solution files are just MSBuild XML so anything that can generate XML can generate a solution. See the MSBuild XML Schema for more information.
Second, construct a Microsoft.Build.Evaluation.Project programmatically using the constructor that takes an Microsoft.Build.Construction.ProjectRootElement instance then call Project.Build(). The ProjectRootElement has methods for adding common element types such as CreateTaskElement(), CreatePropertyElement() and CreateTargetElement().
See also:
Replace .sln with MSBuild and wrap contained projects into targets
Generating an MSBUILD project file from a visual studio solution file and project files.
Related
Is there a way in Visual Studio to define some files or resources to be used only in specific build configurations? We use many #if DEBUG clauses to add debug-only code, but the same can't be done in a .config xml file, for example. Is there a way to define two versions of that file to be used, depending on whether the build configuration is set to Debug or Release?
I found this that describes what I'm looking to do but for Android using Ant. Is there a similar mechanism for Visual Studio and .NET?
Is there a way in Visual Studio to define some files or resources to be used only in specific build configurations?
According to this doc: MSBuild concepts which mentioned “MSBuild provides a basic XML schema that you can use to control how the build platform builds software.”, I think MSBuild could help you solve this issue.
Is there a way to define two versions of that file to be used, depending on whether the build configuration is set to Debug or Release?
MSBuild has four parts: properties, items, tasks, and targets. For this issue you may need to focus on “items” part.
Solution:
You could add this command line “Condition=”’$(Configuration)’==’Debug’” and “Condition=”’$(Configuration)’==’Release’” to control when(Debug/Release) to use different versions of resources.
Refer to following screenshot, and this link(List of common properties and parameters-- Condition).
I'm trying to create post build events to copy the final .js and .debug.js files for my script# projects into the proper directories. I can't use the regular output folder, since I have more than one project that references another project, and that always results in a build error (Unable to copy referenced script because it is being used by another process).
The problem is that the C# compiler appears to run the post build events BEFORE it writes the actual .js files, so they don't exist when the post build event happens.
Is there any other solution to make this work?
You can set up a DeploymentPath property in your csproj and the generated scripts will be copied there.
All of the logic is in here: https://github.com/nikhilk/scriptsharp/blob/cc/src/Core/Build/Tasks/ScriptCompilerTask.cs ... so another option is to customize the build task to exactly your requirements.
The latest work if you check out the github repo, also has the script# part of the build process done during the build step of an msbuild project, so that should free up the post-build step for you to do what you'd like with the generated scripts. See https://github.com/nikhilk/scriptsharp/blob/cc/src/Core/Build/ScriptSharp.targets. Again, its just msbuild stuff, so you could potentially customize the .targets file to your liking as well if it doesn't fit your needs.
I got around this by adding the "copy" command as a pre build step on the projects that were using the script# project output, then adding a dependency so that the script# project would be built first.
I'd like to have a web project in a solution that is set to "not build" in the solution configuration, however I would still like the project's references (and their dependencies) to be copied into that project's bin folder. There are class library projects in the sln that are actually built, and the web project references those.
Our current "build" just calls devenv, which does exactly this. For obvious reasons, I'd rather use MSBuild.
I am not looking for methods to do manual file copying (either individually or *.dll). There are many ways to do this. I am looking specifically for a way to replicate the behaviour that devenv.exe gives us - automatically copy references (and their dependencies) based on what is in the project section in the solution file (below).
These references come from the solution in this section:
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}")="TheWebProjectName",
"Web\Project\Folder",
"{1CBD1906-0C2E-4C92-A81D-63C2AD816EA1}"
ProjectSection(WebsiteProperties) = preProject
TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
ProjectReferences = "{B125568E-E80C-4080-B8D3-5602B604734C}|Some.Reference.dll;
{117E8B0A-F0D6-47D0-BB51-71099969566D}|Some.OtherRef.dll;"
...
EndProjectSection
EndProject
MSBuild uses target files to determine it's build steps. Take a look at the relevant target files and determine how MSBuild copies those files, create your own target file and modify your build configuration to use the new target.
Relevant target files:
Location: C:\Windows\Microsoft.NET\Framework\v$(version)
Microsoft.CSharp.targets
Microsoft.Common.targets
Relevant documentation:
MSBuild
Specifying Targets
You can do build operations such as this using MSBuild Tasks: http://msdn.microsoft.com/en-us/library/ms171466(v=vs.80).aspx
In your specific case you'll probably be interested in the built in Copy Task: http://msdn.microsoft.com/en-us/library/3e54c37h(v=vs.80).aspx
Try using powershell instead of msbuild!! Ria services also relies strongly on powershell commandlets.
Cheers..
Call devenv.exe using an Exec task - we do it all the time for BizTalk solutions because old versions of MSBuild do not support the BizTalk project files...
When using Visual Stdio 2008, you can make a C++ project build with an internal tool rather than having the IDE invoke MSVC directly. This improves the consistency of builds across platforms if a cross-platform build system is used.
However, I cannot figure out how to do the same as a C# project. It would be possible to simply register it as a native project with C# sources, however, you lose some of the advantages gained through having a C# project. More importantly, it will mean that allowing a project to build both directly and with an external tool (which is sadly necessary) will require two separate projects, rather than merely creating an alternate build configuration to invoke the external tool.
Does anyone know if it's possible to prevent Visual Studio from invoking csc by itself and instead call an external tool?
EDIT: Apparently there has some misunderstanding. The goal here is not to compile anything outside of Visual Studio. Instead, it's to allow Visual Studio to serve as the IDE but not the build system. There is already a (Scons-based) build system capable of compiling the C# and C++ sources, and Visual Studio has been configured to invoke Scons for compilation of C++ projects. I'm trying to configure it so that when you hit the 'Build' button, it will invoke Scons for the C# projects as well as the C++ ones.
Edit: Your question is still answered using MSBuild(if you are simply looking to compile outside the IDE). The IDE(Visual Studios) is simply a "fancy" way of constructing the build files that are built by MSBuild. Visual Studios isn't building the files, it simply is invoking MSBuild which ships with the .NET Framework 2.0 and up which compiles your code based on the project file that you create. If Scons can read and process an MSBuild file then I'm sure you can invoke it to build your project. But considering the fact that C# is a Microsoft language, I think you will be hard-pressed to find a value-add in not using MSBuild since I'd assume both the language and build tool are very tuned to work together. - End Edit
You can use MSBuild to compile your C# project. If you open your .csproj file in a text editor you will see that it is a MSBuild file. If you want to write some C# outside of the IDE you can construct a build file using the .csproj file as a starting point and invoke MSBuild to compile your apps. The IDE is just a way of abstracting the editing of the MSBuild file away for you.
If you are really industrious you can create a set of custom tasks to do things in your custom build process like move files around and versioning. MSBuild Community Tasks are a great example of using custom code to do task for you during MSBuild.
Given all the other answers, what MSBuild does when either VS or MSBuild perform a build can be found in the Targets files that ship with .Net. These can be be found in the FrameWork directory on your system. In my case:
C:\Windows\Microsoft.NET\Framework64\v3.5
Contains Microsoft.Common.targets among others. This file contains the following snippit:
<!--
============================================================
Build
The main build entry point.
============================================================
-->
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(BuildDependsOn)"
Outputs="$(TargetPath)"/>
This means that redifining this Target you can make MSBuild an VS do anything you want. The top of the mentioned file contains an important messagge:
Microsoft.Common.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
This file defines the steps in the standard build process for .NET projects. It
contains all the steps that are common among the different .NET languages, such as
Visual Basic, C#, and Visual J#.
My suggestion would be to read all you can about MSBuild and it's build file syntax and try redifining the Build target in your project(s). My impression is that after reading up on MSBuild you'll probably find an easier way to meet your requierements. You can find an example of redifining a Target like this in one of the answers of this so question .
Edit:
How to redefine a target?
Redefining is essentially defining the same target 'after' it has been defined. So for instance in your .*proj file(s) define a Build Task after the <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> line that imports all targets needed to in this case build a C# project. An example could be
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="BeforeBuild"
Outputs="$(TargetPath)">
<Exec Command="nmake" />
</Target>
I found a question in the same direction here, where it is suggested to edit the registry. I am pretty sure there is no other way to change the compiler used by Visual Studio because there is no trace of csc.exe in any solution, config, csproj file or whatsoever, nor in the Visual Studio 9.0 folder / subfolders within the Program Files dir.
Registry locations can be found in:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\74ACAA9F1F0087E4882A06A5E18D7D32
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\9055DA7481CC1024CB23A6109FD8FC9B
but those keys may differ dependng on your installation. Conclusion: changing the compiler used by VS seems next to impossible.
Addition: The following MSDN article deals with the same question for an custom C++ compiler, and Ed Dore's answer seems to confirm my theory that there's no way to choose an custom compiler for use within VS.
Under 'Tools' > 'External Tools' you should be able to define an outside tool to do activities for you. The Command should be the path to the executible for your external tool.
Hope this helps some.
You don't have to maintain different project files to build using an external tool. MSBuild is designed to build using the same project files that Visual Studio uses.
Here's an article that describes it.
Customize Your Builds in Visual Studio Using the Standalone MSBuild Tool
It's for VS2005, but should apply to VS2008 as well.
Looking through the answers, it seems clear to me that integrating scons into Visual Studio in a way that is compatible with the debugger and so on is not going to happen...
An option you might to consider, and I understand you don't want to change build systems, but bear with me, is to use a meta-build system, ie 'cmake'. http://www.cmake.org/
Cmake doeesn't actually build the project. What it does is to create build files for you, that you can use to build the project, and on Windows, the build files it creates for you are: Visual Studio project files. You can simply load those directly into your IDE, and compile, and use normally!
CMake is I feel very easy to use, and provides a high level of transparence and maintainability.
The exact same CMakeLists.txt files on linux will causes linux makefiles to be generated.
On mingw, they can generate mingw makefiles.
There are numerous generators available within cmake. The list is here:
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_Generators
http://springrts.com is a huge opensource rts game that used to use scons as its cross-platform build system and now uses cmake.
I understand that you don't really want to have to change build systems, so it is a medium to long term solution.
Cmake is in any case one more option, to add to those of using a custom build tool, or using msbuild, or running the scons build from the commandline by hand.
Edit your project file and update the CscToolPath keys to point to the directory containing your tool and add CscToolExe keys that holds the name of the directory:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|.NET 3.5' ">
.
.
.
<CscToolPath>path\to\custom\tool\directory</CscToolPath>
<CscToolExe>exe name</CscToolExe>
.
.
.
</PropertyGroup>
I have not tested this, and the CscToolExe key may cause problems, in which case I would simply rename the external tool executable to "csc.exe".
You can build your solution from the command line like this:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>msbuild.exe "C:\path\Your Solution.sln"
In C++ projects there is the possibility to set a custom build step for files. Is there a similar functionality in C# projects? I couldn't really find anything.
One idea would be to create a second project (makefile or c++) and move the files there.
MsBuild should work for you although it might take some time to figure out how it works. It appears that you can setup a step that runs prior to building each .cs file by separating each .cs file into its own build group.
In MSBuild script for compiling each .cs file into an EXE, Dino Chiesa comments:
By using the %(CSFile.identity)
scalar, we run this task once for each
file. The converse would be
#(CSFile.identity). That would run
the compile once, for all files,
compiling them all together into a
single assembly.
Also, these links might help:
Custom build step for C# files
Master Complex Builds with MSBuild
No custom build step for individual files with C# projects. You could probably hack something together with MSBuild...
Look at the BeforeBuild and AfterBuild targets in your csproj file.
I think you are on the right track with your comment about multiple projects. Combine this with the fact that you can include multiple projects within a single Solution and you may have your answer. I use this functionality to build several components at a time and it works quite well.