From b002dc38196a0bedb18c82d228056e1ba108459c Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 7 Jun 2022 16:15:26 +0100 Subject: [PATCH] [Xamarin.Android.Build.Tasks] JavaToolTask Error Reporting (#7012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/xamarin/xamarin-android/issues/7009 Context: https://github.com/xamarin/monodroid/commit/b60c77feb371ba4e3b4f1aea4d8dfd4edcedcac0 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: 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 `` 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` --- Documentation/guides/messages/README.md | 4 ++ Documentation/guides/messages/java0000.md | 34 ++++++++++ .../Android/Xamarin.Android.Javac.targets | 4 ++ .../Properties/Resources.resx | 7 +++ .../Properties/xlf/Resources.cs.xlf | 8 +++ .../Properties/xlf/Resources.de.xlf | 8 +++ .../Properties/xlf/Resources.es.xlf | 8 +++ .../Properties/xlf/Resources.fr.xlf | 8 +++ .../Properties/xlf/Resources.it.xlf | 8 +++ .../Properties/xlf/Resources.ja.xlf | 8 +++ .../Properties/xlf/Resources.ko.xlf | 8 +++ .../Properties/xlf/Resources.pl.xlf | 8 +++ .../Properties/xlf/Resources.pt-BR.xlf | 8 +++ .../Properties/xlf/Resources.ru.xlf | 8 +++ .../Properties/xlf/Resources.tr.xlf | 8 +++ .../Properties/xlf/Resources.zh-Hans.xlf | 8 +++ .../Properties/xlf/Resources.zh-Hant.xlf | 8 +++ .../Tasks/JavaToolTask.cs | 62 ++++++++++++------- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 23 +++++++ .../Utilities/AssemblyIdentityMap.cs | 15 ++++- .../Xamarin.Android.Common.targets | 4 ++ .../Xamarin.Android.D8.targets | 4 ++ .../Xamarin.Android.DX.targets | 4 ++ 23 files changed, 241 insertions(+), 24 deletions(-) create mode 100644 Documentation/guides/messages/java0000.md diff --git a/Documentation/guides/messages/README.md b/Documentation/guides/messages/README.md index fac489e4860..32f8410f448 100644 --- a/Documentation/guides/messages/README.md +++ b/Documentation/guides/messages/README.md @@ -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 diff --git a/Documentation/guides/messages/java0000.md b/Documentation/guides/messages/java0000.md new file mode 100644 index 00000000000..689c25ea338 --- /dev/null +++ b/Documentation/guides/messages/java0000.md @@ -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 diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets index 75b68300b74..96a29c3676c 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets @@ -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)" /> @@ -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)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx index eda7c1bc109..565d697a15c 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx @@ -875,4 +875,11 @@ In this message, the term "handheld app" means "app for handheld devices." The following are literal names and should not be translated: <AndroidNamespaceReplacement> {0} - The AndroidNamespaceReplacement MSBuild value. + + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + + \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.cs.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.cs.xlf index 2a1c6274103..6e938e80eae 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.cs.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.cs.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.de.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.de.xlf index 9078a954ebf..b58b944374f 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.de.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.de.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.es.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.es.xlf index 783b5f8e0e4..f74c7c3ef61 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.es.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.es.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.fr.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.fr.xlf index 609d8f598e9..b433041a6cf 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.fr.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.fr.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.it.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.it.xlf index d2501f349c2..21994c01f6d 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.it.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.it.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ja.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ja.xlf index 53ac9456838..34628f73b2f 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ja.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ja.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ko.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ko.xlf index 38e815e8da9..ea658687d35 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ko.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ko.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pl.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pl.xlf index da758cb999c..5f7dbb870a0 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pl.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pl.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pt-BR.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pt-BR.xlf index a9636b01c76..e15d91c55e0 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pt-BR.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.pt-BR.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ru.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ru.xlf index c94e94638bd..454c6524ba9 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ru.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.ru.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.tr.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.tr.xlf index e2159a91288..88bcd39d56b 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.tr.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.tr.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hans.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hans.xlf index 73ea377e38f..88c332b0c53 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hans.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hans.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hant.xlf b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hant.xlf index 3b2f83edfd0..ac008d881df 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hant.xlf +++ b/src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.zh-Hant.xlf @@ -116,6 +116,14 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins `{0}` is empty. A value for `{0}` should be provided. {0} - The MSBuildProperty which contains a value. + + + Directory '{0}' is from '{1}'. + Directory '{0}' is from '{1}'. + +{0} - A Directory Path. +{1} - A Filename. + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs b/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs index 6e77b614501..fdc90873533 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs @@ -66,11 +66,14 @@ at com.android.dx.command.dexer.Main.main(Main.java:215) at com.android.dx.command.Main.main(Main.java:106) */ const string ExceptionRegExString = @"(?java.lang.+):(?.+)"; + const string LPDirectoryRegExString = @"(lp)([/\\]+)(?[0-9]+)([/\\]+)"; static readonly Regex codeErrorRegEx = new Regex (CodeErrorRegExString, RegexOptions.Compiled); static readonly Regex exceptionRegEx = new Regex (ExceptionRegExString, RegexOptions.Compiled); + static readonly Regex lpRegex = new Regex (LPDirectoryRegExString, RegexOptions.Compiled); bool foundError = false; List errorLines = new List (); StringBuilder errorText = new StringBuilder (); + HashSet mappingText = new HashSet (); string file; int line, column; @@ -78,10 +81,14 @@ at com.android.dx.command.Main.main(Main.java:106) public string JavaMaximumHeapSize { get; set; } - public virtual string DefaultErrorCode => null; + public virtual string DefaultErrorCode => "JAVA0000"; public string WorkingDirectory { get; set; } + public string AssemblyIdentityMapFile { get; set; } + + public string IntermediateOutputPath { get; set; } + protected override string ToolName { get { return OS.IsWindows ? "java.exe" : "java"; } } @@ -93,13 +100,16 @@ protected override string ToolName { protected override bool HandleTaskExecutionErrors () { if (foundError) { + AssemblyIdentityMap assemblyMap = new AssemblyIdentityMap (); + assemblyMap.Load (AssemblyIdentityMapFile); errorText.Clear (); + mappingText.Clear (); foreach (var line in errorLines) { - if (!ProcessOutput (line)) + if (!ProcessOutput (line, assemblyMap)) break; } if (foundError && errorText.Length > 0) { - Log.LogError (ToolName, DefaultErrorCode, null, file, line - 1, column + 1, 0, 0, errorText.ToString ()); + Log.LogError (ToolName, DefaultErrorCode, null, file, line - 1, column + 1, 0, 0, errorText.ToString () + String.Join (Environment.NewLine, mappingText)); } return !Log.HasLoggedErrors; } @@ -118,26 +128,35 @@ protected override string GenerateFullPathToTool () return Path.Combine (ToolPath, ToolExe); } - void LogFromException (string exception, string error) { + bool LogFromException (string exception, string error) { switch (exception) { case "java.lang.OutOfMemoryError": Log.LogCodedError ("XA5213", Properties.Resources.XA5213, ToolName, GenerateCommandLineCommands ()); - break; + return false; default: - Log.LogCodedError (DefaultErrorCode, "{0} : {1}", exception, error); - break; + return true; } } - bool ProcessOutput (string singleLine) + bool ProcessOutput (string singleLine, AssemblyIdentityMap assemblyMap) { var match = CodeErrorRegEx.Match (singleLine); var exceptionMatch = ExceptionRegEx.Match (singleLine); + var lp = lpRegex.Match (singleLine); + if (lp.Success) { + var id = lp.Groups["identifier"].Value; + var asmName = assemblyMap.GetAssemblyNameForImportDirectory (id); + if (!string.IsNullOrEmpty (asmName)) { + var path = Path.Combine(IntermediateOutputPath ?? string.Empty, "lp", id); + mappingText.Add (string.Format (Properties.Resources.XA_Directory_Is_From, path, asmName)); + } + } if (match.Success) { if (!string.IsNullOrEmpty (file)) { - Log.LogError (ToolName, DefaultErrorCode, null, file, line - 1, column + 1, 0, 0, errorText.ToString ()); + Log.LogError (ToolName, DefaultErrorCode, null, file, line - 1, column + 1, 0, 0, errorText.ToString () + String.Join (Environment.NewLine, mappingText)); errorText.Clear (); + mappingText.Clear (); } file = match.Groups ["file"].Value; var error = match.Groups ["error"].Value; @@ -150,8 +169,9 @@ bool ProcessOutput (string singleLine) line = 1; file = ""; column = 0; - LogFromException (exception, error); - return false; + errorText.AppendLine (exception); + errorText.AppendLine (error); + return LogFromException (exception, error); } else if (foundError) { if (singleLine.Trim () == "^") { column = singleLine.IndexOf ("^", StringComparison.Ordinal); @@ -160,8 +180,9 @@ bool ProcessOutput (string singleLine) if (singleLine.StartsWith ("Note:", StringComparison.Ordinal) || singleLine.Trim ().EndsWith ("errors", StringComparison.Ordinal)) { // See if we have one last error to print out - Log.LogError (ToolName, DefaultErrorCode, null, file, line - 1, column + 1, 0, 0, errorText.ToString ()); + Log.LogError (ToolName, DefaultErrorCode, null, file, line - 1, column + 1, 0, 0, errorText.ToString () + String.Join (Environment.NewLine, mappingText)); errorText.Clear (); + mappingText.Clear (); foundError = false; return true; } @@ -178,20 +199,15 @@ protected virtual void GetLineNumber (string match, out int line, out int column protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance) { - var match = CodeErrorRegEx.Match (singleLine); - var exceptionMatch = ExceptionRegEx.Match (singleLine); + errorLines.Add (singleLine); + base.LogEventsFromTextOutput (singleLine, messageImportance); // not sure why/when we would skip this? - if (match.Success || exceptionMatch.Success) { - Log.LogMessage (MessageImportance.High, singleLine); - foundError = true; - errorLines.Add (singleLine); - return; - } else if (foundError) { - Log.LogMessage (MessageImportance.High, singleLine); - errorLines.Add (singleLine); + if (foundError) { return; } - base.LogEventsFromTextOutput (singleLine, messageImportance); + var match = CodeErrorRegEx.Match (singleLine); + var exceptionMatch = ExceptionRegEx.Match (singleLine); + foundError = foundError || match.Success || exceptionMatch.Success; } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 8f4aa643cd4..121e07c600e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -1037,6 +1037,29 @@ public void SignAndroidPackage () Assert.IsTrue (builder.Build ("SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed"); } + [Test] + public void WearProjectJavaBuildFailure () + { + var proj = new XASdkProject { + IsRelease = true, + PackageReferences = { + new Package { Id = "Xamarin.AndroidX.Wear", Version = "1.2.0.5" }, + new Package { Id = "Xamarin.Android.Wear", Version = "2.2.0" }, + new Package { Id = "Xamarin.AndroidX.PercentLayout", Version = "1.0.0.14" }, + new Package { Id = "Xamarin.AndroidX.Legacy.Support.Core.UI", Version = "1.0.0.14" }, + }, + SupportedOSPlatformVersion = "23", + }; + var builder = CreateDotNetBuilder (proj); + Assert.IsFalse (builder.Build (), $"{proj.ProjectName} should fail."); + var text = $"java.lang.RuntimeException"; + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, text), $"Output did not contain '{text}'"); + text = $"is defined multiple times"; + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, text), $"Output did not contain '{text}'"); + text = $"is from 'androidx.core.core.aar'"; + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, text), $"Output did not contain '{text}'"); + } + [Test] public void BenchmarkDotNet () { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyIdentityMap.cs b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyIdentityMap.cs index 45a2add2f30..727cdb7741c 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyIdentityMap.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/AssemblyIdentityMap.cs @@ -12,7 +12,7 @@ internal class AssemblyIdentityMap public void Load (string mapFile) { map.Clear (); - if (!File.Exists (mapFile)) + if (string.IsNullOrWhiteSpace (mapFile) || !File.Exists (mapFile)) return; foreach (var s in File.ReadLines (mapFile)) { if (!map.Contains (s)) @@ -34,6 +34,19 @@ public string GetLibraryImportDirectoryNameForAssembly (string assemblyIdentity) return map.IndexOf (assemblyIdentity).ToString (); } + /// + /// Returns the name of the assembly for the provided `lp` directory. + /// + /// The directory in the `lp` directory which we want to resolve. + public string GetAssemblyNameForImportDirectory (string dir) + { + if (!int.TryParse (dir, out int index)) + return string.Empty; + if (index < 0 || index > map.Count) + return string.Empty; + return map [index]; + } + public void Save (string mapFile) { if (map.Count == 0) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index d58d740ee13..4eb4151e9b8 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1538,6 +1538,8 @@ because xbuild doesn't support framework reference assemblies. ManifestPlaceholders="$(AndroidManifestPlaceholders)" ManifestOverlayFiles="@(AndroidManifestOverlay)" ExtraArgs="$(AndroidManifestMergerExtraArgs)" + IntermediateOutputPath="$(IntermediateOutputPath)" + AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)" /> @@ -2082,6 +2084,8 @@ because xbuild doesn't support framework reference assemblies. UncompressedFileExtensions="$(AndroidStoreUncompressedFileExtensions)" CustomBuildConfigFile="$(AndroidBundleConfigurationFile)" MetaDataFiles="@(AndroidAppBundleMetaDataFile)" + IntermediateOutputPath="$(IntermediateOutputPath)" + AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets index f23db33f84a..5c56d4a8448 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets @@ -75,6 +75,8 @@ Copyright (C) 2018 Xamarin. All rights reserved. CustomMainDexListFiles="@(MultiDexMainDexList)" IgnoreWarnings="$(AndroidR8IgnoreWarnings)" ExtraArguments="$(AndroidR8ExtraArguments)" + IntermediateOutputPath="$(IntermediateOutputPath)" + AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets index bb32a838814..619f9aa04bd 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets @@ -71,6 +71,8 @@ Copyright (C) 2018 Xamarin. All rights reserved. CustomMainDexListFiles="@(MultiDexMainDexList)" ProguardInputJarFilter="$(_AndroidProguardInputJarFilter)" ExtraArgs="$(AndroidMultiDexClassListExtraArgs)" + IntermediateOutputPath="$(IntermediateOutputPath)" + AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)" /> @@ -95,6 +97,8 @@ Copyright (C) 2018 Xamarin. All rights reserved. MultiDexMainDexListFile="$(_AndroidMainDexListFile)" JavaLibrariesToCompile="@(_JavaLibrariesToCompileForApp);@(_InstantRunJavaReference)" AlternativeJarFiles="@(_AlternativeJarForAppDx)" + IntermediateOutputPath="$(IntermediateOutputPath)" + AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)" />