Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] JavaToolTask Error Reporting (#7012)
Browse files Browse the repository at this point in the history
Fixes: #7009

Context: xamarin/monodroid@b60c77f

Let's create a `java`-related error message!

 1. Create an `android` app:

        dotnet new -n bad_error

 2. Edit `bad_error.csproj` to change
    `$(SupportedOSPlatformVersion)`=23, and add this item group:

        <ItemGroup>
          <PackageReference Include="Xamarin.AndroidX.Wear" Version="1.2.0.5" />
          <PackageReference Include="Xamarin.Android.Wear" Version="2.2.0" />
          <PackageReference Include="Xamarin.AndroidX.PercentLayout" Version="1.0.0.14" />
          <PackageReference Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.14" />
        </ItemGroup>

 3. Build

        dotnet build bad_error/bad_error.csproj

It should fail to build:

	error : java.lang.RuntimeException: com.android.tools.r8.CompilationFailedException:
	Compilation failed to complete, origin: obj/Debug/net7.0-android/lp/59/jl/classes.jar :
	android/support/v4/app/INotificationSideChannel$Stub.class

It is expected to fail.  The problem is that *why* it fails is
opaque, and thus it's very hard to know what the problem is so that
it can be fixed.

If you rebuild with diagnostic logging enabled:

	dotnet build -v diag bad_error/bad_error.csproj

We get additional, *useful*, contextual information:

	Task "D8"
	  Task Parameter:JavaMaximumHeapSize=1G
	  Task Parameter:OutputDirectory=obj/Debug/net7.0-android/android/bin/
	  Task Parameter:
	      JavaLibrariesToEmbed=
	          …/dotnet/packs/Microsoft.Android.Ref.32/33.0.0-preview.4.20/ref/net7.0/mono.android.jar
	          …
	  Task Parameter:JarPath=…/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.0-preview.4.20/tools/r8.jar
	  …
	    processing ClassesZip, JavaLibrariesToEmbed...
	  $HOME/android-toolchain/jdk-11/bin/java -Xmx1G -classpath …/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.0-preview.4.20/tools/r8.jar com.android.tools.r8.D8 --debug --min-api 23 --output obj/Debug/net7.0-android/android/bin/ …
	  Error in obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class:
	  Type android.support.v4.app.INotificationSideChannel$Stub is defined multiple times: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class, obj/Debug/net7.0-android/lp/4/jl/bin/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  Compilation failed
	  Exception in thread "main" java.lang.RuntimeException: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, origin: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  	at com.android.tools.r8.internal.Bj.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:98)
	  	at com.android.tools.r8.D8.main(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:4)
	  Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, origin: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  	at Version.fakeStackEntry(Version_3.3.28.java:0)
	  	at com.android.tools.r8.internal.Bj.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:75)
	  	…
	  Caused by: com.android.tools.r8.internal.f: Type android.support.v4.app.INotificationSideChannel$Stub is defined multiple times: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class, obj/Debug/net7.0-android/lp/4/jl/bin/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  	at com.android.tools.r8.internal.DT.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:14)
	  	…

*Now* we see what the error is:

	Type android.support.v4.app.INotificationSideChannel$Stub is defined multiple times:

The fundamental problem is that this entire process is "broken": we
shouldn't require that the project be rebuilt with diagnostic logging
enabled in order to *begin* to understand what the error was.

Part of why the original error message was so "unhelpful" was because
of an explicit attempt to produce a more "helpful" message; from
xamarin/monodroid@b60c77fe

> we need to pick out the exception and then ignore the rest of the
> infromation [sic]. We also need to produce more 'helpful' messages
> to the user for these kind of exceptions. 

In retrospect, attempting to "trim out extraneous information" was a
mistake, as it's very hard to know what is and isn't extraneous.

Improve `<JavaToolTask/>` so that we go the other way: capture *all*
output from `java`, and when an error is detected, dump out all the
output from the `java` command.  This way, instead of:

	error : java.lang.RuntimeException: com.android.tools.r8.CompilationFailedException: …

we can provide a more complete error message *without* needing to
enable diagnostic logs:

	  error JAVA0000: Error in obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class:
	  error JAVA0000: Type android.support.v4.app.INotificationSideChannel$Stub is defined multiple times: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class, obj/Debug/net7.0-android/lp/4/jl/bin/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  error JAVA0000: Compilation failed
	  error JAVA0000: Exception in thread "main" java.lang.RuntimeException: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, origin: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  error JAVA0000: 	at com.android.tools.r8.internal.Bj.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:98)
	  error JAVA0000: 	at com.android.tools.r8.D8.main(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:4)
	  error JAVA0000: Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, origin: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  error JAVA0000: 	at Version.fakeStackEntry(Version_3.3.28.java:0)
	  error JAVA0000: 	at com.android.tools.r8.internal.Bj.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:75)
	  error JAVA0000: 	…
	  error JAVA0000: Caused by: com.android.tools.r8.internal.f: Type android.support.v4.app.INotificationSideChannel$Stub is defined multiple times: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class, obj/Debug/net7.0-android/lp/4/jl/bin/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class
	  error JAVA0000: 	at com.android.tools.r8.internal.DT.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:14)
	  error JAVA0000: 	…

Unfortunately, this error message is still cryptic: what does
`obj/Debug/net7.0-android/lp/59/jl/classes.jar` come from?
What about `obj/Debug/net7.0-android/lp/4/jl/bin/classes.jar`?

At the end of the full `java` output, dump a mapping of the
encountered `…/lp/…` paths to where they came from:

	error JAVA0000: Directory `obj/Debug/net7.0-android/lp/59` is from `androidx.interpolator.interpolator.aar`
	error JAVA0000: Directory `obj/Debug/net7.0-android/lp/4` is from `Xamarin.Android.Support.Compat.dll`
  • Loading branch information
dellis1972 authored Jun 7, 2022
1 parent e1af958 commit b002dc3
Show file tree
Hide file tree
Showing 23 changed files with 241 additions and 24 deletions.
4 changes: 4 additions & 0 deletions Documentation/guides/messages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ ms.date: 01/24/2020
+ APT0003: Invalid file name: It must contain only \[^a-zA-Z0-9_.\]+.
+ APT0004: Invalid file name: It must start with either A-Z or a-z or an underscore.

## JAVAxxxx: Java Tool

+ [JAVA0000](java0000.md): Generic Java tool error

## JAVACxxxx: Java compiler

+ [JAVAC0000](javac0000.md): Generic Java compiler error
Expand Down
34 changes: 34 additions & 0 deletions Documentation/guides/messages/java0000.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Xamarin.Android error JAVA0000
description: JAVA0000 error code
ms.date: 01/06/2022
---
# Xamarin.Android error JAVA0000

## Example messages

```
MSBUILD : java error JAVA0000: Error in obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class: [Example.csproj]
MSBUILD : java error JAVA0000: Type android.support.v4.app.INotificationSideChannel$Stub is defined multiple times: obj/Debug/net7.0-android/lp/59/jl/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class, obj/Debug/net7.0-android/lp/4/jl/bin/classes.jar:android/support/v4/app/INotificationSideChannel$Stub.class [Example.csproj]
MSBUILD : java error JAVA0000: Compilation failed [Example.csproj]
MSBUILD : java error JAVA0000: java.lang.RuntimeException: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, origin: obj/Debug/net7.0-android/lp/59/jl/classes.jar [Example.csproj]
MSBUILD : java error JAVA0000: android/support/v4/app/INotificationSideChannel$Stub.class [Example.csproj]
MSBUILD : java error JAVA0000: at com.android.tools.r8.internal.Bj.a(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:98) [Example.csproj]
MSBUILD : java error JAVA0000: at com.android.tools.r8.D8.main(R8_3.3.28_2aaf796388b4e9f6bed752d926eca110512a53a3f09a8d755196089c1cfdf799:4) [Example.csproj]
```

## Issue

During a normal Xamarin.Android build various java tools are run.
This message indicates that [`java`][java] tool which was
run raised an error.

## Solution

Look at the stack trace included in the error. This should provide
some clues into why the error occured.

Consider submitting a [bug][bug] if you are getting this error under
normal circumstances.

[bug]: https://github.com/xamarin/xamarin-android/wiki/Submitting-Bugs,-Feature-Requests,-and-Pull-Requests
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ It is shared between "legacy" binding projects and .NET 7+ projects.
Jars="@(_BindingJavaLibrariesToCompile);@(_ReferenceJavaLibs)"
JavacTargetVersion="$(JavacTargetVersion)"
JavacSourceVersion="$(JavacSourceVersion)"
IntermediateOutputPath="$(IntermediateOutputPath)"
AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)"
/>
<Touch Files="$(_AndroidCompileBindingJavaStampFile)" AlwaysCreate="true" />
<ItemGroup>
Expand Down Expand Up @@ -134,6 +136,8 @@ It is shared between "legacy" binding projects and .NET 7+ projects.
Jars="@(_JavaLibrariesToCompile);@(_InstantRunJavaReference);@(_ReferenceJavaLibs)"
JavacTargetVersion="$(JavacTargetVersion)"
JavacSourceVersion="$(JavacSourceVersion)"
IntermediateOutputPath="$(IntermediateOutputPath)"
AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)"
/>

<Touch Files="$(_AndroidCompileJavaStampFile)" AlwaysCreate="true" />
Expand Down
7 changes: 7 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -875,4 +875,11 @@ In this message, the term "handheld app" means "app for handheld devices."
<comment>The following are literal names and should not be translated: &lt;AndroidNamespaceReplacement&gt;
{0} - The AndroidNamespaceReplacement MSBuild value.</comment>
</data>
<data name="XA_Directory_Is_From" xml:space="preserve">
<value>Directory '{0}' is from '{1}'.</value>
<comment>
{0} - A Directory Path.
{1} - A Filename.
</comment>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins
<target state="new">`{0}` is empty. A value for `{0}` should be provided.</target>
<note>{0} - The MSBuildProperty which contains a value.
</note>
</trans-unit>
<trans-unit id="XA_Directory_Is_From">
<source>Directory '{0}' is from '{1}'.</source>
<target state="new">Directory '{0}' is from '{1}'.</target>
<note>
{0} - A Directory Path.
{1} - A Filename.
</note>
</trans-unit>
<trans-unit id="XA_Manifest_AutoGenerated_Header">
<source>
Expand Down
Loading

0 comments on commit b002dc3

Please sign in to comment.