예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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;
        }