[Xamarin.Android.Build.Tasks] Don't download during DesignTimeBuild (#709)

Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=57281

One of the problems we have with downloading content is the DesignTimeBuilds.
We CANNOT allow a DesignTimeBuild to download stuff from the internet.
It will lock up the IDE for however long it takes to get the data
and the user will have no indication as to what is going on.

That said... in order to get intellisense working we need to make
sure that a default Xamarin.Forms project will at least build in
DesignTime mode.

So we have a problem. We cannot download stuff, but we need it to build.
Fortunately commit 4f10438c allowed the
`<GetAdditionalResourcesFromAssemblies/>` Task to look in the
android-sdk/extras folder to get its required resources. So we can alter the
Task to allow that part to happen, this will extract the data to the correct
location. But we will still make sure that we do not download any additional
data from the internet.

So providing the m2repository bits are installed in the android-sdk/extras
these changes will allow those to be extracted in a DesignTimeBuild.
The idea is those extras should be installed as part of the main installer,
which will allow the default project to build. Obviously if those extras
are not installed the build will still fail. But as already stated
that cannot be avoided.

We also added `$(DesignTimeBuild)` to the property cache files so we can
ensure that when we do switch to a main build we run
`GetAdditionalResourcesFromAssemblies` again.
This commit is contained in:
Dean Ellis 2017-08-01 00:49:20 +01:00 коммит произвёл Jonathan Pryor
Родитель 4f3d604626
Коммит 1cd582ecc7
4 изменённых файлов: 65 добавлений и 23 удалений

Просмотреть файл

@ -47,6 +47,9 @@ namespace Xamarin.Android.Tasks {
[Required]
public ITaskItem[] Assemblies { get; set; }
[Required]
public bool DesignTimeBuild { get; set; }
[Required]
public string CacheFile { get; set; }
@ -153,7 +156,8 @@ namespace Xamarin.Android.Tasks {
items.Add (Path.GetFullPath (path).TrimEnd (Path.DirectorySeparatorChar));
return;
}
LogCodedError (errorCode, errorFmt, ErrorMessage (attr), path);
if (!DesignTimeBuild)
LogCodedError (errorCode, errorFmt, ErrorMessage (attr), path);
}
bool ExtractArchive (string url, string file, string contentDir)
@ -180,7 +184,7 @@ namespace Xamarin.Android.Tasks {
catch (Exception e) {
LogCodedError ("XA5209", "Unzipping failed. Please download {0} and extract it to the {1} directory.", url, contentDir);
LogCodedError ("XA5209", "Reason: {0}", e.Message);
Log.LogMessage (MessageImportance.Low, e.ToString ());
LogMessage (e.ToString (), MessageImportance.Low);
Directory.Delete (contentDir, true);
return false;
}
@ -198,9 +202,9 @@ namespace Xamarin.Android.Tasks {
return true;
var hash = Xamarin.Android.Tools.Files.HashFile (file).Replace ("-", String.Empty);
Log.LogDebugMessage ("File :{0}", file);
Log.LogDebugMessage ("SHA1 : {0}", hash);
Log.LogDebugMessage ("Expected SHA1 : {0}", sha1);
LogDebugMessage ("File :{0}", file);
LogDebugMessage ("SHA1 : {0}", hash);
LogDebugMessage ("Expected SHA1 : {0}", sha1);
var isValid = string.Compare (hash, sha1, StringComparison.InvariantCultureIgnoreCase) == 0;
if (isValid)
@ -274,7 +278,7 @@ namespace Xamarin.Android.Tasks {
if (string.IsNullOrEmpty (url))
return null;
Log.LogDebugMessage ("Making sure we have {0} downloaded and extracted {1} from it...", url, embeddedArchive);
LogDebugMessage ("Making sure we have {0} downloaded and extracted {1} from it...", url, embeddedArchive);
string destinationDir = version == null ? destinationBase : Path.Combine (destinationBase, version);
bool createDestinationDirectory = !Directory.Exists (destinationDir);
@ -293,6 +297,11 @@ namespace Xamarin.Android.Tasks {
string file = Path.Combine (zipDir, !uri.IsFile ? hash + ".zip" : Path.GetFileName (uri.AbsolutePath));
if (string.IsNullOrEmpty (extraPath) && (!File.Exists (file) || !IsValidDownload (file, sha1) || !MonoAndroidHelper.IsValidZip (file))) {
if (DesignTimeBuild) {
LogWarning ($"DesignTimeBuild={DesignTimeBuild}. Skipping download of {url}");
return null;
}
int progress = -1;
var downloadHandler = new Action<long, long, int>((r,t,p) => {
if (p % 10 != 0 || progress == p)
@ -311,7 +320,7 @@ namespace Xamarin.Android.Tasks {
} catch (Exception e) {
LogCodedError ("XA5208", "Download failed. Please build again.");
LogCodedError ("XA5208", "Reason: {0}", e.GetBaseException ().Message);
Log.LogMessage (MessageImportance.Low, e.ToString ());
LogMessage (e.ToString (), MessageImportance.Low);
}
}
else {
@ -340,7 +349,7 @@ namespace Xamarin.Android.Tasks {
if (Log.HasLoggedErrors)
break;
if (!success) {
Log.LogWarning ("Expected File {0} does not exist. Trying to extract again.", Path.Combine (contentDir, embeddedArchive));
LogWarning ("Expected File {0} does not exist. Trying to extract again.", Path.Combine (contentDir, embeddedArchive));
if (Directory.Exists (contentDir))
Directory.Delete (contentDir, recursive: true);
}
@ -385,7 +394,7 @@ namespace Xamarin.Android.Tasks {
? CachePath
: Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), CacheBaseDir);
using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) {
using (var resolver = new DirectoryAssemblyResolver (LogWarning, loadDebugSymbols: false)) {
foreach (var assemblyItem in Assemblies) {
string fullPath = Path.GetFullPath (assemblyItem.ItemSpec);
if (assemblies.Contains (fullPath)) {

Просмотреть файл

@ -8,6 +8,7 @@ using System.Text;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using System.Xml.Linq;
using System.Security.Cryptography;
namespace Xamarin.Android.Build.Tests
{
@ -36,19 +37,49 @@ namespace Xamarin.Android.Build.Tests
[Test]
public void DesignTimeBuild ([Values(false, true)] bool isRelease)
{
var url = "http://dl-ssl.google.com/android/repository/build-tools_r24-macosx.zip";
var md5 = MD5.Create ();
var hash = string.Concat (md5.ComputeHash (Encoding.UTF8.GetBytes (url)).Select (b => b.ToString ("X02")));
var zipPath = Path.Combine (CachePath, "zips", $"{hash}.zip");
if (File.Exists (zipPath))
File.Delete (zipPath);
var extractedDir = Path.Combine (CachePath, "Lib1");
if (Directory.Exists (extractedDir))
Directory.Delete (extractedDir, recursive: true);
var lib = new XamarinAndroidLibraryProject () {
ProjectName = "Lib1",
IsRelease = isRelease,
AssemblyInfo = @"using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: Android.NativeLibraryReferenceAttribute (""android-N/renderscript/lib/packaged/x86/librsjni.so"",
SourceUrl="""+ url +@""",
Version=""1"", PackageName=""Lib1"")]
",
};
var proj = new XamarinAndroidApplicationProject () {
IsRelease = isRelease,
References = {
new BuildItem.ProjectReference (@"..\Lib1\Lib1.csproj", lib.ProjectName, lib.ProjectGuid),
},
};
using (var b = CreateApkBuilder (string.Format ("temp/DesignTimeBuild_{0}", isRelease))) {
b.Verbosity = Microsoft.Build.Framework.LoggerVerbosity.Diagnostic;
b.ThrowOnBuildFailure = false;
Assert.IsTrue (b.UpdateAndroidResources (proj, parameters: new string[] { "DesignTimeBuild=true" }),
"first build failed");
Assert.IsFalse (b.LastBuildOutput.Contains ("Done executing task \"GetAdditionalResourcesFromAssemblies\""),
"failed to skip GetAdditionalResourcesFromAssemblies");
Assert.IsTrue (b.Build (proj), "second build failed");
Assert.IsTrue (b.LastBuildOutput.Contains ("Task \"GetAdditionalResourcesFromAssemblies\""),
"failed to run GetAdditionalResourcesFromAssemblies");
var path = Path.Combine (Root, "temp", $"DesignTimeBuild_{isRelease}");
using (var l = CreateDllBuilder (Path.Combine (path, lib.ProjectName))) {
using (var b = CreateApkBuilder (Path.Combine (path, proj.ProjectName))) {
l.Verbosity = LoggerVerbosity.Diagnostic;
Assert.IsTrue (l.Build (lib), "Lib1 should have built successfully");
b.Verbosity = LoggerVerbosity.Diagnostic;
b.ThrowOnBuildFailure = false;
Assert.IsTrue (b.UpdateAndroidResources (proj, parameters: new string [] { "DesignTimeBuild=true" }),
"first build failed");
Assert.IsTrue (b.LastBuildOutput.Contains ("Skipping download of "),
"failed to skip the downloading of files.");
Assert.IsTrue (b.Build (proj), "second build failed");
Assert.IsTrue (File.Exists (zipPath), $"Zip should have been downloaded to {zipPath}");
Assert.IsTrue (File.Exists (Path.Combine (extractedDir, "1", "content", "android-N", "aapt")), $"Files should have been extracted to {extractedDir}");
}
}
}

Просмотреть файл

@ -273,7 +273,8 @@ Copyright (C) 2012 Xamarin Inc. All rights reserved.
AndroidNdkDirectory="$(_AndroidNdkDirectory)"
Assemblies="@(ReferencePath);@(ReferenceDependencyPaths)"
CacheFile="$(IntermediateOutputPath)resourcepaths.cache"
Condition=" '$(DesignTimeBuild)' == 'false' Or '$(DesignTimeBuild)' == '' "
YieldDuringToolExecution="$(YieldDuringToolExecution)"
DesignTimeBuild="$(DesignTimeBuild)"
/>
</Target>

Просмотреть файл

@ -264,6 +264,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
<_AndroidSequencePointsMode Condition=" '$(MonoSymbolArchive)' == 'True' And '$(AndroidUseDebugRuntime)' == 'False' And '$(_AndroidSequencePointsMode)' == ''">Normal</_AndroidSequencePointsMode>
<_AndroidSequencePointsMode Condition=" '$(_AndroidSequencePointsMode)' == ''">None</_AndroidSequencePointsMode>
<_InstantRunEnabled Condition=" '$(_InstantRunEnabled)' == '' ">False</_InstantRunEnabled>
<_AndroidBuildPropertiesCache>$(IntermediateOutputPath)build.props</_AndroidBuildPropertiesCache>
</PropertyGroup>
@ -377,7 +378,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
</Target>
<Target Name="_BuildAdditionalResourcesCache"
Inputs="@(ReferencePath);@(ReferenceDependencyPaths);$(MSBuildProjectFullPath);$(NugetPackagesConfig)"
Inputs="@(ReferencePath);@(ReferenceDependencyPaths);$(MSBuildProjectFullPath);$(NugetPackagesConfig);$(_AndroidBuildPropertiesCache)"
Outputs="$(_AndroidResourcePathsCache)"
DependsOnTargets="$(_BeforeBuildAdditionalResourcesCache)"
>
@ -387,7 +388,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
Assemblies="@(ReferencePath);@(ReferenceDependencyPaths)"
CacheFile="$(_AndroidResourcePathsCache)"
YieldDuringToolExecution="$(YieldDuringToolExecution)"
Condition=" '$(DesignTimeBuild)' == 'false' Or '$(DesignTimeBuild)' == '' "
DesignTimeBuild="$(DesignTimeBuild)"
/>
</Target>
@ -967,7 +968,6 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidLintConfigFile>$(IntermediateOutputPath)lint.xml</_AndroidLintConfigFile>
<_AndroidResourceDesignerFile Condition=" '$(AndroidUseIntermediateDesignerFile)' == 'True' ">$(IntermediateOutputPath)$(_AndroidResourceDesigner)</_AndroidResourceDesignerFile>
<_AndroidResourceDesignerFile Condition=" '$(AndroidUseIntermediateDesignerFile)' != 'True' ">$(AndroidResgenFile)</_AndroidResourceDesignerFile>
<_AndroidBuildPropertiesCache>$(IntermediateOutputPath)build.props</_AndroidBuildPropertiesCache>
<_AndroidStaticResourcesFlag>$(IntermediateOutputPath)static.flag</_AndroidStaticResourcesFlag>
<_AndroidResourcesCacheFile>$(IntermediateOutputPath)mergeresources.cache</_AndroidResourcesCacheFile>
</PropertyGroup>
@ -994,6 +994,7 @@ because xbuild doesn't support framework reference assemblies.
<_PropertyCacheItems Include="TargetFrameworkVersion=$(TargetFrameworkVersion)" />
<_PropertyCacheItems Include="AndroidCreatePackagePerAbi=$(AndroidCreatePackagePerAbi)" />
<_PropertyCacheItems Include="OS=$(OS)" />
<_PropertyCacheItems Include="DesignTimeBuild=$(DesignTimeBuild)" />
</ItemGroup>
<Target Name="_ReadPropertiesCache">