I'm looking for a way to call MSBuild with all possible configurations/platforms defined in the solution file.
I've looked here:
Using MSBuild to Build Multiple Configurations
which requires explicit knowledge of the configurations, as you must enumerate them on the command line,
and here:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/066c9dbf-d191-4b8c-8ee1-b9709b56c500/msbuild-for-visual-studio-2010-build-all-configurations-of-a-vcxproj-file?forum=msbuild
which leads to another page that suggests defining another project file to encapsulate the msbuild calls. Unfortunately, it too requires explicit knowledge of the configurations.
So then, is there any way to obtain through the command line, the list of configurations/platforms availalbe to a given project? (It must be the same list that is modified in Visual Studio. ie: adding/removing a configuration in Visual Studio, saving, exiting, and getting the list, would reflect the changes.)
Parsing the solution file as XML is not an option, as it wouldn't be stable if Microsoft decided to change how it is formatted.
You can't parse a solution as XML it's not a markup file without having MSBuild emitting a meta project first. I recommend you play the odds and be pragmatic, read the .sln as a text file and RegEx it on SolutionConfigurationPlatforms pairs, then build the ItemGroup and batch it. If you are truly utterly paranoid about Microsoft completely reengineering the solution file syntax then look inside Microsoft.Build.Construction and/or .Evaluation, the internal SolutionParser, or Roslyn or even Mono since if the syntax changes then those parsers and loaders would be updated accordingly and in case of Microsoft.Build and Roslyn -- simultaneously.
I have lost a few hairs when trying to deal with DeploymentItem recently.
We have a few common directories for native dll's, and many tests depends on these.
For C++ projects, we use propertypages, where these paths are defined. These can even be imported in a C# project aswell, with some manual editing (as they are MSBuild files). Still I can't figure out how to utilize them in tests.
Unfortunately, the DeploymentItemAttribute can't use the properties in the sheet, but it can utilize environment variables. I was hoping to avoid forcing everybody to define global environment variables...
I have seen various suggestions around the net, but haven't really found a simple solution.
Anybody have good approach to this ?
Anders' answer is a good solution, but in my case:
I don't like the idea of keeping binaries within the source tree
Many dlls dont have specific versions, and they are updated on regular
basis.
I somehow ended up with this solution:
First, I included the global VC++ property page into the test project. This must be done manually by adding this directive under the <Project> tag on top of the .csproj:
<Import Project="$(UserProfile)\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props" />
I now got access to the properties/macros that defines the dll paths in my C++ environment.
I then
added a new subfolder in the test-project, say "NativeDlls"
added the needed dlls as links into the NativeDlls folder
the links are absolute, but can be replaced with macros from the
property sheet included above:
<Content Include="$(MyLibLocation)\GDAL18BIN\gdal18.dll">
<Link>NativeDlls\mylib.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
The dlls is then ready to deploy:
[TestMethod]
[DeploymentItem(#"NativeDlls")]
public void TestSomeStuff()
{
}
And, as Anders mentions: The remaining work is to set debug/release and 32/64 conditions.
If these are external dependencies used only by this project (not shared between source trees) then I suggest moving them into the source control. Dependencies should be versioned together with the source. The rationale being that you should be able to check out a revision of the source tree (any revision in the history), and it should build. If you have binary dependencies that are not under source control, you will have problems knowing which version of the dependency you need when you build a specific version of the source.
If you can move the dependencies into the source tree (e.g. $svnroot/trunk/dependencies) then you can use test deployment with only relative paths. It will work under TeamCity as well as on any developer machine.
If you cannot version your dependencies or you must have them outside the repository for some other reason, then you can use an environment variable that the test deployment can use. See This msdn post for an example
EDIT: moved a comment about managing binary dependencies here
For csprojs I just have a dll-reference in the projects to the dll:s in the lib directory under the source tree (i.e. reference to ..\lib\log4net.dll). If you want to reference separate libs for separate builds, e.g. different for x86/64 or Debug/Release, then VS doesn't support it but MsBuild and the csproj file does, so you can add conditional references but you have to edit the csproj by hand to include for example the x86 dependency only if platform is x86 and so on.
I finally realized why my BeforeBuild Target is no longer executing as expected -- it's so silly, it's because the project's configuration names had changed. But what I really want to do is test for the solution's configuration name, not the project's.
I know that the project's configuration name is stored in $(Configuration). Is there one for the solution's configuration name? Or is this simply not possible because (presumably) the solution names are only known to the configuration manager? If so, can anyone recommend a good method for managing configurations? I'd hate to have to add duplicate project configuration names everywhere...
UPDATE: after searching and reading some docs, I haven't been able to find any proof that MSBuild is aware of the solution's configuration name when its individual project files are compiled. I went ahead and build the solution from the command line, passing /v:diag, and dumped the output to a file. I searched through the file to find any signs of it knowing that the solution's configuration name is "Deployment", but the only occurences of that string appear when the BeforeBuild condition is checked.
See my other answer. I was able to create a VS extension to get the solution configuration name as a build macro ($(variable) notation).
The only solution I've come up with so far is to create my own environment variable on the TeamCity server, and have MSBuild check for its presence in the BeforeBuild target.
EDIT: I couldn't use my own environment variable because it wasn't getting passed to the build runner for some reason. But when I used /v:n in the TeamCity MSBuild settings, I noticed that there is $(COMPUTERNAME), which is exactly what I wanted anyway. I ended up trying this and it totally did the trick.
There is property SolutionConfigurationContents witch is created by Msbulid during soluton file processing it contains solution configuration in it. When building from VS it will contains project (not solution) configuration.
I have a C# project which includes one exe and 11 library files. The exe references all the libraries, and lib1 may reference lib2, lib3, lib4, etc.
If I make a change to a class in lib1 and built the solution, I assumed that only lib1 and the exe would need to be changed. However, all dll's and the exe are being built if I want to run the solution.
Is there a way that I can stop the dependencies from being built if they have not been changed?
Is the key this phrase? "However, all dll's and the exe are being built if I want to run the solution"
Visual Studio will always try to build everything when you run a single project, even if that project doesn't depend on everything. This choice can be changed, however. Go to Tools|Options|Projects and Solutions|Build and Run and check the box "Only build startup projects and dependencies on Run". Then when you hit F5, VS will only build your startup project and the DLLs it depends on.
I just "fixed" the same problem with my VS project. Visual Studio did always a rebuild, even if didn't change anything. My Solution: One cs-File had a future timestamp (Year 2015, this was my fault). I opened the file, saved it and my problem was solved!!!
I am not sure if there is a way to avoid dependencies from being built. You can find some info here like setting copylocal to false and putting the dlls in a common directory.
Optimizing Visual Studio solution build - where to put DLL files?
We had a similar problem at work. In post-build events we were manually embedding manifests into the outputs in the bin directory. Visual Studio was copying project references from the obj dir (which weren't modified). The timestamp difference triggered unnecessary rebuilds.
If your post-build events modify project outputs then either modify the outputs in the bin and obj dir OR copy the modified outputs in the bin dir on top of those in the obj dir.
You can uncheck the build option for specified projects in your Solution configuration:
(source: microsoft.com)
You can can create your own solution configurations to build specific project configurations...
(source: microsoft.com)
We actually had this problem on my current project, in our scenario even running unit tests (without any code changes) was causing a recompile. Check your build configuration's "Platform".
If you are using "Any CPU" then for some reason it rebuilds all projects regardless of changes. Try using processor specific builds, i.e. x86 or x64 (use the platform which is specific to the machine architecture of your machine). Worked for us for x86 builds.
(source: episerver.com)
Now, after I say this, some propeller-head is going to come along and contradict me, but there is no way to do what you want to do from Visual Studio. There is a way of doing it outside of VS, but first, I have a question:
Why on earth would you want to do this? Maybe you're trying to save CPU cycles, or save compile time, but if you do what you're suggesting you will suddenly find yourself in a marvelous position to shoot yourself in the foot. If you have a library 1 that depends upon library 2, and only library 2 changes, you may think you're OK to only build the changed library, but one of these days you are going to make a change to library 2 that will break library 1, and without a build of library 2 you will not catch it in the compilation. So in my humble opinion, DON'T DO IT.
The reason this won't work in VS2005 and 2008 is because VS uses MSBuild. MSBuild runs against project files, and it will examine the project's references and build all referenced projects first, if their source has changed, before building the target project. You can test this yourself by running MSBuild from the command line against one project that has not changed but with a referenced project that has changed. Example:
msbuild ClassLibrary4.csproj
where ClassLibrary4 has not changed, but it references ClassLibrary5, which has changed. MSBuild will build lib 5 first, before it builds 4, even though you didn't mention 5.
The only way to get around all these failsafes is to use the compiler directly instead of going through MSBuild. Ugly, ugly, but that's it. You will basically be reduced to re-implementing MSBuild in some form in order to do what you want to do.
It isn't worth it.
Check out the following site for more detailed information on when a project is built as well as the differences between build and rebuild.
I had this problem too, and noticed these warning messages when building on Windows 7 x64, VS2008 SP1:
cl : Command line warning D9038 : /ZI is not supported on this platform; enabling /Zi instead
cl : Command line warning D9007 : '/Gm' requires '/Zi'; option ignored
I changed my project properties to:
C/C++ -> General -> Debug Information Format = /Zi
C/C++ -> Code Generation -> Enable Minimal Build = No
After rebuilding I switched them both back and dependencies work fine again. But prior to that no amount of cleaning, rebuilding, or completely deleting the output directory would fix it.
I don't think there's away for you to do it out of the box in VS. You need this add-in
http://workspacewhiz.com/
It's not free but you can evaluate it before you buy.
Yes, exclude the non-changing bits from the solution. I say this with a caveat, as you can compile in a way where a change in build number for the changed lib can cause the non built pieces to break. This should not be the case, as long as you do not break interface, but it is quite common because most devs do not understand interface in the .NET world. It comes from not having to write IDL. :-)
As for X projcts in a solution, NO, you can't stop them from building, as the system sees a dependency has changed.
BTW, you should look at your project and figure out why your UI project (assume it is UI) references the same library as everything else. A good Dependency Model will show the class(es) that should be broken out as data objects or domain objects (I have made an assumption that the common dependency is some sort of data object or domain object, of course, but that is quite common). If the common dependency is not a domain/data object, then I would rethink my architecture in most cases. In general, you should be able to create a path from UI to data without common dependencies other than non-behavioral objects.
Not sure of an awesome way to handle this, but in the past if I had a project or two that kept getting rebuilt, and assuming I wouldn't be working in them, I would turn the build process off for them.
Right click on the sln, select configuration manager and uncheck the check boxes. Not perfect, but works when Visual Studio isn't behaving.
If you continue to experience this problem, it may be due to a missing or out of date calculated dependency (like a header) that is listed in your project, but does not exist.
This happens to me especially common after migrating to a new version (for example: from 2012 to 2013) because VS may have recalculated dependencies in the conversion, or you are migrating to a new location.
A quick check is to double-click every file in offending project from solution explorer. If you discover a file does not exist, that is your problem.
Failing a simple missing file: You may have a more complicated build date relationship between source and target. You can use a utility to find out what front-end test is triggering the build. To get that information you can enable verbose CPS logging. See: Andrew Arnott - Enable C++ and Javascript project system tracing (http://blogs.msdn.com/b/vsproject/archive/2009/07/21/enable-c-project-system-logging.aspx). I use the DebugView option. Invaluable tool when you need it.
(this is a C# specific question, but a different post was merged as identical)
I have a question regarding the commandline options of msbuild. I am
currently using msbuild to build projects using the existing solution
files. These solution files have references to external dll which have
different paths on each machine. I am currently writing a build script
and passing the specific path to the project file via the /p: switch of
msbuild.
My current build line is:
msbuild test.sln /p:ReferencePath="c:\abc" /p:ReferencePath="c:\rca"
What i have noticed that Reference Path now contains only c:\rca and
not c:\abc. this is causing problems for me since, the external dlls
lie in two different directorys. I am allowed to keep multiple
reference paths via visual studio, but not via the commandline.
Is there any known way by which i can do this
I believe you can use this /p:ReferencePath="c:\abc;c:\rca"
At least that is what that link is hinting at, they are using %3B to encode the ";" within the build file.
Although the correct syntax for providing more the one reference path is listed above, I would suggest solving the root cause which in my opinion is the different locations of your referenced assembly. I would suggest you put all thirdparty dependencies, apart from the framework assemblies in your source code repository for the following reasons:
Relatitve paths are consistent across computers
The source code is always in sink with the correct version of your thirdparty assembly (if you for instance need to build an old version of your software 2 years from now).
Upgrading your thirdparty assembly is as easy as upgrading on one machine and then committing your changes to the repository. (In a previous project we even went as far as checking in the entire java runtime environment and were quite happy with the given setup.)
Try seperating your pathes with a semi-colon (;)
Like this:
c:\abc;c:\rca
You may be better off by synchronizing your libraries across machines. I have found that Visual Studio makes this easy. Simply add a solution folder, and add your libraries there. Then, in each project, reference the libraries from this common place. This way, each developer has them in the same place.
This will remove one of variables you have when trying to script out builds.
The command line options for setting the reference path will work just fine (assuming you escape the semi colon, it seems both %3B and ; will work). However, when the argument was passed in from nant (and I needed multiple paths), creating a 'Visual Studio Project User Options file' seemed to work better.
I just emit (echo) a file to the file system with the following format:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ReferencePath>
C:\abc;c:\rca
</ReferencePath>
</PropertyGroup>
I give the *.user file an appropriate name (given a project file MyProject.csproj, my user file would be MyProject.csproj.user)