Example repository of a multi-targeting project build Cake build scripts to build and code-sign both assemblies *and* NuGet packages
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.github
deployment/cake
src
tools
.editorconfig
.gitattributes
.gitignore
AUTHORS
CONTRIBUTING.md
CONTRIBUTORS
GitVersionConfig.yaml
LICENSE
README.md
build.cake
build.ps1
cake.config
scripts - Update NuGet.bat

README.md

MultiTargetingProject

This is an example repository on how to target .NET 4.6, .NET 4.7 and UAP 10.0 using a single project.

This project has been written as an example for the blog post about multi-targeting platforms with a single project.

Along the way, this example has been expanded with the following new Cake build scripts:

  • Build multi-targeting class libraries (components)
  • Build WPF apps
  • Build UWP apps

The scripts are set up in a way that allows a combination of these items as well (e.g. a WPF with an API library) can all be set up. For more information, see the RepositoryTemplate repository.

How to build this example

  1. Open powershell with the repository as working directory
  2. .\build.ps1 -target package

How does it work?

The scripts are extremely generic. One only has to customize 1 file:

  • /build.cake

Below is an example script to package a (multi-targeting) component, wpf and uwp app in a single solution:

// Define the required parameters
var DefaultSolutionName = "Ghk.MultiTargeting";
var DefaultCompany = "Geert van Horrik";
var DefaultRepositoryUrl = string.Format("https://github.com/{0}/{1}", DefaultCompany, DefaultSolutionName);
var StartYear = 2018;

// Note: the rest of the variables should be coming from the build server,
// see `/deployment/cake/*-variables.cake` for customization options

//=======================================================

// Components

var ComponentsToBuild = new []
{
    "Ghk.MultiTargeting" 
};

//=======================================================

// WPF apps

var WpfAppsToBuild = new []
{
    "Ghk.MultiTargeting.Example.Wpf"
};

//=======================================================

// UWP apps

var UwpAppsToBuild = new []
{
    "Ghk.MultiTargeting.Example.Uwp"
};

//=======================================================

// Now all variables are defined, include the tasks, that
// script will take care of the rest of the magic

#l "./deployment/cake/tasks.cake"

And if you are not using a build server (seriously, you should be), you could choose to customize /deployment/cake/*-variables.cake as well.

The Cake magic happens in the generic scripts in /deployment/cake/*.cake

How to use the scripts

Below are a few example targets using exactly the same scripts:

Script Description
./build.ps1 -Target BuildWpfApps Build all WPF apps in the solution
./build.ps1 -Target Package Build & package all components & (WPF & UWP) apps in the solution
./build.ps1 -Target PackageComponents Build & package all components in the solution
./build.ps1 -Target PackageUwpApps Build & package all UWP apps in the solution

As you can see, there is a pattern:

  • Build[SpecificTarget]
  • Package[SpecificTarget]

Note that [SpecificTarget] is optional

Project differences compared to the original template

Compared to the original multi-targeting example, the following changes were made.

Project defines

To make sure I could still use the defines we invested in (to maximize code-sharing, we use a lot of #if in code shared between WPF and UWP). This project creates the following defines:

  • .NET 4.6 => NET; NET46
  • .NET 4.7 => NET; NET47
  • UAP 10.0 => UAP; NETFX_CORE
  • .NET Standard 2.0 => NS; NS20; NETSTANDARD; NETSTANDARD2_0

Include solution assembly info

The project structure adds this line to the project to include the SolutionAssemblyInfo and GlobalSuppressions files which are in the root of the solution.

<Compile Include="..\*.cs" />

Allow shared code-behind (e.g. MyView.xaml.cs) with a per platform view (e.g. MyView.xaml)

To allow sharing of code-behind of a view (for example, for custom controls), we need to to a bit of hacking. We create the view inside each platform specific view directory:

  • Platforms\net\Views\MyView.xaml (+ .cs)
  • Platforms\uap10.0\Views\MyView.xaml (+ .cs)

After creating the views, one will need to customize the code-behind to add a partial method:

public partial class MyView
{
     public MyView()
     {
         InitializeComponent();
 
         Construct();
     }
 
     partial void Construct();
}

Next, create a partial code-behind class inside the regular views folder that contains the shared code:

  • Views\MyView.xaml.cs

This view should contain the following code and allows sharing code-behind but have per-platform xaml files:

public partial class MyView
{
     partial void Construct()
     {
         // TODO: Add shared constructor info here
     }
}

As an example, a dependency property is added in the shared code-behind that shows how to deal with the different platforms in shared code using defines.

Credits