Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Documentation/build_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,27 @@ when packaing Release applications.

This property is `False` by default.

- **AndroidErrorOnCustomJavaObject** – A boolean property that
determines whether types may implement `Android.Runtime.IJavaObject`
*without* also inheriting from `Java.Lang.Object` or `Java.Lang.Throwable`:

class BadType : IJavaObject {
public IntPtr Handle {
get {return IntPtr.Zero;}
}

public void Dispose()
{
}
}

When True, such types will generate an XA4212 error, otherwise a
XA4212 warning will be generated.

Support for this property was added in Xamarin.Android 7.6.

This property is `True` by default.

- **AndroidFastDeploymentType** – A `:` (colon)-separated list
of values to control what types can be deployed to the
[Fast Deployment directory](#Fast_Deployment) on the target device
Expand Down
2 changes: 1 addition & 1 deletion external/Java.Interop
24 changes: 12 additions & 12 deletions src/Xamarin.Android.Build.Tasks/Tasks/AsyncTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,27 @@ public void LogDebugTaskItems (string message, ITaskItem[] items)
LogDebugMessage (" {0}", item.ItemSpec);
}

protected void LogMessage (string message)
public void LogMessage (string message)
{
LogMessage (message, importance: MessageImportance.Normal);
}

protected void LogMessage (string message, params object[] messageArgs)
public void LogMessage (string message, params object[] messageArgs)
{
LogMessage (string.Format (message, messageArgs));
}

protected void LogDebugMessage (string message)
public void LogDebugMessage (string message)
{
LogMessage (message , importance: MessageImportance.Low);
}

protected void LogDebugMessage (string message, params object[] messageArgs)
public void LogDebugMessage (string message, params object[] messageArgs)
{
LogMessage (string.Format (message, messageArgs), importance: MessageImportance.Low);
}

protected void LogMessage (string message, MessageImportance importance = MessageImportance.Normal)
public void LogMessage (string message, MessageImportance importance = MessageImportance.Normal)
{
if (UIThreadId == Thread.CurrentThread.ManagedThreadId) {
#pragma warning disable 618
Expand All @@ -121,27 +121,27 @@ protected void LogMessage (string message, MessageImportance importance = Messag
}
}

protected void LogError (string message)
public void LogError (string message)
{
LogError (code: null, message: message, file: null, lineNumber: 0);
}

protected void LogError (string message, params object[] messageArgs)
public void LogError (string message, params object[] messageArgs)
{
LogError (code: null, message: string.Format (message, messageArgs));
}

protected void LogCodedError (string code, string message)
public void LogCodedError (string code, string message)
{
LogError (code: code, message: message, file: null, lineNumber: 0);
}

protected void LogCodedError (string code, string message, params object[] messageArgs)
public void LogCodedError (string code, string message, params object[] messageArgs)
{
LogError (code: code, message: string.Format (message, messageArgs), file: null, lineNumber: 0);
}

protected void LogError (string code, string message, string file = null, int lineNumber = 0)
public void LogError (string code, string message, string file = null, int lineNumber = 0)
{
if (UIThreadId == Thread.CurrentThread.ManagedThreadId) {
#pragma warning disable 618
Expand Down Expand Up @@ -180,12 +180,12 @@ protected void LogError (string code, string message, string file = null, int li
}
}

protected void LogWarning (string message, params object[] messageArgs)
public void LogWarning (string message, params object[] messageArgs)
{
LogWarning (string.Format (message, messageArgs));
}

protected void LogWarning (string message)
public void LogWarning (string message)
{
if (UIThreadId == Thread.CurrentThread.ManagedThreadId) {
#pragma warning disable 618
Expand Down
2 changes: 1 addition & 1 deletion src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ void AddNativeLibrariesFromAssemblies (ZipArchiveEx apk, string supportedAbis)
{
int count = 0;
var abis = supportedAbis.Split (new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
using (var res = new DirectoryAssemblyResolver (Console.WriteLine, loadDebugSymbols: false)) {
using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
foreach (var assembly in EmbeddedNativeLibraryAssemblies)
res.Load (assembly.ItemSpec);
foreach (var assemblyPath in EmbeddedNativeLibraryAssemblies) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public override bool Execute ()
Log.LogDebugMessage (" ProjectFile: {0}", ProjectFile);
Log.LogDebugTaskItems (" ResolvedUserAssemblies: {0}", ResolvedAssemblies);

using (var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) {
using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
foreach (var assembly in ResolvedAssemblies) {
res.Load (Path.GetFullPath (assembly.ItemSpec));
var apiLevel = ExtractApiLevel (res, assembly);
Expand Down
13 changes: 10 additions & 3 deletions src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
Expand Down Expand Up @@ -51,6 +52,8 @@ public class GenerateJavaStubs : Task

public bool UseSharedRuntime { get; set; }

public bool ErrorOnCustomJavaObject { get; set; }

[Required]
public string ResourceDirectory { get; set; }

Expand All @@ -69,6 +72,7 @@ public override bool Execute ()
Log.LogDebugMessage (" PackageName: {0}", PackageName);
Log.LogDebugMessage (" AndroidSdkDir: {0}", AndroidSdkDir);
Log.LogDebugMessage (" AndroidSdkPlatform: {0}", AndroidSdkPlatform);
Log.LogDebugMessage ($" {nameof (ErrorOnCustomJavaObject)}: {ErrorOnCustomJavaObject}");
Log.LogDebugMessage (" OutputDirectory: {0}", OutputDirectory);
Log.LogDebugMessage (" MergedAndroidManifestOutput: {0}", MergedAndroidManifestOutput);
Log.LogDebugMessage (" UseSharedRuntime: {0}", UseSharedRuntime);
Expand All @@ -83,7 +87,7 @@ public override bool Execute ()
try {
// We're going to do 3 steps here instead of separate tasks so
// we can share the list of JLO TypeDefinitions between them
using (var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: true)) {
using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: true)) {
Run (res);
}
}
Expand Down Expand Up @@ -117,9 +121,12 @@ void Run (DirectoryAssemblyResolver res)
var fxAdditions = MonoAndroidHelper.GetFrameworkAssembliesToTreatAsUserAssemblies (ResolvedAssemblies)
.Where (a => assemblies.All (x => Path.GetFileName (x) != Path.GetFileName (a)));
assemblies = assemblies.Concat (fxAdditions).ToList ();

// Step 1 - Find all the JLO types
var all_java_types = JavaTypeScanner.GetJavaTypes (assemblies, res, Log.LogWarning);
var scanner = new JavaTypeScanner (this.CreateTaskLogger ()) {
ErrorOnCustomJavaObject = ErrorOnCustomJavaObject,
};
var all_java_types = scanner.GetJavaTypes (assemblies, res);

WriteTypeMappings (all_java_types);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public override bool Execute ()
var assemblyNames = new List<string> ();
if (IsApplication && References != null && References.Any ()) {
// FIXME: should this be unified to some better code with ResolveLibraryProjectImports?
using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) {
using (var resolver = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
foreach (var assemblyName in References) {
var suffix = assemblyName.ItemSpec.EndsWith (".dll") ? String.Empty : ".dll";
string hintPath = assemblyName.GetMetadata ("HintPath").Replace (Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ public override bool Execute ()
? CachePath
: Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), CacheBaseDir);

using (var resolver = new DirectoryAssemblyResolver (LogWarning, loadDebugSymbols: false)) {
using (var resolver = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
foreach (var assemblyItem in Assemblies) {
string fullPath = Path.GetFullPath (assemblyItem.ItemSpec);
if (assemblies.Contains (fullPath)) {
Expand Down
2 changes: 1 addition & 1 deletion src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public override bool Execute ()
var rp = new ReaderParameters {
InMemory = true,
};
using (var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false, loadReaderParameters: rp)) {
using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false, loadReaderParameters: rp)) {
return Execute (res);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class ResolveAssemblies : Task

public override bool Execute ()
{
using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) {
using (var resolver = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
return Execute (resolver);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public override bool Execute ()

assemblyMap.Load (AssemblyIdentityMapFile);

using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) {
using (var resolver = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
Extract (resolver, jars, resolvedResourceDirectories, resolvedAssetDirectories, resolvedEnvironmentFiles);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public override bool Execute ()
Log.LogDebugMessage ("StripEmbeddedLibraries Task");
Log.LogDebugTaskItems (" Assemblies: ", Assemblies);

using (var res = new DirectoryAssemblyResolver (Log.LogWarning, true, new ReaderParameters { ReadWrite = true } )) {
using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), true, new ReaderParameters { ReadWrite = true } )) {
return Execute (res);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,36 @@ public static void Foo () {
Assert.IsTrue(sb.BuildProject(app1, "SignAndroidPackage"), "Build of project should have succeeded");
sb.Dispose();
}

[Test]
public void XA4212 ()
{
var proj = new XamarinAndroidApplicationProject () {
};
proj.Sources.Add (new BuildItem ("Compile", "MyBadJavaObject.cs") { TextContent = () => @"
using System;
using Android.Runtime;
namespace UnnamedProject {
public class MyBadJavaObject : IJavaObject
{
public IntPtr Handle {
get {return IntPtr.Zero;}
}

public void Dispose ()
{
}
}
}" });
using (var builder = CreateApkBuilder (Path.Combine ("temp", TestContext.CurrentContext.Test.Name))) {
builder.ThrowOnBuildFailure = false;
Assert.IsFalse (builder.Build (proj), "Build should have failed with XA4212.");
StringAssert.Contains ($"error XA4", builder.LastBuildOutput, "Error should be XA4212");
StringAssert.Contains ($"Type `UnnamedProject.MyBadJavaObject` implements `Android.Runtime.IJavaObject`", builder.LastBuildOutput, "Error should mention MyBadJavaObject");
Assert.IsTrue (builder.Build (proj, parameters: new [] { "AndroidErrorOnCustomJavaObject=False" }), "Build should have succeeded.");
StringAssert.Contains ($"warning XA4", builder.LastBuildOutput, "warning XA4212");
}
}
}
}

37 changes: 37 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Utilities/MSBuildExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,43 @@ public static void LogCodedWarning (this TaskLoggingHelper log, string code, str
messageArgs: messageArgs);
}

public static Action<TraceLevel, string> CreateTaskLogger (this Task task)
{
Action<TraceLevel, string> logger = (level, value) => {
switch (level) {
case TraceLevel.Error:
task.Log.LogError ("{0}", value);
break;
case TraceLevel.Warning:
task.Log.LogWarning ("{0}", value);
break;
default:
task.Log.LogDebugMessage ("{0}", value);
break;
}
};
return logger;
}

public static Action<TraceLevel, string> CreateTaskLogger (this AsyncTask task)
{
Action<TraceLevel, string> logger = (level, value) => {
switch (level) {
case TraceLevel.Error:
task.LogError (value);
break;
case TraceLevel.Warning:
task.LogWarning (value);
break;
default:
task.LogDebugMessage (value);
break;
}
};
return logger;
}


public static IEnumerable<ITaskItem> Concat (params ITaskItem[][] values)
{
if (values == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
<AndroidSkipJavacVersionCheck Condition="'$(AndroidSkipJavacVersionCheck)' == ''">False</AndroidSkipJavacVersionCheck>
<AndroidBuildApplicationPackage Condition=" '$(AndroidBuildApplicationPackage)' == ''">False</AndroidBuildApplicationPackage>

<AndroidErrorOnCustomJavaObject Condition=" '$(AndroidErrorOnCustomJavaObject)' == '' ">True</AndroidErrorOnCustomJavaObject>

<!-- Ahead-of-time compilation properties -->
<AndroidAotMode Condition=" '$(AndroidAotMode)' == '' And '$(AotAssemblies)' == 'True' ">Normal</AndroidAotMode>
<AotAssemblies Condition=" '$(AndroidAotMode)' != '' ">True</AotAssemblies>
Expand Down Expand Up @@ -1733,6 +1735,7 @@ because xbuild doesn't support framework reference assemblies.
<GenerateJavaStubs
ResolvedAssemblies="@(_ResolvedAssemblies)"
ResolvedUserAssemblies="@(_ResolvedUserAssemblies)"
ErrorOnCustomJavaObject="$(AndroidErrorOnCustomJavaObject)"
ManifestTemplate="$(_AndroidManifestAbs)"
MergedManifestDocuments="@(ExtractedManifestDocuments)"
Debug="$(AndroidIncludeDebugSymbols)"
Expand Down