Stand-alone build system for Visual Studio projects - c#

We use Make to compile our product, which includes, C, C++, Java and a bunch of other bits and pieces. As much as possible we have all tools required to compile the whole thing checked into source control, to eliminate local dependencies and to ensure consistency across dev machines.
Recently we've added some components written in C# using Visual Studio and would like to take a similar approach with Visual Studio solutions. Shelling out to devenv isn't a good option. Calling csc.exe directly (as I've done before using Nant) would require keeping track of file dependencies in the build script, which I'd rather just let the Visual Studio solution do.
MSBuild seems like a good bet, though its default location in %windir%\Microsoft.NET\Framework\[version]\ makes me worried about variability between machines, both with the [version] in the path and the fact that you'll see both "Framework" and "Framework64" directories. I wouldn't mind having a requirement that all developers have whatever .NET framework version installed, but I do worry that your v3.5 might not be the same as mine.
Does anyone have a solution to this that they like? Tried anything that you really didn't like?

MSBuild is the lowest-friction option for sure. Different fx versions aren't that big a deal at build-time- if you're using something important from a fx version higher than what's installed, it won't build. The last place I was at, we built a huge multi-environment build system with NAnt as the base, and it hooked out to MSBuild with NAnt's MSBuild tasks. MSBuild is fine on its own if you're just doing MS stuff, but we had a bunch of things that MSBuild didn't natively support, hence the NAnt wrapper.

I agree with everyone else. To make it easy, just make vsvars.bat (the batch file that is the Visual Studio Command prompt) part of your build script, and then MSBuild will just work.

We use Nant to drive msbuild. If you're worried about different versions of the framework, particularly service packs, use FxCop to check that you're not letting unexpected dependencies creep in. Details are in this answer.

MSBuild is the right tool for this job. Just match your framework version to the version of the framework bundled with the Visual Studio you're using.
32-bit versus 64-bit shouldn't matter, I don't think -- I'm pretty sure both the 32-bit and 64-bit editions of Csc.exe can cross-compile to the other platform. The MSBuild project file (*.*proj XML file) should contain everything MSBuild needs to build your application.

Related

Is there a simple way to make Visual Studio 2015 use a specific ToolsVersion?

When building a project or solution using a specific version of msbuild I can select an earlier .net toolchain by using the /toolsversion or /tv switch:
"C:\Program Files (x86)\MSBuild\14.0\bin\msbuild" /tv:12.0 amazing.sln
This Just Works for all versions of msbuild, and the version of csc.exe etc. is correctly chosen based on the above:
> "C:\Program Files (x86)\MSBuild\14.0\bin\msbuild" /tv:4.0 amazing.sln
...
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe ...
...
> "C:\Program Files (x86)\MSBuild\14.0\bin\msbuild" /tv:12.0 amazing.sln
...
CoreCompile:
C:\Program Files (x86)\MSBuild\12.0\bin\Csc.exe ...
...
If I don't specify /tv, then depending on which version of msbuild I'm using and a number of environment variables, I may get any of:
The ToolsVersion specified in the top-level element in the project file
The ToolsVersion corresponding to the version of msbuild.exe I'm using
A value from msbuild.exe.config
A value from the registry
(See the different versions of the Overriding ToolsVersion Settings page on MSDN).
So, in order to have builds that have consistent results on the build server and on my local machine, I use /tv when running msbuild.exe (in fact, this is enforced in a psake script, which also ensures it uses the corresponding version of msbuild.exe).
However I cannot use the /tv switch when building with Visual Studio. Instead, Visual Studio 2013 and up will use the .net toolchain that shipped with that version of Visual Studio unless:
The environment variable MSBUILDLEGACYDEFAULTTOOLSVERSION is set and...
...all the project files have the ToolsVersion attribute set to the version I want to use.
This is so baroque that I cannot believe anyone is actually doing it. My questions are thus:
Is anyone doing the MSBUILDLEGACYDEFAULTTOOLSVERSION thing?
If not, is there another way to make Visual Studio use a specific ToolsVersion short of using the version of Visual Studio that shipped with that ToolsVersion? Something that could be stored in version control (so in a project or some other settings file) would be ideal.
And lastly:
Should I even care? Given that each successive version of the C# compiler should be able to handle previous versions' input, and I can set the target .net framework and C# language level in the project file, is this enough to ensure repeatable builds?
(My prejudice is that I should care, since:
I want builds in the IDE and on the build server to be the same (of course)
I want to be able to use VS2015 (and future versions) because it's a better IDE than previous versions, but I don't want to be obliged to use the new toolchain until I decide to.
Perhaps I want too much...)
For a concrete example of the problem, please see my msbuild-vs-vs2015-toolsversion repository on github.
Some background: I'm asking this because we recently had a CI build error when one of my colleagues submitted C# 6.0 code that compiled fine with Roslyn on their copy of Visual Studio 2015, but failed in CI because that uses the previous release of the .net toolchain (they'd used an automatic property with no setter, which is fine in Roslyn but not in earlier versions). We will be updating the CI build to Roslyn, but I wanted to see if we could prevent this sort of thing happening in the future.
I solved this by writing a Visual Studio extension that temporarily sets the environment variable MSBUILDDEFAULTTOOLSVERSION for the duration of a build; the value to be used is read from a file .toolsversion in the same directory as the .sln file. The psake script reads the same .toolsversion file and passes the value to the /tv switch.
The code for the extension can be found here: https://github.com/guyboltonking/set-toolsversion-extension. Sadly, I'm not working with C++, or indeed with Visual Studio, at the moment, so I can't provide any support for it (but I can tell you I used it with no issues at all for several months).
Kudos to #efaruk for reminding me about the existence of MSBUILDDEFAULTTOOLSVERSION.
Edit: Thanks to #mbadawi23, it's now possible to use the extension with both VS2015 and VS2017.
To force a specific C# version in Visual Studio 2015, you can go into the project properties -> Build -> Advanced -> Language Version.
If you set this to 5, the compiler will complain about C# 6 features with: Feature '...' is not available in C# 5. Please use language version 6 or greater.
Alternativly ReSharper also has some tools for this.
Note: You can always create an msbuild file to build your project from using it or changing your project it self and you can decide your tool version conditionally (https://msdn.microsoft.com/en-us/library/7z253716.aspx) (.csproj is also a structured msbuild script with different extension and it will be also compatible with VS).
Regards...
Edit:
https://msdn.microsoft.com/en-us/library/bb383985.aspx
by setting the $(ProjectToolsVersion) property on a project within a solution. This lets you build a project in a solution with a Toolset version that differs from that of the other projects.
So, I think you have got your answer ;)
What you see within Visual Studio (the tools etc) and the code behind them are not what is included in the compiled data they are merely a visual/readable representation, when compiling them as an earlier version of VS you are making the executable of that version.
Please keep in mind that if compiling as a previous .NET version you will potentially lose functionality such as async functionality.

Trouble getting JSIL to compile

Every modern version of JSIL I ever try to get working with XNA ends up with this error.
Everywhere I've ever looked in the past for information about why it doesn't run ends up with an answer about XNA 4.0 not being installed properly or something.
This error was reproduced on 3 different computers.
I CAN get A version of JSIL working, I can download one of the releases from the git repository (JSIL-0.7.6) and it'll work with XNA providing you don't give it anything the build is unable to support.
But those releases are a couple of years old now. It would've been nice to get a modern build working.
I try to offer up some speculation but I'm sort of out of my depth here.
JSIL-0.7.6 - won't build in AnyCPU, requires the solution platform be set to x86.
Latest JSIL git release - A lot of the projects are now set to AnyCPU and setting them to x86 will create a various mixture of errors or warnings.
So I think somewhere along the line I might be having problems with a build at the point certain projects in JSIL went from x86 to 64 bit support.
I have visual studio express 2010 and visual studio community installed.
I've tried things like using XNA refresh. Using emscription, FNA, etc...
In an ideal world I'd rather get JSIL working with monogame but I get so many errors on any version of JSIL it doesn't seem to be worth bothering. Porting monogame projects to xna isn't too much trouble.
Trunk JSIL is designed to be built using VS2015 Community. Most of the dependencies have moved over to NuGet, which means that you need to restore packages before building for the first time - VS2015 will do this for you automatically; at the command line you may need to do a manual NuGet package restore.
If you want to use the XNA support, you'll want to compile as Debug|Any CPU or Release|Any CPU. This should still work because the compiler - JSILc - has 32-bit and 64-bit targets now. If you use the 32-bit target (Compiler.Executor.32bit) that will ensure the compiler is running in 32-bit mode and the XNA bits will work. The 32-bit target builds as JSILc.exe and the 64-bit target builds as JSILc.AnyCPU.exe.
As far as the content pipeline bits go, I'd need to see more log text to speculate as to why it's not working... but in general, the content pipeline does not work reliably in command-line msbuild. Your best bet is to first build the game project a single time using Visual Studio so all the content is built correctly, at which point command-line msbuild will handle it better.
For XNA in VS2015, use the VS2013 package from codeplex:
https://mxa.codeplex.com/releases
You may need to edit the manifest inside the package before VS2015 will let you install it, but it works perfectly.
Building with VS2013 will probably work fine, but I haven't done that recently.
If you're still having trouble, try ruling out the basics by doing a NoXNA build (Debug|NoXNA instead of Debug|AnyCPU) and make sure everything works there. An easy way to verify a working build is to run the 'SimpleTests' test suite using the VS2015 test runner - it takes a relatively short amount of time and will identify basic issues with the compiler or build pipeline.
Keep in mind that when you invoke tools like msbuild or csc from the command-line, it's somewhat unpredictable which version you'll get. VS2015 x64 native tools command prompt and VS2015 x86 native tools command prompt are two start menu shortcuts that will get you a command prompt with the right tools loaded if you have VS2015. Given that you have VS2010 installed, it's possible that old versions of msbuild and/or csc are being used when you try to build.

When is this ClickOnce installer really necessary?

I'm not a professional programmer yet, I've just started college and I study some things by myself outside of it. I'm doing pretty basic stuff in C#, like console applications and simple stuff for the web in asp.net.
I've noticed that whenever I publish a C# project using Visual Studio 2010, I am obligated to use this "click once" setup wizard for my apps. But I don't really think any of them need a setup program, they are just a executable and maybe a bunch of .dlls which are able to run by just executing them right away.
I fail to see what's the poing of this click once installer? It probably checks if the correct version of the .Net framework is installed and, if not, installs it. But is that all it does? I think this click once is too ugly and if checking the .net version is all it does I'd rather code my own installer using another language which looks better and provides more info about my program.
You don't need to use ClickOnce, that's just an option for how to distribute your app. You could simply build using the Release configuration and then distribute that Release folder (typically bin\Release, configured in the project's settings), or use a post-build command to, e.g., build a zip of the assemblies and config(s) you need:
del /Q $(SolutionDir)MyApp-win.zip
cd $(OutDir)
"C:\Program Files\7-Zip\7z.exe" a $(SolutionDir)MyApp-win.zip MyApp.exe MyApp.exe.config OtherAssembly.dll
I recommend using ClickOnce for smaller apps since it simplifies the distribution of app updates alot.
You don't need to use the ClickOnce installer that is provided by Visual Studio though. You can create your own installer (with a UI that suits you more) that in turn uses ClickOnce under the hood for the heavy lifting.
See https://msdn.microsoft.com/en-us/library/dd997001.aspx.

Visual studio 2008 & nant , msbuild how we use this for automate? Is nant work for vs2008?

I am working on a windows as well as web projects. We currently use Visual Studio to build our solution using visual studio 2008.
I would like to move to a more powerful build system such as Nant or MsBuild for atomate.
What are the ways & how i do this?
Currntly we use Visual source safe & mercurial(hg) as source control
How does this all integrate with Source Control?
Help me all the ways..
Thanks!
Last time I checked, NAnt didn't support VS2008 project files properly.
I personally like using NAnt as the general build controller, but delegating to MSBuild for the core "build the code into assemblies" part. This has worked well for me in Protocol Buffers, for example.
I don't know about using either VSS or Hg from NAnt, but I'd be very surprised if there weren't adapters available. Where do you need to integrate source control with the build, is it for version numbers, continuous integration, or something else? You may find that whatever continuous integration server you're using can handle the source control aspect itself, and that your build file doesn't need to know about it.
This really depends on what you want to automate and how. Visual Studio Solution files can be called directly from MSBuild, so to just build the solution without Visual Studio, nothing has to be done.
NAnt can call msbuild to build Solution files for you, so you can wrap you solution build in a NAnt script and do other useful things around it. This is how I usually do things. That way your build script and your solution files stay in sync.
NAnt has had VSS tasks since the dawn of time, so checking out the code is trivial. If they don't have a Mercurial task, there is always the exec task which will allow you to run any commandline program (I assume there is one for Mercurial).
Normally I have a build server with a working copy of the application/solution. Then, each night, the server calls a NAnt script that updates the working copy to the latest revision, and builds the solution using the msbuild task. Then you can do all kinds of nifty things like creating zips or tars, or even installers.

Why would I want to continue to use Nant when MSBuild is available?

I have seen the prior questions and answers. In that one question, the original poster asked a followup question:
what are the compelling reasons to use msbuild? are there cons?
I didn't see the answer to that. I'd like to know the converse, too. What are the compelling features of Nant?
I think, for nant, cross-platform is big. For msbuild, it is the currency and integration with Visual Studio. Does this sound right? Anything else?
EDIT/Added: anyone have a feature list comparison? Someone said "nant has more features out of the box." Which ones?
Would it make sense to combine these projects, combine efforts so as to benefit mutually? Has anyone asked MS if they'd be willing to contribute msbuild to the community, like WiX? What are the chances?
EDIT2: I just found this prior discussion, not sure why I couldn't find it before.
Nant has more features out of the box, but MSBuild has a much better fundamental structure (item metadata rocks) which makes it much easier to build reusable MSBuild scripts.
MSBuild takes a while to understand, but once you do it's very nice.
Learning materials:
Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build
by Sayed Ibrahim Hashimi (Jan, 2009)
Deploying .NET Applications: Learning MSBuild and ClickOnce
by Sayed Y. Hashimi (Sep, 2008)
I simply find NAnt easier to use. I dare say this is partly due to my background in Ant, but I found building a NAnt file for Protocol Buffers to be a much simpler job than building an MSBuild file for MiscUtil. (Even now there are things in the MiscUtil build which I'd like to include but can't - it seems ridiculously hard to dump the output of a task to a text file, IIRC.) The concepts are simpler, and there seem to be fewer gotchas in terms of when file collections are evaluated etc.
I currently like using a setup which I previously thought was really silly - I use NAnt for my "main" build file, but invoke MSBuild to do the actual "compile my .NET project" step. The idea of having two build systems for the same project is abhorrent, but I basically don't treat the MSBuild part as a full build system - it's just an easy way of compiling, and I never need to manually examine the project file. (I only interact with it via Visual Studio.) I've been able to evolve my Protocol Buffers build very easily this way, and I doubt I'd have had the same experience if I'd used MSBuild.
Soon I'm going to try building it all with Mono (when 2.4 is released - until then there are showstoppers in gmcs) at which point we'll see how portable the strategy is...
You would continue using nant because you are already using it. If you were using msbuild, and wanted to know why would you switch to nant, then the answer is theres no real reason to switch. At least you know msbuild isnt going anywere, nant hasnt been updated since december 2007.
Considering that NAnt is based off Ant for Java, that there might be reason enough to stick with it. Other build tools are based off Ant - Phing is one, for PHP. When I started using that tool, I picked it up in no time since I was already familiar with NAnt.
We use a hybrid approach because we started on NANT before MS-Build was available. However MS-Build cna do parallel buids on projects that are not dependent which can in the right circumstances reduce your build times significantly. Leaving NANT to interact with SVN, deployment and just having MS-build do compilation cut our build times by about 45% YMMV depending on how you structure your sln.
Some points that came to mind:
you must use msbuild if you are working with Windows Workflow Foundation (compiling *.xoml files, probably this is also true for WPF)
if you are using wix for building setup .msi file you can use VisualStudio or msbuild to compile wix scripts (in case of error VS can jump to problematic line in wix script)
msbuild allows you to have build environment as much similar to development/Visual Studio environment (for example when building with msbuild postbuild events are executed, you don't have to manually maintain a list of *.cs files to csc task, ...)
Where I work we are currently using NAnt scripts with msbuild task from NAntContrib.

Categories