diff --git a/src/Xamarin.Android.Build.Tasks.tpnitems b/src/Xamarin.Android.Build.Tasks.tpnitems index a085e3423e3..61c2f7350ce 100644 --- a/src/Xamarin.Android.Build.Tasks.tpnitems +++ b/src/Xamarin.Android.Build.Tasks.tpnitems @@ -78,5 +78,47 @@ https://github.com/IronyProject/Irony + + + The MIT License (MIT) + + Copyright (c) 2007 James Newton-King + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + associated documentation files (the "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + https://github.com/JamesNK/Newtonsoft.Json + + + + Copyright (c) .NET Foundation and Contributors. + + All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + these files except in compliance with the License. You may obtain a copy of the + License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed + under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. See the License for the + specific language governing permissions and limitations under the License. + + https://github.com/NuGet/NuGet.Client + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs index 45ddd4d28bf..cf9c352fa2a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs @@ -10,12 +10,15 @@ using MonoDroid.Tuner; using System.IO; using Xamarin.Android.Tools; +using NuGet.Common; +using NuGet.Frameworks; +using NuGet.ProjectModel; using Java.Interop.Tools.Cecil; namespace Xamarin.Android.Tasks { - public class ResolveAssemblies : Task + public class ResolveAssemblies : AsyncTask { // The user's assemblies to package [Required] @@ -24,6 +27,12 @@ public class ResolveAssemblies : Task [Required] public string ReferenceAssembliesDirectory { get; set; } + public string ProjectAssetFile { get; set; } + + public string TargetMoniker { get; set; } + + public string NuGetPackageRoot { get; set; } + public string I18nAssemblies { get; set; } public string LinkMode { get; set; } @@ -45,18 +54,30 @@ public class ResolveAssemblies : Task public override bool Execute () { - using (var resolver = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) { - return Execute (resolver); - } + System.Threading.Tasks.Task.Run (() => { + using (var resolver = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) { + return Execute (resolver); + } + }, Token).ContinueWith ((t) => { + if (t.Exception != null) { + var ex = t.Exception.GetBaseException (); + LogError (ex.Message + Environment.NewLine + ex.StackTrace); + } + Complete (); + }); + return base.Execute (); } bool Execute (DirectoryAssemblyResolver resolver) { - Log.LogDebugMessage ("ResolveAssemblies Task"); - Log.LogDebugMessage (" ReferenceAssembliesDirectory: {0}", ReferenceAssembliesDirectory); - Log.LogDebugMessage (" I18nAssemblies: {0}", I18nAssemblies); - Log.LogDebugMessage (" LinkMode: {0}", LinkMode); - Log.LogDebugTaskItems (" Assemblies:", Assemblies); + LogDebugMessage ("ResolveAssemblies Task"); + LogDebugMessage (" ReferenceAssembliesDirectory: {0}", ReferenceAssembliesDirectory); + LogDebugMessage (" I18nAssemblies: {0}", I18nAssemblies); + LogDebugMessage (" LinkMode: {0}", LinkMode); + LogDebugTaskItems (" Assemblies:", Assemblies); + LogDebugMessage (" ProjectAssetFile: {0}", ProjectAssetFile); + LogDebugMessage (" NuGetPackageRoot: {0}", NuGetPackageRoot); + LogDebugMessage (" TargetMoniker: {0}", TargetMoniker); foreach (var dir in ReferenceAssembliesDirectory.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) resolver.SearchDirectories.Add (dir); @@ -64,6 +85,14 @@ bool Execute (DirectoryAssemblyResolver resolver) var assemblies = new HashSet (); var topAssemblyReferences = new List (); + var logger = new NuGetLogger((s) => { + LogDebugMessage ("{0}", s); + }); + + LockFile lockFile = null; + if (!string.IsNullOrEmpty (ProjectAssetFile) && File.Exists (ProjectAssetFile)) { + lockFile = LockFileUtilities.GetLockFile (ProjectAssetFile, logger); + } try { foreach (var assembly in Assemblies) { @@ -77,21 +106,26 @@ bool Execute (DirectoryAssemblyResolver resolver) if (assemblyDef == null) throw new InvalidOperationException ("Failed to load assembly " + assembly.ItemSpec); if (MonoAndroidHelper.IsReferenceAssembly (assemblyDef)) { - Log.LogWarning ($"Ignoring {assembly_path} as it is a Reference Assembly"); - continue; + // Resolve "runtime" library + if (lockFile != null) + assemblyDef = ResolveRuntimeAssemblyForReferenceAssembly (lockFile, resolver, assemblyDef.Name); + if (lockFile == null || assemblyDef == null) { + LogWarning ($"Ignoring {assembly_path} as it is a Reference Assembly"); + continue; + } } topAssemblyReferences.Add (assemblyDef); assemblies.Add (Path.GetFullPath (assemblyDef.MainModule.FullyQualifiedName)); } } catch (Exception ex) { - Log.LogError ("Exception while loading assemblies: {0}", ex); + LogError ("Exception while loading assemblies: {0}", ex); return false; } try { foreach (var assembly in topAssemblyReferences) AddAssemblyReferences (resolver, assemblies, assembly, true); } catch (Exception ex) { - Log.LogError ("Exception while loading assemblies: {0}", ex); + LogError ("Exception while loading assemblies: {0}", ex); return false; } @@ -109,10 +143,10 @@ bool Execute (DirectoryAssemblyResolver resolver) ResolvedUserAssemblies = ResolvedAssemblies.Where (p => !MonoAndroidHelper.IsFrameworkAssembly (p.ItemSpec, true)).ToArray (); ResolvedDoNotPackageAttributes = do_not_package_atts.ToArray (); - Log.LogDebugTaskItems (" [Output] ResolvedAssemblies:", ResolvedAssemblies); - Log.LogDebugTaskItems (" [Output] ResolvedUserAssemblies:", ResolvedUserAssemblies); - Log.LogDebugTaskItems (" [Output] ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies); - Log.LogDebugTaskItems (" [Output] ResolvedDoNotPackageAttributes:", ResolvedDoNotPackageAttributes); + LogDebugTaskItems (" [Output] ResolvedAssemblies:", ResolvedAssemblies); + LogDebugTaskItems (" [Output] ResolvedUserAssemblies:", ResolvedUserAssemblies); + LogDebugTaskItems (" [Output] ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies); + LogDebugTaskItems (" [Output] ResolvedDoNotPackageAttributes:", ResolvedDoNotPackageAttributes); return !Log.HasLoggedErrors; } @@ -120,6 +154,35 @@ bool Execute (DirectoryAssemblyResolver resolver) readonly List do_not_package_atts = new List (); int indent = 2; + AssemblyDefinition ResolveRuntimeAssemblyForReferenceAssembly (LockFile lockFile, DirectoryAssemblyResolver resolver, AssemblyNameDefinition assemblyNameDefinition) + { + if (string.IsNullOrEmpty(TargetMoniker) || string.IsNullOrEmpty (NuGetPackageRoot) || !Directory.Exists (NuGetPackageRoot)) + return null; + + var framework = NuGetFramework.Parse (TargetMoniker); + if (framework == null) { + LogWarning ($"Could not parse '{TargetMoniker}'"); + return null; + } + var target = lockFile.GetTarget (framework, string.Empty); + if (target == null) { + LogWarning ($"Could not resolve target for '{TargetMoniker}'"); + return null; + } + var libraryPath = lockFile.Libraries.FirstOrDefault (x => x.Name == assemblyNameDefinition.Name); + if (libraryPath == null) + return null; + var library = target.Libraries.FirstOrDefault (x => x.Name == assemblyNameDefinition.Name); + if (library == null) + return null; + var runtime = library.RuntimeAssemblies.FirstOrDefault (); + if (runtime == null) + return null; + var path = Path.Combine (NuGetPackageRoot, libraryPath.Path, runtime.Path); + LogDebugMessage ($"Attempting to load {path}"); + return resolver.Load (path, forceLoad: true); + } + void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection assemblies, AssemblyDefinition assembly, bool topLevel) { var fqname = assembly.MainModule.FullyQualifiedName; @@ -132,11 +195,11 @@ void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection a.AttributeType.FullName == "Java.Interop.DoNotPackageAttribute")) { string file = (string) att.ConstructorArguments.First ().Value; if (string.IsNullOrWhiteSpace (file)) - Log.LogError ("In referenced assembly {0}, Java.Interop.DoNotPackageAttribute requires non-null file name.", assembly.FullName); + LogError ("In referenced assembly {0}, Java.Interop.DoNotPackageAttribute requires non-null file name.", assembly.FullName); do_not_package_atts.Add (Path.GetFileName (file)); } - Log.LogMessage (MessageImportance.Low, "{0}Adding assembly reference for {1}, recursively...", new string (' ', indent), assembly.Name); + LogMessage ("{0}Adding assembly reference for {1}, recursively...", new string (' ', indent), assembly.Name); indent += 2; // Add this assembly if (!topLevel && assemblies.All (a => new AssemblyNameDefinition (a, null).Name != assembly.Name.Name)) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index e77fda6c915..19f5704550e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -280,9 +280,14 @@ public partial class App : Application public App() { - JsonConvert.DeserializeObject(""test""); - package = Package.Open (""""); + try { + JsonConvert.DeserializeObject(""test""); + package = Package.Open (""""); + } catch { + } InitializeComponent(); + + MainPage = new ContentPage (); } protected override void OnStart() @@ -337,6 +342,29 @@ protected override void OnResume() KnownPackages.XamarinForms_2_3_4_231, } }; + app.MainActivity = @"using System; +using Android.App; +using Android.Content; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Android.OS; +using XamFormsSample; + +namespace App1 +{ + [Activity (Label = ""App1"", MainLauncher = true, Icon = ""@drawable/icon"")] + public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + global::Xamarin.Forms.Forms.Init (this, bundle); + + LoadApplication (new App ()); + } + } + }"; app.SetProperty (KnownProperties.AndroidSupportedAbis, "x86;armeabi-v7a"); var expectedFiles = new string [] { "Java.Interop.dll", @@ -346,6 +374,7 @@ protected override void OnResume() "System.dll", "System.Runtime.Serialization.dll", "System.IO.Packaging.dll", + "System.IO.Compression.dll", "Mono.Android.Export.dll", "App1.dll", "FormsViewGroup.dll", diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj index cd5bbf7b8bc..452cf421100 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj @@ -7,7 +7,7 @@ Library Xamarin.Android.Build.Tests Xamarin.Android.Build.Tests - v4.5.1 + v4.6.2 diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/NuGetLogger.cs b/src/Xamarin.Android.Build.Tasks/Utilities/NuGetLogger.cs new file mode 100644 index 00000000000..873d6811c35 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/NuGetLogger.cs @@ -0,0 +1,34 @@ +using System; +using NuGet.Common; +using Microsoft.Build.Utilities; +using TPL = System.Threading.Tasks; + +namespace Xamarin.Android.Tasks { + + class NuGetLogger : LoggerBase { + Action log; + + public NuGetLogger (Action log) + { + this.log = log; + } + + public override void Log (ILogMessage message) { + log (message.Message); + } + + public override void Log (LogLevel level, string data) { + log (data); + } + + public override TPL.Task LogAsync (ILogMessage message) { + Log (message); + return TPL.Task.FromResult(0); + } + + public override TPL.Task LogAsync (LogLevel level, string data) { + Log (level, data); + return TPL.Task.FromResult(0); + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index a7da157e62e..9193e809861 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -9,7 +9,7 @@ Xamarin.Android.Tasks Xamarin.Android.Build.Tasks 512 - v4.5.1 + v4.6.2 2.0 @@ -51,6 +51,53 @@ ..\..\packages\FSharp.Core.3.1.2.5\lib\net40\FSharp.Core.dll + + ..\..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\..\packages\NuGet.Frameworks.4.6.0\lib\net46\NuGet.Frameworks.dll + + + ..\..\packages\NuGet.Common.4.6.0\lib\net46\NuGet.Common.dll + + + + ..\..\packages\NuGet.Configuration.4.6.0\lib\net46\NuGet.Configuration.dll + + + + ..\..\packages\NuGet.Versioning.4.6.0\lib\net46\NuGet.Versioning.dll + + + ..\..\packages\NuGet.LibraryModel.4.6.0\lib\net46\NuGet.LibraryModel.dll + + + ..\..\packages\NuGet.Packaging.Core.4.6.0\lib\net46\NuGet.Packaging.Core.dll + + + ..\..\packages\NuGet.Packaging.4.6.0\lib\net46\NuGet.Packaging.dll + + + ..\..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + + + + + ..\..\packages\System.Runtime.InteropServices.4.3.0\lib\net462\System.Runtime.InteropServices.dll + + + ..\..\packages\NuGet.Protocol.4.6.0\lib\net46\NuGet.Protocol.dll + + + + + + + ..\..\packages\NuGet.DependencyResolver.Core.4.6.0\lib\net46\NuGet.DependencyResolver.Core.dll + + + ..\..\packages\NuGet.ProjectModel.4.6.0\lib\net46\NuGet.ProjectModel.dll + @@ -507,6 +554,7 @@ + desugar_deploy.jar PreserveNewest diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index cf3a4495ca1..283a0ec82f0 100755 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1591,6 +1591,9 @@ because xbuild doesn't support framework reference assemblies. Assemblies="@(FilteredAssemblies)" I18nAssemblies="$(MandroidI18n)" LinkMode="$(AndroidLinkMode)" + ProjectAssetFile="$(ProjectLockFile)" + NuGetPackageRoot="$(NuGetPackageRoot)" + TargetMoniker="$(NuGetTargetMoniker)" ReferenceAssembliesDirectory="$(TargetFrameworkDirectory)"> diff --git a/src/Xamarin.Android.Build.Tasks/packages.config b/src/Xamarin.Android.Build.Tasks/packages.config index 25cedecb4d5..78c0fa586fb 100644 --- a/src/Xamarin.Android.Build.Tasks/packages.config +++ b/src/Xamarin.Android.Build.Tasks/packages.config @@ -3,4 +3,17 @@ + + + + + + + + + + + + + \ No newline at end of file