Avoiding too many configurations for a Visual Studio project - c++

I'm currently porting a large Linux project to Visual Studio. The project depends on a number of third-party libraries (Python, MPI, etc.) as well as a couple of in-house ones. But it can also be built without these libraries, or with only a few of them. So I don't want to create a different configuration for each possible combination, e.g. "Parallel with Python", "Parallel without Python", etc. There are just too many combinations. Is this a situation where I could use MSBuild?
Edit: One possibility I considered is to create a bunch of .vsprops files, but this is essentially the same as creating a bunch of different configurations.
Edit: Maybe CMake is more what I'm looking for? I'd love to hear from any CMake users out there...

One approach could be to conditionally reference your libraries using the Condition attribute of every assemblies Reference element (Python, MPI, etc).
This could separate your libraries from the configuration and platform properties, and allow you to build them by default, or conditionally using MSBuild properties.
So in your csproj:
<Reference Include="YourPythonLibrary"
Condition="$(BuildType) == '' Or $(BuildType) == 'TypeA'" />
<Reference Include="YourMpiLibrary"
Condition="$(BuildType) == 'TypeA' Or $(BuildType) == 'TypeB'" />
That includes Python by default and MPI only if the correct build type is set. Wouldn't matter what the configuration or platform is set as, and you could adjust the boolean logic to suit each library for each of your build types.
MSBuild /p:BuildType=TypeA
MSBuild /p:BuildType=TypeB
It would be nice to use some form of bitwise operation on the condition, but i'm not sure that is possible in MSBuild?
Note: Doesn't have to a Reference element, if it's just included as Content this approach will still work.

There's no good solution to this that I'm aware of. The IDE seems to require a configuration for each set of command line arguments to the tools. So if N different sets of arguments are required -- as it sounds like the case is here -- N different configurations will be required. That's just how the IDE works, it appears.
Unfortunate, but one rarely wins in a fight against Visual Studio, so I personally have always given in and created as many configurations as needed. It's a pain, and it's fiddly, and yes the IDE should ideally provide some better mechanism for managing the combinations -- but it's doable, just about, and it doesn't actually take as long to set up as it feels like at the time.
(As I understand them, .vsprops can take some of the pain away by allowing easy sharing of configuration settings between configurations. So those miniscule text boxes in VS are only used to set up the settings that differ between configurations. This may make them still worth investigating. This isn't something I've used myself yet, though; only discovered it recently.)

If you right-click the solution in Visual Studio and select Configuration Manager you can create build targets for each configuration.
You can select between those targets with a combo box in the toolbar if you have the default settings.
Those targets can also be selected when using MSBuild just as you can choose between Release and Debug.

Related

Is there a quick way to switch the solution platform in Visual Studio 2010?

I want to compile my C++ projects in 32-bit and 64-bit mode. Until now, I created Solution Configurations: in addition to the pre-configured "Debug" and "Release" configurations, I then had "Debug x64" and "Release x64" configurations which I set to compile a project for the x64 architecture.
However, my latest project can be changed in a number of dimensions: Not only "Release" vs "Debug" but also "XP", "Server03" and "newer" as well as "EXE" vs "DLL" (it can actually be compiled in both formats). Because this already gives 2*2*3=12 configurations, adding another "x64" configuration for each of those would give the whole thing absurd proportions.
That's why I want to use the Solution Platform setting from now on. Unfortunately, the only way to change that seems to be to click the configuration dropdown list, open the Configuration Manager from there, then change the Solution Platform and click OK. This takes a rather long time (more than doubling the number of clicks). Is there a quicker way? Or alternatively, a better way to manage all the dimensions in which the project can change (which involve project settings and precompiler definitions)?
I'd say that since your build is so complex, a build script would be a better choice to handle all that complexity. You could write the script using MSBuild, NAnt, Rake or whatever you prefer. When you want to build some configuration, or all, you just call the script with the appropiate parameters.
My recommendation: Use the IronRuby-Albacore combo, it's really straightforward and you code your build script in Ruby, which is much more readable than XML. Get started here
One option is to create a Visual Studio macro and binding it to a either key or a menu item. Once the macro is invoked you can have it iterate through all of the solution platforms and build each one.
There is a dropdown box for the target platform which can be added to the toolbar ("Project Platform"). This eliminates the need to encode the platform in Project Configurations.

Allowing developer-specific settings in VS2008 Native C++ projects

Is it possible to combine the following properties, and if so, how?
Store in our version control system some Visual Studio 2008 native C++ (VCPROJ) project files for the developers in our team that use this IDE.
Allow some of those developers to tweak their projects (e.g. using debug version of third-party libraries instead of the usual ones).
Make sure these modifications are done in files that are not versioned.
In other words, I would like to allow developers to tweak some settings in their projects without risking that these changes are committed.
An 'optional VSPROP' file approach seems doomed to fail, as VS2008 refuses to load projects that refer to non-existent VSPROP files...
Any other suggestion? Is this possible with VS2010?
You may not be able to do this but using a solution that generates the vcproj like CMake for example would let you do this. Scripts all your project with CMake and literally conditionally include a config file(if present for example) that developers can change on their setup.
Branches could solve this problem: you create a branch, play with different versions of third-party, merge changes to trunk if results are good.
Well, as a preliminary solution you could put the project file into something like .hgignore or .gitignore after its initial commit.
This way changes to it can't be done accidentally.
At least that's how I handle .hgignore itself.
We use a versionned "common_configuration" folder, and a script which copies project files from this "common_configuration" folder towards the "project" folder.
We have another script to copy the configuration backwards, so the developpers need to make a conscious action to commit their local changes to the global version control system.
It answers partly your needs :
The upside : we have a way to keep a common configuration for everyone, and no accidental committing of local configuration
The downside : blindly copying the files actually crushes local changes. We live with it. We could write some more clever merger tool (using diff, or xml specific manipulations), but don't want to spend to much time on supporting the deployment tools.

Building both DLL and static libs from the same project

I have a number of native C++ libraries (Win32, without MFC) compiling under Visual Studio 2005, and used in a number of solutions.
I'd like to be able to choose to compile and link them as either static libraries or DLLs, depending on the needs of the particular solution in which I'm using them.
What's the best way to do this? I've considered these approaches:
1. Multiple project files
Example: "foo_static.vcproj" vs "foo_dll.vcproj"
Pro: easy to generate for new libraries, not too much manual vcproj munging.
Con: settings, file lists, etc. in two places get out of sync too easily.
2. Single project file, multiple configurations
Example: "Debug | Win32" vs "Debug DLL | Win32", etc.
Pro: file lists are easier to keep in sync; compilation options are somewhat easier to keep in sync
Con: I build for both Win32 and Smart Device targets, so I already have multiple configurations; I don't want to make my combinatorial explosion worse ("Static library for FooPhone | WinMobile 6", "Dynamic library for FooPhone | WinMobile 6", "Static library for BarPda | WinMobile 6", etc.
Worse Con: VS 2005 has a bad habit of assuming that if you have a configuration defined for platform "Foo", then you really need it for all other platforms in your solution, and haphazardly inserts all permutations of configuration/platform configurations all over the affected vcproj files, whether valid or not. (Bug filed with MS; closed as WONTFIX.)
3. Single project file, selecting static or dynamic via vsprops files
Example: store the appropriate vcproj fragments in property sheet files, then apply the "FooApp Static Library" property sheet to config/platform combinations when you want static libs, and apply the "FooApp DLL" property sheet when you want DLLs.
Pros: This is what I really want to do!
Cons: It doesn't seem possible. It seems that the .vcproj attribute that switches between static and dynamic libraries (the ConfigurationType attribute of the Configuration element) isn't overrideable by the .vsprops file. Microsoft's published schema for these files lists only <Tool> and <UserMacro> elements.
EDIT: In case someone suggests it, I've also tried a more "clever" version of #3, in which I define a .vsprops containing a UserMacro called "ModuleConfigurationType" with a value of either "2" (DLL) or "4" (static library), and changed the configuration in the .vcproj to have ConfigurationType="$(ModuleConfigurationType)". Visual Studio silently and without warning removes the attribute and replaces it with ConfigurationType="1". So helpful!
Am I missing a better solution?
I may have missed something, but why can't you define the DLL project with no files, and just have it link the lib created by the other project?
And, with respect to settings, you can factor them out in vsprop files...
There is an easy way to create both static and dll lib versions in one project.
Create your dll project. Then do the following to it:
Simply create an nmake makefile or .bat file that runs the lib tool.
Basically, this is just this:
lib /NOLOGO /OUT:<your_lib_pathname> #<<
<list_all_of_your_obj_paths_here>
<<
Then, in your project, add a Post Build Event where the command just runs the .bat file (or nmake or perl). Then, you will always get both a dll and a static lib.
I'll refrain from denigrating visual studio for not allowing the tool for this to exist in a project just before Linker (in the tool flow).
I think the typical way this is done is choice 2 above. It is what I use and what I have seen done by a number of libraries and companies.
If you find it does not work for you then by all means use something else.
Good luck.
I prefer 2 configurations way.
Setup all common settings via 'All configurations' item in a project properties windows. After it separated settings. And it's done. Let's go coding.
Also there is very good feature named 'Batch build', which builds specified configurations by turn.
Multiple projects are the best way to go - this is the configuration i have most widely seen in umpteen no of projects that i have come across.
That said, it might be also possible to implement the third option by modifying your vcproj files on the fly from external tools(like a custom vbscript), that you could invoke from a make file. You can use shell variables to control the behavior of the tool.
Note that you should still use use visual studio to make the build, the makefile should only launch your external tool if required to make the mods and then follow that by the actual build command
I use Visual Studio 6.0 (Still) due to issues that are preventing us from Migrating to VS2005 or newer. Rebuilding causes severe issues (everything breaks)... so many of us are considering lobbying a migration to GnuC++ moving forward in a structured way to eventually get us off of licensed Visual Studio products and onto Eclipse and Linux.
In Unix/Linux it is easy to build for all configurations.. so I can't believe what a time and productivity sink it is to try and accomplish the same task in Visual Studio. For VS6.0 I have so far found that only having two separate projects seems to be workable. I haven't yet tried the multiple configuration technique, but will see if it works in the older VS6.0.
Why not go for version 1 and generate the second set of project files from the first using a script or something. That way you know that the differences are JUST the pieces required to build a dll or static lib.

Complex builds in Visual Studio

I have a few things that I cannot find a good way to perform in Visual Studio:
Pre-build step invokes a code generator that generates some source files which are later compiled. This can be solved to a limited extent by adding blank files to the project (which are later replaced with real generated files), but it does not work if I don't know names and/or the number of auto-generated source files. I can easily solve it in GNU make using $(wildcard generated/*.c). How can I do something similar with Visual Studio?
Can I prevent pre-build/post-build event running if the files do not need to be modified ("make" behaviour)? The current workaround is to write a wrapper script that will check timestamps for me, which works, but is a bit clunky.
What is a good way to locate external libraries and headers installed outside of VS? In *nix case, they would normally be installed in the system paths, or located with autoconf. I suppose I can specify paths with user-defined macros in project settings, but where is a good place to put these macros so they can be easily found and adjusted?
Just to be clear, I am aware that better Windows build systems exist (CMake, SCons), but they usually generate VS project files themselves, and I need to integrate this project into existing VS build system, so it is desirable that I have just plain VS project files, not generated ones.
If you need make behavior and are used to it, you can create visual studio makefile projects and include them in your project.
If you want less clunky, you can write visual studio macros and custom build events and tie them to specific build callbacks / hooks.
You can try something like workspacewhiz which will let you setup environment variables for your project, in a file format that can be checked in. Then users can alter them locally.
I've gone through this exact problem and I did get it working using Custom Build Rules.
But it was always a pain and worked poorly. I abandoned visual studio and went with a Makefile system using cygwin. Much better now.
cl.exe is the name of the VS compiler.
Update: I recently switched to using cmake, which comes with its own problems, and cmake can generate a visual studio solution. This seems to work well.
Specifically for #3, I use property pages to designate 3rd party library location settings (include paths, link paths, etc.). You can use User Macros from a parent or higher level property sheet to designate the starting point for the libraries themselves (if they are in a common root location), and then define individual sheets for each library using the base path macro. It's not automatic, but it is easy to maintain, and every developer can have a different root directory if necessary (it is in our environment).
One downside of this approach is that the include paths constructed this way are not included in the search paths for Visual Studio (unless you duplicate the definitions in the Projects and Directories settings for VS). I spoke to some MS people at PDC08 about getting this fixed for VS2010, and improving the interface in general, but no solid promises from them.
(1). I don't know a simple answer to this, but there are workarounds:
1a. If content of generated files does not clash (i.e. there is no common static identifiers etc.), you can add to the project a single file, such as AllGeneratedFiles.c, and modify your generator to append a #include "generated/file.c" to this file when it produces generated/file.c.
1b. Or you can create a separate makefile-based project for generated files and build them using nmake.
(2). Use a custom build rule instead of post-build event. You can add a custom build rule by right-clicking on the project name in the Solution Explorer and selecting Custom Build Rules.
(3). There is no standard way of doing this; it has to be defined on a per-project basis. One approach is to use environment variables to locate external dependencies. You can then use those environment variables in project properties. Add a readme.txt describing required tools and libraries and corresponding environment variables which the user has to set, and it should be easy enough for anyone to set up.
Depending on exactly what you are trying to do, you can sometimes have some luck with using a custom build step and setting your dependencies properly. It may be helpful to put all the generated code into its own project and then have your main project depend on it.

Using Makefile instead of Solution/Project files under Visual Studio (2005)

Does anyone have experience using makefiles for Visual Studio C++ builds (under VS 2005) as opposed to using the project/solution setup. For us, the way that the project/solutions work is not intuitive and leads to configuruation explosion when you are trying to tweak builds with specific compile time flags.
Under Unix, it's pretty easy to set up a makefile that has its default options overridden by user settings (or other configuration setting). But doing these types of things seems difficult in Visual Studio.
By way of example, we have a project that needs to get build for 3 different platforms. Each platform might have several configurations (for example debug, release, and several others). One of my goals on a newly formed project is to have a solution that can have all platform build living together, which makes building and testing code changes easier since you aren't having to open 3 different solutions just to test your code. But visual studio will require 3 * (number of base configurations) configurations. i.e. PC Debug, X360 Debug, PS3 Debug, etc.
It seems like a makefile solution is much better here. Wrapped with some basic batchfiles or scripts, it would be easy to keep the configuration explotion to a minimum and only maintain a small set of files for all of the different builds that we have to do.
However, I have no experience with makefiles under visual studio and would like to know if others have experiences or issues that they can share.
Thanks.
(post edited to mention that these are C++ builds)
I've found some benefits to makefiles with large projects, mainly related to unifying the location of the project settings. It's somewhat easier to manage the list of source files, include paths, preprocessor defines and so on, if they're all in a makefile or other build config file. With multiple configurations, adding an include path means you need to make sure you update every config manually through Visual Studio's fiddly project properties, which can get pretty tedious as a project grows in size.
Projects which use a lot of custom build tools can be easier to manage too, such as if you need to compile pixel / vertex shaders, or code in other languages without native VS support.
You'll still need to have various different project configurations however, since you'll need to differentiate the invocation of the build tool for each config (e.g. passing in different command line options to make).
Immediate downsides that spring to mind:
Slower builds: VS isn't particularly quick at invoking external tools, or even working out whether it needs to build a project in the first place.
Awkward inter-project dependencies: It's fiddly to set up so that a dependee causes the base project to build, and fiddlier to make sure that they get built in the right order. I've had some success getting SCons to do this, but it's always a challenge to get working well.
Loss of some useful IDE features: Edit & Continue being the main one!
In short, you'll spend less time managing your project configurations, but more time coaxing Visual Studio to work properly with it.
Visual studio is being built on top of the MSBuild configurations files. You can consider *proj and *sln files as makefiles. They allow you to fully customize build process.
While it's technically possible, it's not a very friendly solution within Visual Studio. It will be fighting you the entire time.
I recommend you take a look at NAnt. It's a very robust build system where you can do basically anything you need to.
Our NAnt script does this on every build:
Migrate the database to the latest version
Generate C# entities off of the database
Compile every project in our "master" solution
Run all unit tests
Run all integration tests
Additionally, our build server leverages this and adds 1 more task, which is generating Sandcastle documentation.
If you don't like XML, you might also take a look at Rake (ruby), Bake/BooBuildSystem (Boo), or Psake (PowerShell)
You can use nant to build the projects individually thus replacing the solution and have 1 coding solution and no build solutions.
1 thing to keep in mind, is that the solution and csproj files from vs 2005 and up are msbuild scripts. So if you get acquainted with msbuild you might be able to wield the existing files, to make vs easier, and to make your deployment easier.
We have a similar set up as the one you are describing. We support at least 3 different platforms, so the we found that using CMake to mange the different Visual Studio solutions. Set up can be a bit painful, but it pretty much boils down to reading the docs and a couple of tutorials. You should be able to do virtually everything you can do by going to the properties of the projects and the solution.
Not sure if you can have all three platforms builds living together in the same solution, but you can use CruiseControl to take care of your builds, and running your testing scripts as often as needed.