Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps

Cajoling Multi-Platform Solutions in Visual Studio

5.00/5 (1 vote)
24 Nov 2015CPOL2 min read 6.6K  
Here is a trick to create a Visual Studio solution that simultaneously builds multiple platforms for targeted projects.

Introduction

To support a WiX install project, I needed to build the product's components for both 32bit (x86) and 64bit (x64) platforms. WiX requires the different platforms of a component to each have their own unique product GUIDs. The challenge was to have a single solution that would build the components for the multiple platforms ahead of the multi-platform installers, each with their own unique platform specific project GUIDs, without requiring redundant project files that might drift away from the main development of the source projects.

Basic Approach

Small, single-platform project stubs can be used to include full projects by using the <Import /> element.

For example, MyProject-x86.csproj (shown below in its entirety) would reference and include the primary MyProject.csproj that houses the full project details.

XML
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <AltProjectGUID>{6BA556BF-37D1-4BF0-81DC-AD68FB387CFE}</AltProjectGUID>
  </PropertyGroup>
  <Import Project="MyProject.csproj" />
</Project>

Make sure to use a unique, tool generated GUID, for each platform stub project. AltProjectGUID is a made up tag; any non-conflicting tag name could be used. In my case, the stub projects reside in the same directory as the projects that they include. If this is not the case, the absolute or relative path to the imported project must be used.

Each target project will have the following element, usually near the top of the project file:

XML
<ProjectGuid>{9A01BD2F-DFFF-4E1B-9DF5-72EE4461ED2D}</ProjectGuid>

Change this line into the following; fixing up the GUIDs appropriately:

XML
<AltProjectGUID Condition=" '$(AltProjectGUID)'=='' 
And '$(Platform)'=='x86' 
">{B2CC2918-1188-4DD9-A16B-35E16FAAD372}</AltProjectGUID>
<AltProjectGUID Condition=" '$(AltProjectGUID)'=='' 
And '$(Platform)'=='x64' 
">{2CBAD510-C714-4C58-A6E1-6AD5B963DADF}</AltProjectGUID>
<AltProjectGUID Condition=" '$(AltProjectGUID)'=='' ">
{9A01BD2F-DFFF-4E1B-9DF5-72EE4461ED2D}</AltProjectGUID>
<ProjectGuid>$(AltProjectGUID)</ProjectGuid>

Image 1

The last <AltProjectGUID> element is the default when the project has not been wrapped by a stub project, or the platform of the stub project does not match the expected platform(s). Make sure that this default GUID matches your regular, generic solution (.sln) files. When it doesn't match the solution file, Visual Studio will gratuitously overwrite it with a new <ProjectGuid> for you.

Lastly, add your stub projects to your multi-platform solution and force your solution's Configuration Manager to match each stub project with the desired build platform. In my case, I remove all spurious platform options to enforce consistent build constraints.

Image 2

As with the above project files, you will have to edit the solution (.sln) file outside of Visual Studio to ensure that the correct GUIDs are being used for each stub project. Here is a snippet of what you are looking for in the solution file:

Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = 
"cwprint-x86", "..\cwprint-x86.csproj", 
	"{B2CC2918-1188-4DD9-A16B-35E16FAAD372}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = 
"cwprint-x64", "..\cwprint-x64.csproj", 
	"{2CBAD510-C714-4C58-A6E1-6AD5B963DADF}"
EndProject

{B2CC2918-1188-4DD9-A16B-35E16FAAD372}.Release|Any CPU.ActiveCfg = Release|x86
{B2CC2918-1188-4DD9-A16B-35E16FAAD372}.Release|Any CPU.Build.0 = Release|x86
{2CBAD510-C714-4C58-A6E1-6AD5B963DADF}.Release|Any CPU.ActiveCfg = Release|x64
{2CBAD510-C714-4C58-A6E1-6AD5B963DADF}.Release|Any CPU.Build.0 = Release|x64

Conditions and Anomalies

Image 3

For this approach to work, each base project must have separate output paths for each target platform. Even though the multi-platform solution will build correctly, it will hide all of the source files and will show the dependent references as unresolved. Build order will have to be hand crafted by setting the 'Project Dependencies' as needed in the solution, if any.

Image 4

Conclusion

You will want to manage your projects from their mainstream solutions, but this multi-platform trick will let you build your projects targeting multiple platforms in one go.

History

  • Initial submission

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)