Skip to content

Commit ec426d1

Browse files
committed
[Xamarin.Android.Build.Tasks] Use correct Mono.Android.dll
We're trying to get [`make jenkins`][0] working on Jenkins, and [it's failing][1], as one might expect when a particular repo and associated build system has never been run on Jenkins before: Android.App/ApplicationTest.cs(9,7): error CS0246: The type or namespace name `NUnit' could not be found. Are you missing an assembly reference? This error occurs while building `src/Mono.Android/Test/Mono.Android-Tests.csproj`, and happens because the `Xamarin.Android.NUnitLite.dll` assembly isn't referenced... because it isn't *found*: Microsoft.Common.targets: warning : Reference 'Xamarin.Android.NUnitLite' not resolved This raises a long-standing issue with building `xamarin-android`: The Xamarin.Android SDK is intended to be usable from a system-wide installation environment, e.g. installed into `$(MSBuildExtensionsPath)`, as many MSBuild tasks such as `<GetReferenceAssemblyPaths/>` are used to resolve assemblies, and those -- by default -- look in system-wide installation locations. "Unfortunately," A `xamarin-android` *build* **should not** be built into the system-wide install location; it should be built in a separate location, for all manner of "hygiene" and "sanity" reasons. Additionally, overriding `$(TargetFrameworkRootPath)` isn't a reliable solution. All of which adds up to either build failures such as the above -- when there is no system-wide Xamarin.Android install -- or the use/resolution of the system-wide Xamarin.Android assemblies when building e.g. `src/Mono.Android/Test`, which is wholly undesirable. A possible "fix"/"workaround": *force* `xbuild` to behave as we want it to by setting the `$MSBuildExtensionsPath` and `$XBUILD_FRAMEWORK_FOLDERS_PATH` environment variables *from within the build process*. Since `xbuild` doesn't cache the value of these environment variables, calling `Environment.SetEnvironmentVariable()` within the build process will cause subsequent `<GetReferenceAssemblyPaths/>`/etc. invocations to use the updated values, allowing us to control which directories are used for assembly framework resolution purposes. Update the `_GetReferenceAssemblyPaths` target within `Xamarin.Android.Common.targets` and `Xamarin.Android.Bindings.targets` so that they call the new `<SetMSBuildExtensionsPath/>` task, which updates the `$MSBuildExtensionsPath` and `$XBUILD_FRAMEWORK_FOLDERS_PATH` environment variables. This allows building `src/Mono.Android/Test` with "normal" `xbuild` to use the intended assemblies without requiring the use of `tools/scripts/xabuild` to build `src/Mono.Android/Test`. [0]: a16673d [1]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/20/console
1 parent f3943b1 commit ec426d1

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
5+
using Microsoft.Build.Utilities;
6+
using Microsoft.Build.Framework;
7+
8+
namespace Xamarin.Android.Tasks
9+
{
10+
public sealed class SetMSBuildExtensionsPath : Task
11+
{
12+
const string MSBuildExtensionsPath = "MSBuildExtensionsPath";
13+
const string XBUILD_FRAMEWORK_FOLDERS_PATH = "XBUILD_FRAMEWORK_FOLDERS_PATH";
14+
public override bool Execute ()
15+
{
16+
var frameworksPath = Path.GetDirectoryName (typeof (SetMSBuildExtensionsPath).Assembly.Location);
17+
if (Path.DirectorySeparatorChar == '\\') {
18+
// TODO: Default Windows search location
19+
} else {
20+
// e == $prefix/lib/xbuild/Xamarin/Android
21+
// Want: $prefix/lib/xbuild-frameworks
22+
if (!frameworksPath.EndsWith ("xbuild/Xamarin/Android", StringComparison.OrdinalIgnoreCase)) {
23+
throw new NotSupportedException ("Cannot determine path to xbuild-frameworks!");
24+
}
25+
frameworksPath = Path.GetDirectoryName (Path.GetDirectoryName (Path.GetDirectoryName (frameworksPath)));
26+
frameworksPath = Path.Combine (frameworksPath, "xbuild-frameworks");
27+
}
28+
29+
UpdateEnvironmentVariable (MSBuildExtensionsPath, frameworksPath);
30+
UpdateEnvironmentVariable (XBUILD_FRAMEWORK_FOLDERS_PATH, frameworksPath);
31+
32+
return !Log.HasLoggedErrors;
33+
}
34+
35+
void UpdateEnvironmentVariable (string environmentVariable, string newPath)
36+
{
37+
var p = (Environment.GetEnvironmentVariable (environmentVariable) ?? "")
38+
.Split (new [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);
39+
if (p.Any (x => string.Equals (x, newPath, StringComparison.OrdinalIgnoreCase))) {
40+
return;
41+
}
42+
43+
var newValue = string.Join (Path.PathSeparator.ToString (), new [] { newPath }.Concat (p));
44+
Log.LogMessage (MessageImportance.Low, $" Setting environment variable `{environmentVariable}`='{newValue}'.");
45+
Environment.SetEnvironmentVariable (environmentVariable, newValue);
46+
}
47+
}
48+
}
49+

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Copyright (C) 2012 Xamarin Inc. All rights reserved.
3535
<UsingTask TaskName="Xamarin.Android.Tasks.CreateNativeLibraryArchive" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
3636
<UsingTask TaskName="Xamarin.Android.Tasks.ImportJavaDoc" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
3737
<UsingTask TaskName="Xamarin.Android.Tasks.MDoc" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
38+
<UsingTask TaskName="Xamarin.Android.Tasks.SetMSBuildExtensionsPath" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
3839

3940
<!--
4041
*******************************************
@@ -142,6 +143,7 @@ Copyright (C) 2012 Xamarin Inc. All rights reserved.
142143
</PropertyGroup>
143144

144145
<Target Name="_GetReferenceAssemblyPaths">
146+
<SetMSBuildExtensionsPath />
145147
<GetReferenceAssemblyPaths
146148
TargetFrameworkMoniker="$(TargetFrameworkIdentifier),Version=v1.0"
147149
RootPath="$(TargetFrameworkRootPath)">

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@
391391
<Compile Include="Tasks\CheckTargetFrameworks.cs" />
392392
<Compile Include="Tasks\Dx.cs" />
393393
<Compile Include="Tasks\CreateMsymManifest.cs" />
394+
<Compile Include="Tasks\SetMSBuildExtensionsPath.cs" />
394395
<Compile Include="Utilities\AndroidResource.cs">
395396
<Link>Utilities\AndroidResource.cs</Link>
396397
</Compile>

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
9191
<UsingTask TaskName="Xamarin.Android.Tasks.Proguard" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
9292
<UsingTask TaskName="Xamarin.Android.Tasks.DetermineJavaLibrariesToCompile" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
9393
<UsingTask TaskName="Xamarin.Android.Tasks.CreateMultiDexMainDexClassList" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
94+
<UsingTask TaskName="Xamarin.Android.Tasks.SetMSBuildExtensionsPath" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
9495

9596
<!--
9697
*******************************************
@@ -531,6 +532,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
531532
</Target>
532533

533534
<Target Name="_GetReferenceAssemblyPaths">
535+
<SetMSBuildExtensionsPath />
534536
<GetReferenceAssemblyPaths
535537
TargetFrameworkMoniker="$(TargetFrameworkIdentifier),Version=v1.0"
536538
RootPath="$(TargetFrameworkRootPath)">

0 commit comments

Comments
 (0)