Skip to content

Commit

Permalink
[build] Allow building with msbuild.
Browse files Browse the repository at this point in the history
DO NOT MERGE!!!

TODO: Need the Java.Interop bump for the generator fix!
dotnet/java-interop#46

Fix the solution and project files so that `msbuild` may be used to
build the solution instead of requiring `xbuild`.

There were a few issues that `msbuild` didn't like:

1. MSBuild doesn't like the "extra" configuration mappings in
    Xamarin.Android.sln.

2. MSBuild doesn't like the presence of `.dll` within `@(Reference)`
    entries. `<Reference Include="System.dll" />` is Bad™, so
    Don't Do That™.™.

3. Turning `$(AndroidSupportedAbis)` into an item group is...broken.

(1) and (2) are straightforward fixes. (3) requires some explanation.

`src/monodroid` needs to *only* build `libmonodroid.so` for the
non-"host" ABIs within `$(AndroidSupportedAbis)`. It needs this
restriction because non-selected ABIs may not be configured in
`$(AndroidNdkDirectory)`, and thus can't be built.

This *could* be done by following
`build-tools/mono-runtimes/mono-runtimes.projitems` and doing lots of
`Condition`s on `$(AndroidSupportedAbisForConditionalChecks)`:

	<_MonoRuntime Include="armeabi-v7a" Condition="$(AndroidSupportedAbisForConditionalChecks.Contains(':armeabi-v7a:'))" />
	...

However, that's kinda ugly when *all* we need is the ABI name, so
`monodroid.projitems` was "cute":

	<PropertyGroup>
		<_SupportedAbis>$(AndroidSupportedAbis.Replace(':', ';'))</_SupportedAbis>
	</PropertyGroup>
	<ItemGroup>
		<_MonoRuntime Include="$(_SupportedAbis)" Exclude="@(HostOSName)" />
	</ItemGroup>
	<!-- @(_MonoRuntime) is `armeabi-v7a` by default -->

This works...on xbuild, but *not* `msbuild`. Doh!

(`msbuild` is "smart" and doesn't treat the `;` as an item separator,
so if `$(AndroidSupportedAbis)` is `host-Darwin;armeabi-v7a` then
MSBuild treats the `;` as part of the filename -- NOT a filename
separator -- and `@(_MonoRuntime)` contains *one* item with
an `%(Identity)` of `host-Darwin;armeabi-v7a`. On the one hand, this
is kinda awesome and answers the question "how can you have a filename
that contains `;`?", but on the other hand it broke my project!)

The only fix I could think of was to use `.Split(':')`:

	<_MonoRuntime Include="$(AndroidSupportedAbis.Split(':'))" Exclude="@(HostOSName)" />

That provides desired behavior with `msbuild`, but `xbuild` doesn't
support it and appears to either *ignore* it, or treat it literally.

Other attempts to fix things so that `msbuild` behaves as desired
would cause `xbuild` to break; they appear to be
*mutually incompatible* here.

To resolve this, add a new `<ValueToItems/>` task to
`Xamarin.Android.Tools.BootstrapTasks.dll`. This new task takes a
value, splits on a given separator, and turns it into an
`<ItemGroup/>`, allowing particular items to be excluded:

	<ValueToItems
	    Value="$(AndroidSupportedAbis)"
	    Split=":"
	    Exclude="@(HostOSName)">
	  <Output TaskParameter="Items" ItemName="_MonoRuntime" />
	</ValueToItems>

This allows for `@(_MonoRuntime)` to have the desired value on both
`msbuild` and `xbuild`, allowing `src/monodroid` to build as desired.
  • Loading branch information
jonpryor committed Jun 11, 2016
1 parent 0175852 commit 2524fdb
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 16 deletions.
2 changes: 0 additions & 2 deletions Xamarin.Android.sln
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AnyCPU = Debug|AnyCPU
Release|AnyCPU = Release|AnyCPU
XAIntegrationDebug|Any CPU = XAIntegrationDebug|Any CPU
XAIntegrationRelease|Any CPU = XAIntegrationRelease|Any CPU
XAIntegrationDebug|AnyCPU = XAIntegrationDebug|AnyCPU
XAIntegrationRelease|AnyCPU = XAIntegrationRelease|AnyCPU
EndGlobalSection
Expand Down
6 changes: 3 additions & 3 deletions src/Mono.Android.Export/Mono.Android.Export.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
<HintPath>$(OutputPath)..\v1.0\mscorlib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.dll">
<Reference Include="System">
<HintPath>$(OutputPath)..\v1.0\System.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Core.dll">
<Reference Include="System.Core">
<HintPath>$(OutputPath)..\v1.0\System.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.dll">
<Reference Include="System.Xml">
<HintPath>$(OutputPath)..\v1.0\System.Xml.dll</HintPath>
<Private>False</Private>
</Reference>
Expand Down
10 changes: 5 additions & 5 deletions src/Mono.Android/Mono.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,23 @@
<HintPath>$(OutputPath)..\v1.0\mscorlib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.dll">
<Reference Include="System">
<HintPath>$(OutputPath)..\v1.0\System.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Core.dll">
<Reference Include="System.Core">
<HintPath>$(OutputPath)..\v1.0\System.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Net.Http.dll">
<Reference Include="System.Net.Http">
<HintPath>$(OutputPath)..\v1.0\System.Net.Http.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Runtime.Serialization.dll">
<Reference Include="System.Runtime.Serialization">
<HintPath>$(OutputPath)..\v1.0\System.Runtime.Serialization.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.dll">
<Reference Include="System.Xml">
<HintPath>$(OutputPath)..\v1.0\System.Xml.dll</HintPath>
<Private>False</Private>
</Reference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\GenerateProfile.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\GetNugetPackageBasePath.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\Which.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\ValueToItems.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Xamarin.Android.Tools.BootstrapTasks.targets">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tools.BootstrapTasks
{
public class ValueToItems : Task
{
[Required]
public string Value { get; set; }

public string Split { get; set; }

public ITaskItem[] Exclude { get; set; }

[Output]
public ITaskItem[] Items { get; set; }

[Output]
public ITaskItem Location { get; set; }

public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (ValueToItems)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Value)}: {Value}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Split)}: '{Split}'");
Log.LogMessage (MessageImportance.Low, $" {nameof (Exclude)}:'");
foreach (var e in (Exclude ?? new ITaskItem[0])) {
Log.LogMessage (MessageImportance.Low, $" {e}");
}

var items = new List<ITaskItem> ();
var excludes = Exclude?.Select (e => e.ItemSpec)?.ToList ();

var values = Value.Split (new [] { Split }, StringSplitOptions.RemoveEmptyEntries);
foreach (var v in values) {
if (excludes != null && excludes.Any (e => string.Equals (e, v, StringComparison.OrdinalIgnoreCase)))
continue;
items.Add (new TaskItem (v));
}

Items = items.ToArray ();

Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Items)}:");
foreach (var e in Items) {
Log.LogMessage (MessageImportance.Low, $" {e}");
}

return !Log.HasLoggedErrors;
}
}
}

6 changes: 0 additions & 6 deletions src/monodroid/monodroid.projitems
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_SupportedAbis>$(AndroidSupportedAbis.Replace(':', ';'))</_SupportedAbis>
</PropertyGroup>
<ItemGroup>
<_MonoRuntime Include="$(_SupportedAbis)" Exclude="@(HostOSName)" />
</ItemGroup>
<ItemGroup>
<_RequiredProgram Include="xxd" />
</ItemGroup>
Expand Down
10 changes: 10 additions & 0 deletions src/monodroid/monodroid.targets
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.ValueToItems" />
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.Which" />
<Import Project="monodroid.projitems" />
<PropertyGroup>
Expand All @@ -8,7 +9,16 @@
<ItemGroup>
<CFiles Include="jni\**\*.c" />
</ItemGroup>
<Target Name="_GetRuntimes">
<ValueToItems
Value="$(AndroidSupportedAbis)"
Split=":"
Exclude="@(HostOSName)">
<Output TaskParameter="Items" ItemName="_MonoRuntime" />
</ValueToItems>
</Target>
<Target Name="_BuildRuntimes"
DependsOnTargets="_GetRuntimes"
Inputs="@(CFiles);jni\Android.mk"
Outputs="@(_MonoRuntime->'$(OutputPath)\%(Identity)\libmono-android.$(_Conf).so')">
<Which Program="%(_RequiredProgram.Identity)" Required="True" />
Expand Down

0 comments on commit 2524fdb

Please sign in to comment.