bool Execute(DirectoryAssemblyResolver res) { // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load(Path.GetFullPath(assembly.ItemSpec)); } var resolver = new AssemblyResolver(res.ToResolverCache()); // Set up for linking var options = new LinkerOptions(); options.MainAssembly = res.GetAssembly(MainAssembly); options.OutputDirectory = Path.GetFullPath(OutputDirectory); options.LinkSdkOnly = string.Compare(LinkMode, "SdkOnly", true) == 0; options.LinkNone = string.Compare(LinkMode, "None", true) == 0; options.Resolver = resolver; options.LinkDescriptions = LinkDescriptions.Select(item => Path.GetFullPath(item.ItemSpec)).ToArray(); options.I18nAssemblies = Linker.ParseI18nAssemblies(I18nAssemblies); if (!options.LinkSdkOnly) { options.RetainAssemblies = GetRetainAssemblies(res); } options.DumpDependencies = DumpDependencies; options.HttpClientHandlerType = HttpClientHandlerType; options.TlsProvider = TlsProvider; options.PreserveJniMarshalMethods = PreserveJniMarshalMethods; var skiplist = new List <string> (); if (string.Compare(UseSharedRuntime, "true", true) == 0) { skiplist.AddRange(Profile.SharedRuntimeAssemblies.Where(a => a.EndsWith(".dll")).Select(a => Path.GetFileNameWithoutExtension(a))); } if (!string.IsNullOrWhiteSpace(LinkOnlyNewerThan) && File.Exists(LinkOnlyNewerThan)) { var newerThan = File.GetLastWriteTime(LinkOnlyNewerThan); var skipOldOnes = ResolvedAssemblies.Where(a => File.GetLastWriteTime(a.ItemSpec) < newerThan); foreach (var old in skipOldOnes) { Log.LogMessage(MBF.MessageImportance.Low, " Skip linking unchanged file: " + old.ItemSpec); } skiplist = skipOldOnes.Select(a => Path.GetFileNameWithoutExtension(a.ItemSpec)).Concat(skiplist).ToList(); } // Add LinkSkip options if (!string.IsNullOrWhiteSpace(LinkSkip)) { foreach (var assembly in LinkSkip.Split(',', ';')) { skiplist.Add(assembly); } } options.SkippedAssemblies = skiplist; if (EnableProguard) { options.ProguardConfiguration = ProguardConfiguration; } // Link! try { LinkContext link_context; Linker.Process(options, this, out link_context); var copydst = OptionalDestinationDirectory ?? OutputDirectory; foreach (var assembly in ResolvedAssemblies) { var copysrc = assembly.ItemSpec; var filename = Path.GetFileName(assembly.ItemSpec); var assemblyDestination = Path.Combine(copydst, filename); if (options.LinkNone) { if (skiplist.Any(s => Path.GetFileNameWithoutExtension(filename) == s)) { // For skipped assemblies, skip if there is existing file in the destination. // We cannot just copy the linker output from *current* run output, because // it always renew the assemblies, in *different* binary values, whereas // the dll in the OptionalDestinationDirectory must retain old and unchanged. if (File.Exists(assemblyDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(assemblyDestination, DateTime.UtcNow, Log); continue; } } else { // Prefer fixup assemblies if exists, otherwise just copy the original. copysrc = Path.Combine(OutputDirectory, filename); copysrc = File.Exists(copysrc) ? copysrc : assembly.ItemSpec; } } else if (!MonoAndroidHelper.IsForceRetainedAssembly(filename)) { continue; } if (MonoAndroidHelper.CopyIfChanged(copysrc, assemblyDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(assemblyDestination, DateTime.UtcNow, Log); } try { var mdbDestination = assemblyDestination + ".mdb"; if (MonoAndroidHelper.CopyIfChanged(assembly.ItemSpec + ".mdb", mdbDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(mdbDestination, DateTime.UtcNow, Log); } } catch (Exception) { // skip it, mdb sometimes fails to read and it's optional } var pdb = Path.ChangeExtension(copysrc, "pdb"); if (File.Exists(pdb) && Files.IsPortablePdb(pdb)) { var pdbDestination = Path.ChangeExtension(Path.Combine(copydst, filename), "pdb"); if (MonoAndroidHelper.CopyIfChanged(pdb, pdbDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(pdbDestination, DateTime.UtcNow, Log); } } } } catch (ResolutionException ex) { Diagnostic.Error(2006, ex, "Could not resolve reference to '{0}' (defined in assembly '{1}') with scope '{2}'. When the scope is different from the defining assembly, it usually means that the type is forwarded.", ex.Member, ex.Member.Module.Assembly, ex.Scope); } return(true); }
bool Execute(DirectoryAssemblyResolver resolver) { 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); } var assemblies = new HashSet <string> (); var topAssemblyReferences = new List <AssemblyDefinition> (); 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) { var assembly_path = Path.GetDirectoryName(assembly.ItemSpec); if (!resolver.SearchDirectories.Contains(assembly_path)) { resolver.SearchDirectories.Add(assembly_path); } // Add each user assembly and all referenced assemblies (recursive) var assemblyDef = resolver.Load(assembly.ItemSpec); if (assemblyDef == null) { throw new InvalidOperationException("Failed to load assembly " + assembly.ItemSpec); } if (MonoAndroidHelper.IsReferenceAssembly(assemblyDef)) { // 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) { LogError("Exception while loading assemblies: {0}", ex); return(false); } try { foreach (var assembly in topAssemblyReferences) { AddAssemblyReferences(resolver, assemblies, assembly, true); } } catch (Exception ex) { LogError("Exception while loading assemblies: {0}", ex); return(false); } // Add I18N assemblies if needed AddI18nAssemblies(resolver, assemblies); ResolvedAssemblies = assemblies.Select(a => new TaskItem(a)).ToArray(); ResolvedSymbols = assemblies.Select(a => a + ".mdb").Where(a => File.Exists(a)).Select(a => new TaskItem(a)).ToArray(); ResolvedSymbols = ResolvedSymbols.Concat( assemblies.Select(a => Path.ChangeExtension(a, "pdb")) .Where(a => File.Exists(a) && Files.IsPortablePdb(a)) .Select(a => new TaskItem(a))) .ToArray(); ResolvedFrameworkAssemblies = ResolvedAssemblies.Where(p => MonoAndroidHelper.IsFrameworkAssembly(p.ItemSpec, true)).ToArray(); ResolvedUserAssemblies = ResolvedAssemblies.Where(p => !MonoAndroidHelper.IsFrameworkAssembly(p.ItemSpec, true)).ToArray(); ResolvedDoNotPackageAttributes = do_not_package_atts.ToArray(); LogDebugTaskItems(" [Output] ResolvedAssemblies:", ResolvedAssemblies); LogDebugTaskItems(" [Output] ResolvedUserAssemblies:", ResolvedUserAssemblies); LogDebugTaskItems(" [Output] ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies); LogDebugTaskItems(" [Output] ResolvedDoNotPackageAttributes:", ResolvedDoNotPackageAttributes); return(!Log.HasLoggedErrors); }
public override bool Execute() { Log.LogDebugMessage("LinkAssemblies Task"); Log.LogDebugMessage(" UseSharedRuntime: {0}", UseSharedRuntime); Log.LogDebugMessage(" MainAssembly: {0}", MainAssembly); Log.LogDebugMessage(" OutputDirectory: {0}", OutputDirectory); Log.LogDebugMessage(" OptionalDestinationDirectory: {0}", OptionalDestinationDirectory); Log.LogDebugMessage(" I18nAssemblies: {0}", I18nAssemblies); Log.LogDebugMessage(" LinkMode: {0}", LinkMode); Log.LogDebugMessage(" LinkSkip: {0}", LinkSkip); Log.LogDebugTaskItems(" LinkDescriptions:", LinkDescriptions); Log.LogDebugTaskItems(" ResolvedAssemblies:", ResolvedAssemblies); Log.LogDebugMessage(" EnableProguard: {0}", EnableProguard); Log.LogDebugMessage(" ProguardConfiguration: {0}", ProguardConfiguration); Log.LogDebugMessage(" DumpDependencies: {0}", DumpDependencies); Log.LogDebugMessage(" LinkOnlyNewerThan: {0}", LinkOnlyNewerThan); var res = new DirectoryAssemblyResolver(Log.LogWarning, loadDebugSymbols: false); // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load(Path.GetFullPath(assembly.ItemSpec)); } var resolver = new AssemblyResolver(res.ToResolverCache()); // Set up for linking var options = new LinkerOptions(); options.MainAssembly = res.GetAssembly(MainAssembly); options.OutputDirectory = Path.GetFullPath(OutputDirectory); options.LinkSdkOnly = string.Compare(LinkMode, "SdkOnly", true) == 0; options.LinkNone = string.Compare(LinkMode, "None", true) == 0; options.Resolver = resolver; options.LinkDescriptions = LinkDescriptions.Select(item => Path.GetFullPath(item.ItemSpec)).ToArray(); options.I18nAssemblies = Linker.ParseI18nAssemblies(I18nAssemblies); if (!options.LinkSdkOnly) { options.RetainAssemblies = GetRetainAssemblies(res); } options.DumpDependencies = DumpDependencies; var skiplist = new List <string> (); if (string.Compare(UseSharedRuntime, "true", true) == 0) { skiplist.AddRange(Profile.SharedRuntimeAssemblies.Where(a => a.EndsWith(".dll")).Select(a => Path.GetFileNameWithoutExtension(a))); } if (!string.IsNullOrWhiteSpace(LinkOnlyNewerThan) && File.Exists(LinkOnlyNewerThan)) { var newerThan = File.GetLastWriteTime(LinkOnlyNewerThan); var skipOldOnes = ResolvedAssemblies.Where(a => File.GetLastWriteTime(a.ItemSpec) < newerThan); foreach (var old in skipOldOnes) { Log.LogMessage(MessageImportance.Low, " Skip linking unchanged file: " + old.ItemSpec); } skiplist = skipOldOnes.Select(a => Path.GetFileNameWithoutExtension(a.ItemSpec)).Concat(skiplist).ToList(); } // Add LinkSkip options if (!string.IsNullOrWhiteSpace(LinkSkip)) { foreach (var assembly in LinkSkip.Split(',', ';')) { skiplist.Add(assembly); } } options.SkippedAssemblies = skiplist; if (EnableProguard) { options.ProguardConfiguration = ProguardConfiguration; } // Link! try { LinkContext link_context; Linker.Process(options, out link_context); var copydst = OptionalDestinationDirectory ?? OutputDirectory; foreach (var assembly in ResolvedAssemblies) { var copysrc = assembly.ItemSpec; var filename = Path.GetFileName(assembly.ItemSpec); if (options.LinkNone) { if (skiplist.Any(s => Path.GetFileNameWithoutExtension(filename) == s)) { // For skipped assemblies, skip if there is existing file in the destination. // We cannot just copy the linker output from *current* run output, because // it always renew the assemblies, in *different* binary values, whereas // the dll in the OptionalDestinationDirectory must retain old and unchanged. if (File.Exists(Path.Combine(copydst, filename))) { continue; } copysrc = assembly.ItemSpec; } else { // Prefer fixup assemblies if exists, otherwise just copy the original. copysrc = Path.Combine(OutputDirectory, filename); copysrc = File.Exists(copysrc) ? copysrc : assembly.ItemSpec; } } else if (!MonoAndroidHelper.IsForceRetainedAssembly(filename)) { continue; } MonoAndroidHelper.CopyIfChanged(copysrc, Path.Combine(copydst, filename)); try { MonoAndroidHelper.CopyIfChanged(assembly.ItemSpec + ".mdb", Path.Combine(copydst, filename + ".mdb")); } catch (Exception) { // skip it, mdb sometimes fails to read and it's optional } } } catch (ResolutionException ex) { Diagnostic.Error(2006, ex, "Reference to metadata item '{0}' (defined in '{1}') from '{1}' could not be resolved.", ex.Member, ex.Member.Module.Assembly, ex.Scope); } return(true); }
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); foreach (var dir in ReferenceAssembliesDirectory.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { resolver.SearchDirectories.Add(dir); } var assemblies = new HashSet <string> (); var topAssemblyReferences = new List <AssemblyDefinition> (); try { foreach (var assembly in Assemblies) { var assembly_path = Path.GetDirectoryName(assembly.ItemSpec); if (!resolver.SearchDirectories.Contains(assembly_path)) { resolver.SearchDirectories.Add(assembly_path); } // Add each user assembly and all referenced assemblies (recursive) var assemblyDef = resolver.Load(assembly.ItemSpec); if (assemblyDef == null) { throw new InvalidOperationException("Failed to load assembly " + assembly.ItemSpec); } topAssemblyReferences.Add(assemblyDef); assemblies.Add(assemblyDef.MainModule.FullyQualifiedName); } } catch (Exception ex) { Log.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); return(false); } // Add I18N assemblies if needed AddI18nAssemblies(resolver, assemblies); ResolvedAssemblies = assemblies.Select(a => new TaskItem(a)).ToArray(); ResolvedSymbols = assemblies.Select(a => a + ".mdb").Where(a => File.Exists(a)).Select(a => new TaskItem(a)).ToArray(); ResolvedFrameworkAssemblies = ResolvedAssemblies.Where(p => MonoAndroidHelper.IsFrameworkAssembly(p.ItemSpec, true)).ToArray(); 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); return(!Log.HasLoggedErrors); }
bool Execute(DirectoryAssemblyResolver resolver) { Log.LogDebugMessage("ResolveAssemblies Task"); Log.LogDebugMessage(" ReferenceAssembliesDirectory: {0}", ReferenceAssembliesDirectory); Log.LogDebugMessage(" I18nAssemblies: {0}", I18nAssemblies); Log.LogDebugTaskItems(" Assemblies:", Assemblies); foreach (var dir in ReferenceAssembliesDirectory.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { resolver.SearchDirectories.Add(dir); } var assemblies = new HashSet <string>(); var topAssemblyReferences = new List <AssemblyDefinition>(); try { foreach (var assembly in Assemblies) { var assembly_path = Path.GetDirectoryName(assembly.ItemSpec); if (!resolver.SearchDirectories.Contains(assembly_path)) { resolver.SearchDirectories.Add(assembly_path); } // Add each user assembly and all referenced assemblies (recursive) var assemblyDef = resolver.Load(assembly.ItemSpec); if (assemblyDef == null) { throw new InvalidOperationException("Failed to load assembly " + assembly.ItemSpec); } topAssemblyReferences.Add(assemblyDef); assemblies.Add(Path.GetFullPath(assemblyDef.MainModule.FullyQualifiedName)); } } catch (Exception ex) { Log.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); return(false); } // Add I18N assemblies if needed AddI18nAssemblies(resolver, assemblies); ResolvedAssemblies = assemblies.Select(a => new TaskItem(a)).ToArray(); // mdb files retain the .dll/.exe, e.g. mscorlib.dll.mdb ResolvedMdbFiles = assemblies.Select(a => $"{a}.mdb").Where(File.Exists).Select(a => new TaskItem(a)).ToArray(); // pdb files have the .dll/.exe removed, e.g. mscorlib.pdb ResolvedPdbFiles = assemblies.Select(a => a.Substring(0, a.LastIndexOf('.'))).Select(a => $"{a}.pdb") .Where(File.Exists).Select(a => new TaskItem(a)).ToArray(); ResolvedConfigFiles = assemblies.Select(a => $"{a}.config").Where(File.Exists).Select(a => new TaskItem(a)).ToArray(); ResolvedFrameworkAssemblies = ResolvedAssemblies.Where(p => IsFrameworkAssembly(p.ItemSpec, true)).ToArray(); ResolvedUserAssemblies = ResolvedAssemblies.Where(p => !IsFrameworkAssembly(p.ItemSpec, true)).ToArray(); Log.LogDebugTaskItems(" [Output] ResolvedAssemblies:", ResolvedAssemblies); Log.LogDebugTaskItems(" [Output] ResolvedUserAssemblies:", ResolvedUserAssemblies); Log.LogDebugTaskItems(" [Output] ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies); Log.LogDebugTaskItems(" [Output] ResolvedMdbFiles:", ResolvedMdbFiles); Log.LogDebugTaskItems(" [Output] ResolvedPdbFiles:", ResolvedPdbFiles); Log.LogDebugTaskItems(" [Output] ResolvedConfigFiles:", ResolvedConfigFiles); return(!Log.HasLoggedErrors); }