public static void Process(LinkerOptions options, ILogger logger, out LinkContext context) { var pipeline = CreatePipeline(options); pipeline.PrependStep(new ResolveFromAssemblyStep(options.MainAssembly)); if (options.RetainAssemblies != null) { foreach (var assembly in options.RetainAssemblies) { pipeline.PrependStep(new ResolveFromAssemblyStep(assembly)); } } context = CreateLinkContext(options, pipeline, logger); context.Resolver.AddSearchDirectory(options.OutputDirectory); Run(pipeline, context); }
static LinkContext CreateLinkContext(LinkerOptions options, Pipeline pipeline) { var context = new LinkContext(pipeline, options.Resolver); if (options.DumpDependencies) { var prepareDependenciesDump = context.Annotations.GetType().GetMethod("PrepareDependenciesDump", new Type[] {}); if (prepareDependenciesDump != null) { prepareDependenciesDump.Invoke(context.Annotations, null); } } context.LogInternalExceptions = Xamarin.Android.Tasks.MonoAndroidHelper.LogInternalExceptions; context.CoreAction = AssemblyAction.Link; context.LinkSymbols = true; context.SymbolReaderProvider = new MdbReaderProvider(); context.SymbolWriterProvider = new MdbWriterProvider(); context.OutputDirectory = options.OutputDirectory; return(context); }
static LinkContext CreateLinkContext(LinkerOptions options, Pipeline pipeline, ILogger logger) { var context = new LinkContext(pipeline, options.Resolver); if (options.DumpDependencies) { var prepareDependenciesDump = context.Annotations.GetType().GetMethod("PrepareDependenciesDump", new Type[] {}); if (prepareDependenciesDump != null) { prepareDependenciesDump.Invoke(context.Annotations, null); } } context.LogMessages = true; context.Logger = logger; context.CoreAction = AssemblyAction.Link; context.UserAction = AssemblyAction.Link; context.LinkSymbols = true; context.SymbolReaderProvider = new DefaultSymbolReaderProvider(true); context.SymbolWriterProvider = new DefaultSymbolWriterProvider(); context.OutputDirectory = options.OutputDirectory; return(context); }
static Pipeline CreatePipeline(LinkerOptions options) { var pipeline = new Pipeline(); if (options.LinkNone) { pipeline.AppendStep(new FixAbstractMethodsStep()); pipeline.AppendStep(new OutputStep()); return(pipeline); } pipeline.AppendStep(new LoadReferencesStep()); if (options.I18nAssemblies != I18nAssemblies.None) { pipeline.AppendStep(new LoadI18nAssemblies(options.I18nAssemblies)); } pipeline.AppendStep(new BlacklistStep()); foreach (var desc in options.LinkDescriptions) { pipeline.AppendStep(new ResolveFromXmlStep(new XPathDocument(desc))); } pipeline.AppendStep(new CustomizeActions(options.LinkSdkOnly, options.SkippedAssemblies)); pipeline.AppendStep(new TypeMapStep()); // monodroid tuner steps pipeline.AppendStep(new SubStepDispatcher { new ApplyPreserveAttribute(), }); pipeline.AppendStep(new SubStepDispatcher { new PreserveExportedTypes(), new RemoveSecurity(), new MarkJavaObjects(), new PreserveJavaExceptions(), new PreserveJavaTypeRegistrations(), new PreserveApplications(), new RemoveAttributes(), new PreserveDynamicTypes(), new PreserveHttpAndroidClientHandler { HttpClientHandlerType = options.HttpClientHandlerType }, new PreserveTlsProvider { TlsProvider = options.TlsProvider }, new PreserveSoapHttpClients(), new PreserveTypeConverters(), new PreserveLinqExpressions(), new PreserveRuntimeSerialization(), }); pipeline.AppendStep(new PreserveCrypto()); pipeline.AppendStep(new PreserveCode()); pipeline.AppendStep(new RemoveResources(options.I18nAssemblies)); // remove collation tables // end monodroid specific pipeline.AppendStep(new FixAbstractMethodsStep()); pipeline.AppendStep(new MonoDroidMarkStep()); pipeline.AppendStep(new SweepStep()); pipeline.AppendStep(new CleanStep()); // monodroid tuner steps if (!string.IsNullOrWhiteSpace(options.ProguardConfiguration)) { pipeline.AppendStep(new GenerateProguardConfiguration(options.ProguardConfiguration)); } pipeline.AppendStep(new StripEmbeddedLibraries()); // end monodroid specific pipeline.AppendStep(new RegenerateGuidStep()); pipeline.AppendStep(new OutputStep()); return(pipeline); }
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; }