Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] trailing / causes missing classes.dex (#…
…4505) Fixes: #4478 Fixes: #4486 We with the release of VS for Mac 8.5 going stable have been getting some reports of: error ADB0010: Deployment failed Mono.AndroidTools.InstallFailedException: Failure [INSTALL_FAILED_INVALID_APK: Package couldn't be installed in /data/app/com.contoso.androidapp1-RTZZFPyLkRI7Bk7VDgGkDg==: Package /data/app/com.contoso.androidapp1-RTZZFPyLkRI7Bk7VDgGkDg==/base.apk code is missing] at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess (System.String output, System.String packageName) [0x00159] in <65710797f19f43cc9d8f9e05353b9615>:0 at Mono.AndroidTools.AndroidDevice+<>c__DisplayClass95_0.<InstallPackage>b__0 (System.Threading.Tasks.Task`1[TResult] t) [0x0001c] in <65710797f19f43cc9d8f9e05353b9615>:0 at System.Threading.Tasks.ContinuationTaskFromResultTask`1[TAntecedentResult].InnerInvoke () [0x00024] in <f9d1b832704f410aa8ec771f4fe80552>:0 at System.Threading.Tasks.Task.Execute () [0x00000] in <f9d1b832704f410aa8ec771f4fe80552>:0 --- End of stack trace from previous location where exception was thrown --- at AndroidDeviceExtensions.PushAndInstallPackage (Mono.AndroidTools.AndroidDevice device, System.String apkFile, System.String packageName, System.Boolean reinstall, Mono.AndroidTools.Adb.AdbProgressReporter notifyProgress, System.Threading.CancellationToken token) [0x001d3] in <81f66a65e9434daf9d06602cf6ac0bf9>:0 at AndroidDeviceExtensions.PushAndInstallPackage (Mono.AndroidTools.AndroidDevice device, System.String apkFile, System.String packageName, System.Boolean reinstall, Mono.AndroidTools.Adb.AdbProgressReporter notifyProgress, System.Threading.CancellationToken token) [0x00402] in <81f66a65e9434daf9d06602cf6ac0bf9>:0 at Xamarin.AndroidTools.AndroidDeploySession.InstallPackage () [0x003be] in <81f66a65e9434daf9d06602cf6ac0bf9>:0 at Xamarin.AndroidTools.AndroidDeploySession.RunAsync (System.Threading.CancellationToken token) [0x003f8] in <81f66a65e9434daf9d06602cf6ac0bf9>:0 at Xamarin.AndroidTools.AndroidDeploySession.RunLoggedAsync (System.Threading.CancellationToken token) [0x00077] in <81f66a65e9434daf9d06602cf6ac0bf9>:0 [/Users/macuser/Projects/AndroidApp1/AndroidApp1/AndroidApp1.csproj] The error means the `.apk` is missing `classes.dex`. It seems to affect apps where: * `$(AndroidDexTool)=dx`, this would need to be set explicitly or it would default to `d8`. * The issue appears to occur only on macOS. @brendanzagaeski [was able to reproduce the issue][0]: Using [`4478TestCase.zip`][1], there is an `obj` directory sitting next to the `.sln` file: * `obj` * `AndroidApp1` * `AndroidApp1/AndroidApp1.csproj` * `AndroidApp1/obj` * `AndroidApp1.sln` Note that the actual `$(BaseIntermediateOutputPath)` would be `AndroidApp1/obj`. Brendan just moved an `obj` directory next to the `.sln` file while trying to reproduce the issue. However, it appears the presence of this phantom `obj` triggers the issue! You can rename it to `obj2` to *solve* the issue. It is a directory with sub-directories, but no files. If you look at the build log, the main difference is: CompileToDalvik Parameters - ClassesOutputDirectory = obj/Release/android/bin/classes/ + ClassesOutputDirectory = obj/Release/android/bin/classes The presence of the trailing `/` breaks this code: cmd.AppendSwitchIfNotNull ("--output ", Path.GetDirectoryName (ClassesOutputDirectory)); `classes.dex` is output into `obj/Release/android/bin/classes` instead of `obj/Release/android/bin` and doesn't make it into the final `.apk`. Tracking back to what creates the input value of `ClassesOutputDirectory`, it is the MSBuild property `$(_AndroidIntermediateJavaClassDirectory)`, which is: <_AndroidIntermediateJavaClassDirectory>$(IntermediateOutputPath)android\bin\classes\</_AndroidIntermediateJavaClassDirectory> But then comparing broken vs working logs: Broken: _InitialBaseIntermediateOutputPath = obj/ BaseIntermediateOutputPath = obj/ IntermediateOutputPath = obj/Release/ _AndroidIntermediateJavaClassDirectory = obj/Release/android/bin/classes/ Working: _InitialBaseIntermediateOutputPath = obj\ BaseIntermediateOutputPath = obj\ IntermediateOutputPath = obj\Release\ _AndroidIntermediateJavaClassDirectory = obj\Release\android\bin\classes\ It appears the existence of this random `obj` directory influences MSBuild's path combining behavior? The trailing `\` works, but `/` does not, due to `TrimEnd`: <CompileToDalvik ... ClassesOutputDirectory="$(_AndroidIntermediateJavaClassDirectory.TrimEnd('\'))" The breakage was introduced in 185c529, which added a trailing `\` to the directory passed to `<CompileToDalvik/>`. We are unsure what is causing the strange MSBuild behavior. However, after reviewing `<CompileToDalvik/>`, I think we should just remove the `Path.GetDirectoryName()` call. We should just pass in the directory name we want to use from MSBuild targets. I could add a test for this scenario by setting a global property: /p:_AndroidIntermediateJavaClassDirectory=obj/Debug/android/bin/classes/ Setting a global property could test the trailing `/` character regardless of MSBuild behavior. I also cleaned things up a bit by create a new `$(_AndroidIntermediateDexOutputDirectory)` property. [0]: #4478 (comment) [1]: https://github.com/xamarin/xamarin-android/files/4419061/4478TestCase.zip
- Loading branch information