Our company develops and sells a cross-platform C++ library. We distribute binary only versions for Windows, Mac OS X, Linux, iOS, Android, etc. The only source code the customers get is the header files with the class interfaces. Our IDE is Visual Studio; we're very glad it now supports cross-compilation out-of-the-box (clang! remote control of a Mac with XCode! Ability to call older versions of the compiler! Makes our lives much easier). We try to build all the versions at the same time on the same build machine (which calls out to a Mac to do the iOS and Mac OS X ports). Most customers are on Windows and just get the libraries for recent Visual C++, but some customers get the works.
The code itself is the same between platforms.
However, not all of our customers are on the latest version of Visual Studio -- some of them are using versions as far back as 2005. While we are trying to encourage them to move to a newer version, we still have to support the old ones if they find a bug.
This leads to a proliferation of product configurations: (Debug/Release) * (Static library/Shared Library) * (Platform) * (x86/x64/ARM) * (Compiler version)
most of which are very similar to each other, but with some differences.
I was studying MSBuild and playing around with the
.vcxproj file but it still seems extremely complicated (and Visual Studio chokes on any
.vcxproj with anything more than a bare minimum of tweaks).
The way we used to deal with this was to manually tweak the project each time we were doing a new build. That is obviously unsustainable.
I was assigned to bring the project up-to-date, and I initially created a bunch of new configurations, corresponding to that absurd cross product I mentioned above. I think that makes for 40 configurations. Ugh. But aside from the management headache, I didn't always make the necessary project settings changes when copying from (say) x86 to x64. So some of the new configurations didn't build when I did a batch build.
In order to stop this happening again, I created a bunch of new user macros in the project file (probably should have been in the
.props file referenced in the
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release-2013|Win32'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> </ImportGroup>
I guess) and made sure that all the project configurations were the same and that the changes between each of them were just made in the user macros. But that's getting unwieldy too, and pulling down a menu of 40 things to select the right thing to build, plus then having to go into the right folder and pick out the relevant files, also seems error prone.
So my question is: How can I make this more automatic and not require so much thought? Do people creating a cross-platform library really work with 40+ configurations in their project? How are some ways people handle this in real life -- or at least set things up so they don't make so many mistakes?