Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[build] msbuild /t:Prepare Xamarin.Android.sln hits ""ResolveAndroidTooling" task failed unexpectedly." with Visual Studio 2017 version 15.9 Preview if $(AndroidToolchainDirectory) doesn't already exist #2195

Closed
brendanzagaeski opened this issue Sep 19, 2018 · 5 comments · Fixed by #2204

Comments

@brendanzagaeski
Copy link
Member

This is a new error that happens when running msbuild /t:Prepare Xamarin.Android.sln using Visual Studio 2017 version 15.9 Preview or higher (any version that includes d73442e).

The error doesn't happen when building with Visual Studio 2017 version 15.8 because in that version GetMaxInstalledApiLevel() was directly part of a single large ResolveSdkTask where $(AndroidSdkPath) was set to MonoAndroidHelper.AndroidSdk.AndroidSdkPath (C:\Program Files (x86)\Android\android-sdk in my test environment). Although ResolveSdkTask itself still uses MonoAndroidHelper.AndroidSdk.AndroidSdkPath in Visual Studio 2017 version 15.9 Preview, the new ResolveAndroidTooling task does not currently use MonoAndroidHelper, so $(AndroidSdkPath) stays set to $(AndroidToolchainDirectory) (C:\src\android-toolchain in my test environment). When GetMaxInstalledApiLevel() calls Directory.EnumerateDirectories() on the Android SDK in the program files directory, it works because that directory exists, but when it tries to enumerate C:\src\android-toolchain, it hits an error because that directory does not yet exist. (The next step of the build just after the NuGet packages are restored is to set up that directory.)

Possible Fix

One possible way to resolve this issue is to have ResolveAndroidTooling use MonoAndroidHelper.AndroidSdk.AndroidSdkPath:

diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs
index a6b76204..9161bb99 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs
@@ -77,6 +77,9 @@ namespace Xamarin.Android.Tasks
 
 		public override bool Execute ()
 		{
+			AndroidNdkPath = MonoAndroidHelper.AndroidSdk.AndroidNdkPath;
+			AndroidSdkPath = MonoAndroidHelper.AndroidSdk.AndroidSdkPath;
+
 			string toolsZipAlignPath = Path.Combine (AndroidSdkPath, "tools", ZipAlign);
 			bool findZipAlign = (string.IsNullOrEmpty (ZipAlignPath) || !Directory.Exists (ZipAlignPath)) && !File.Exists (toolsZipAlignPath);
 

I tested this locally, and it worked as desired for this scenario. I believe this should be OK for end-user Xamarin.Android app builds too because it's just going back to how these paths were determined at this step in Visual Studio 2017 version 15.8.

Other possibles approaches

I initially tried moving <MSBuild Projects="$(MSBuildThisFileDirectory)..\android-toolchain\android-toolchain.csproj" /> to happen before the NuGet restore commands, but that was unsuccessful due to missing dependencies. It might be possible to adjust android-toolchain.csproj and the other preparation steps so that android-toolchain.csproj can build before any NuGet.exe restore step (or more precisely, before any NuGet.exe restore on a project that imports Xamarin.Android.Common.targets), but I haven't experimented with that.

Steps to Reproduce

  1. Install Visual Studio 2017 version 15.9 Preview 2 or higher with the Mobile development with .NET workload. Also select the following Individual components:

    • .NET Framework 4 targeting pack
    • .NET Framework 4.5 targeting pack
    • .NET Framework 4.5.1 targeting pack
    • .NET Framework 4.5.2 targeting pack
    • .NET Framework 4.6 targeting pack
    • .NET Framework 4.6.1 targeting pack
    • .NET Framework 4.6.2 targeting pack
  2. git clone https://github.com/xamarin/xamarin-android.git

  3. Ensure that you do not yet have an android-toolchain directory from a previous msbuild /t:Prepare Xamarin.Android.sln. (Or rename the existing directory out of the way.)

  4. msbuild Xamarin.Android.sln /t:Prepare

    If Visual Studio version 15.8 is also installed, then NuGet will default to using the MSBuild and Xamarin.Android.Common.targets file from that version, and the /t:Prepare target will succeed. In that case you can invoke NuGet directly instead, passing in the path to MSBuild from the Visual Studio preview version:

    .\.nuget\NuGet.exe restore .\Xamarin.Android-Tests.sln -MSBuildPath "C:\Program Files (x86)\Microsoft Visual Studio\Preview\Enterprise\MSBuild\15.0\bin"

Expected Behavior

The NuGet restore step succeeds.

Actual Behavior

The NuGet restore step fails for Xamarin.Android-Tests.sln at the point where _SetLatestTargetFrameworkVersion calls the new ResolveAndroidTooling task.

"C:\Users\Windows User\AppData\Local\Temp\NuGetScratch\uj5oucwn.yyt.nugetinputs.targets" (GenerateRestoreGraphFile target) (1) ->
"C:\src\xamarin-android\src\Mono.Android\Test\Mono.Android-Tests.csproj
" (_GenerateProjectRestoreGraph target) (2:5) ->
(_SetLatestTargetFrameworkVersion target) -> 
  C:\Program Files (x86)\Microsoft Visual Studio\Preview\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(712,2): error MSB4018: The 
"ResolveAndroidTooling" task failed unexpectedly. [C:\src\xamarin-android\src\Mono.Android\Test\Mono.Android-Tests.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\Preview\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(712,2): error MSB4018: 
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\src\android-toolchain\sdk\platforms'. 
[C:\src\xamarin-android\src\Mono.Android\Test\Mono.Android-Tests.csproj]
@brendanzagaeski
Copy link
Member Author

brendanzagaeski commented Sep 19, 2018

/cc @jonathanpeppers, for whenever you have a moment, so I can have you sanity-check if it sounds reasonable to paste those 2 lines from ResolveSdkTask into ResolveAndroidTooling (as shown in the Possible Fix section) as a way to take care of this. Thanks!

@jonathanpeppers
Copy link
Member

So I guess I haven't run into this, because I don't set $(AndroidToolchainDirectory), I generally leave all the options default/blank (don't even use Configuration.Override.props).

Basically you could boil it down to:

  • You want a custom $(AndroidToolchainDirectory), let's say your username has a space or you want it at C:\android, etc.
  • $(AndroidToolchainDirectory) has not been created yet
  • nuget.exe restore Xamarin.Android.sln errors out, because it's going to call MSBuild and the _SetLatestTargetFrameworkVersion target

I'm not sure what the best fix is here...

If you took your example:

AndroidSdkPath = MonoAndroidHelper.AndroidSdk.AndroidSdkPath;

I'm guessing this works because it goes and finds some Android SDK somewhere, could you have one from the VS install? I also wouldn't want to do this, as it's going to go "find" an SDK instead of the one supplied by the setting in the IDE in customer apps.

Your other idea about reordering stuff seems a bit safer, but we might have a chicken-and-egg scenario.

We had to work around something like this for NuGet when we introduced TargetFrameworkVersion=v9.0 and system Xamarin.Android didn't have it yet: 41a4cbc

I would rather get rid of 41a4cbc in favor of something less hacky, maybe could fix this scenario at the same time? Need to think about it.

@brendanzagaeski
Copy link
Member Author

You want a custom $(AndroidToolchainDirectory), let's say your username has a space or you want it at C:\android, etc.

I realized overnight that this condition isn't necessary, and so there is in fact a way to hit the issue in end-user app builds too: #2200.

I'm assuming that since $(AndroidUseLatestPlatformSdk) still has an effect in Visual Studio 2017 version 15.9 Preview 2, it's probably safest to apply the Possible Fix patch, at least for the Visual Studio 2017 version 15.9 release. But if the goal is actually to disable $(AndroidUseLatestPlatformSdk) entirely (even when explicitly set in a command line build) by the time of the first version 15.9 non-preview release, then this might not be necessary.

@jonpryor
Copy link
Member

$(AndroidUseLatestPlatformSdk)=True needs to continue to be supported on Visual Studio for Mac until after the next major release. Visual Studio (Windows) 15.8 will actively remove this property from .csproj files.

@jonathanpeppers
Copy link
Member

We believe this fixes it: #2204

@brendanzagaeski feel free to reopen if you find something new here.

@xamarin xamarin locked as resolved and limited conversation to collaborators Jun 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
3 participants