Esempio n. 1
0
        public void ManagedLink()
        {
            var cache_path = Path.Combine (ArchDirectory, "linked-assemblies.txt");

            foreach (var a in Assemblies)
                a.CopyToDirectory (LinkDirectory, false, check_case: true);

            // Check if we can use a previous link result.
            if (!Driver.Force) {
                var input = new List<string> ();
                var output = new List<string> ();
                var cached_output = new List<string> ();

                if (File.Exists (cache_path)) {
                    cached_output.AddRange (File.ReadAllLines (cache_path));

                    var cached_loaded = new HashSet<string> ();
                    // Only add the previously linked assemblies (and their satellites) as the input/output assemblies.
                    // Do not add assemblies which the linker process removed.
                    foreach (var a in Assemblies) {
                        if (!cached_output.Contains (a.FullPath))
                            continue;
                        cached_loaded.Add (a.FullPath);
                        input.Add (a.FullPath);
                        output.Add (Path.Combine (PreBuildDirectory, a.FileName));
                        if (a.Satellites != null) {
                            foreach (var s in a.Satellites) {
                                input.Add (s);
                                output.Add (Path.Combine (PreBuildDirectory, Path.GetFileName (Path.GetDirectoryName (s)), Path.GetFileName (s)));
                            }
                        }
                    }

                    // The linker might have added assemblies that weren't specified/reachable
                    // from the command line arguments (such as I18N assemblies). Those are not
                    // in the Assemblies list at this point (since we haven't run the linker yet)
                    // so make sure we take those into account as well.
                    var not_loaded = cached_output.Except (cached_loaded);
                    foreach (var path in not_loaded) {
                        input.Add (path);
                        output.Add (Path.Combine (PreBuildDirectory, Path.GetFileName (path)));
                    }

                    // Include mtouch here too?
                    // input.Add (Path.Combine (MTouch.MonoTouchDirectory, "usr", "bin", "mtouch"));

                    if (Application.IsUptodate (input, output)) {
                        cached_link = true;
                        for (int i = Assemblies.Count - 1; i >= 0; i--) {
                            var a = Assemblies [i];
                            if (!cached_output.Contains (a.FullPath)) {
                                Assemblies.RemoveAt (i);
                                continue;
                            }
                            // Load the cached assembly
                            a.LoadAssembly (Path.Combine (PreBuildDirectory, a.FileName));
                            Driver.Log (3, "Target '{0}' is up-to-date.", a.FullPath);
                        }

                        foreach (var path in not_loaded) {
                            var a = new Assembly (this, path);
                            a.LoadAssembly (Path.Combine (PreBuildDirectory, a.FileName));
                            Assemblies.Add (a);
                        }

                        Driver.Watch ("Cached assemblies reloaded", 1);

                        return;
                    }
                }
            }

            // Load the assemblies into memory.
            foreach (var a in Assemblies)
                a.LoadAssembly (a.FullPath);

            var assemblies = new List<string> ();
            foreach (var a in Assemblies)
                assemblies.Add (a.FullPath);
            var linked_assemblies = new List<string> (assemblies);

            LinkAssemblies (App.RootAssembly, ref linked_assemblies, PreBuildDirectory, out LinkContext);

            // Remove assemblies that were linked away
            var removed = new HashSet<string> (assemblies);
            removed.ExceptWith (linked_assemblies);

            foreach (var assembly in removed) {
                for (int i = Assemblies.Count - 1; i >= 0; i--) {
                    var ad = Assemblies [i];
                    if (assembly != ad.FullPath)
                        continue;

                    Assemblies.RemoveAt (i);
                }
            }

            // anything added by the linker will have it's original path
            var added = new HashSet<string> ();
            foreach (var assembly in linked_assemblies)
                added.Add (Path.GetFileName (assembly));
            var original = new HashSet<string> ();
            foreach (var assembly in assemblies)
                original.Add (Path.GetFileName (assembly));
            added.ExceptWith (original);

            foreach (var assembly in added) {
                // the linker already copied the assemblies (linked or not) into the output directory
                // and we must NOT overwrite the linker work with an original (unlinked) assembly
                string path = Path.Combine (PreBuildDirectory, assembly);
                var ad = ManifestResolver.Load (path);
                var a = new Assembly (this, ad);
                a.CopyToDirectory (PreBuildDirectory);
                Assemblies.Add (a);
            }

            assemblies = linked_assemblies;

            // Make the assemblies point to the right path.
            foreach (var a in Assemblies)
                a.FullPath = Path.Combine (PreBuildDirectory, a.FileName);

            File.WriteAllText (cache_path, string.Join ("\n", linked_assemblies));
        }
Esempio n. 2
0
        public void ManagedLink()
        {
            var cache_path = Path.Combine(ArchDirectory, "linked-assemblies.txt");

            foreach (var a in Assemblies)
            {
                a.CopyToDirectory(LinkDirectory, false, check_case: true);
            }

            // Check if we can use a previous link result.
            if (!Driver.Force)
            {
                var input         = new List <string> ();
                var output        = new List <string> ();
                var cached_output = new List <string> ();

                if (File.Exists(cache_path))
                {
                    cached_output.AddRange(File.ReadAllLines(cache_path));

                    var cached_loaded = new HashSet <string> ();
                    // Only add the previously linked assemblies (and their satellites) as the input/output assemblies.
                    // Do not add assemblies which the linker process removed.
                    foreach (var a in Assemblies)
                    {
                        if (!cached_output.Contains(a.FullPath))
                        {
                            continue;
                        }
                        cached_loaded.Add(a.FullPath);
                        input.Add(a.FullPath);
                        output.Add(Path.Combine(PreBuildDirectory, a.FileName));
                        if (File.Exists(a.FullPath + ".mdb"))
                        {
                            // Debug files can change without the assemblies themselves changing
                            // This should also invalidate the cached linker results, since the non-linked mdbs can't be copied.
                            input.Add(a.FullPath + ".mdb");
                            output.Add(Path.Combine(PreBuildDirectory, a.FileName) + ".mdb");
                        }

                        if (a.Satellites != null)
                        {
                            foreach (var s in a.Satellites)
                            {
                                input.Add(s);
                                output.Add(Path.Combine(PreBuildDirectory, Path.GetFileName(Path.GetDirectoryName(s)), Path.GetFileName(s)));
                                // No need to copy satellite mdb files, satellites are resource-only assemblies.
                            }
                        }
                    }

                    // The linker might have added assemblies that weren't specified/reachable
                    // from the command line arguments (such as I18N assemblies). Those are not
                    // in the Assemblies list at this point (since we haven't run the linker yet)
                    // so make sure we take those into account as well.
                    var not_loaded = cached_output.Except(cached_loaded);
                    foreach (var path in not_loaded)
                    {
                        input.Add(path);
                        output.Add(Path.Combine(PreBuildDirectory, Path.GetFileName(path)));
                    }

                    // Include mtouch here too?
                    // input.Add (Path.Combine (MTouch.MonoTouchDirectory, "usr", "bin", "mtouch"));

                    if (Application.IsUptodate(input, output))
                    {
                        cached_link = true;
                        for (int i = Assemblies.Count - 1; i >= 0; i--)
                        {
                            var a = Assemblies [i];
                            if (!cached_output.Contains(a.FullPath))
                            {
                                Assemblies.RemoveAt(i);
                                continue;
                            }
                            // Load the cached assembly
                            a.LoadAssembly(Path.Combine(PreBuildDirectory, a.FileName));
                            Driver.Log(3, "Target '{0}' is up-to-date.", a.FullPath);
                        }

                        foreach (var path in not_loaded)
                        {
                            var a = new Assembly(this, path);
                            a.LoadAssembly(Path.Combine(PreBuildDirectory, a.FileName));
                            Assemblies.Add(a);
                        }

                        Driver.Watch("Cached assemblies reloaded", 1);
                        Driver.Log("Cached assemblies reloaded.");

                        return;
                    }
                }
            }

            // Load the assemblies into memory.
            foreach (var a in Assemblies)
            {
                a.LoadAssembly(a.FullPath);
            }

            var assemblies = new List <string> ();

            foreach (var a in Assemblies)
            {
                assemblies.Add(a.FullPath);
            }
            var linked_assemblies = new List <string> (assemblies);

            LinkAssemblies(App.RootAssembly, ref linked_assemblies, PreBuildDirectory, out LinkContext);

            // Remove assemblies that were linked away
            var removed = new HashSet <string> (assemblies);

            removed.ExceptWith(linked_assemblies);

            foreach (var assembly in removed)
            {
                for (int i = Assemblies.Count - 1; i >= 0; i--)
                {
                    var ad = Assemblies [i];
                    if (assembly != ad.FullPath)
                    {
                        continue;
                    }

                    Assemblies.RemoveAt(i);
                }
            }

            // anything added by the linker will have it's original path
            var added = new HashSet <string> ();

            foreach (var assembly in linked_assemblies)
            {
                added.Add(Path.GetFileName(assembly));
            }
            var original = new HashSet <string> ();

            foreach (var assembly in assemblies)
            {
                original.Add(Path.GetFileName(assembly));
            }
            added.ExceptWith(original);

            foreach (var assembly in added)
            {
                // the linker already copied the assemblies (linked or not) into the output directory
                // and we must NOT overwrite the linker work with an original (unlinked) assembly
                string path = Path.Combine(PreBuildDirectory, assembly);
                var    ad   = ManifestResolver.Load(path);
                var    a    = new Assembly(this, ad);
                a.CopyToDirectory(PreBuildDirectory);
                Assemblies.Add(a);
            }

            assemblies = linked_assemblies;

            // Make the assemblies point to the right path.
            foreach (var a in Assemblies)
            {
                a.FullPath = Path.Combine(PreBuildDirectory, a.FileName);
                // The linker can copy files (and not update timestamps), and then we run into this sequence:
                // * We run the linker, nothing changes, so the linker copies
                //   all files to the PreBuild directory, with timestamps intact.
                // * This means that for instance SDK assemblies will have the original
                //   timestamp from their installed location, and the exe will have the
                //   timestamp of when it was built.
                // * mtouch is executed again for some reason, and none of the input assemblies changed.
                //   We'll still re-execute the linker, because at least one of the input assemblies
                //   (the .exe) has a newer timestamp than some of the assemblies in the PreBuild directory.
                // So here we manually touch all the assemblies we have, to make sure their timestamps
                // change (this is us saying 'we know these files are up-to-date at this point in time').
                Driver.Touch(a.GetRelatedFiles());
            }

            File.WriteAllText(cache_path, string.Join("\n", linked_assemblies));
        }
Esempio n. 3
0
        public void ManagedLink()
        {
            var cache_path = Path.Combine(ArchDirectory, "linked-assemblies.txt");

            foreach (var a in Assemblies)
            {
                a.CopyToDirectory(LinkDirectory, false, check_case: true);
            }

            // Check if we can use a previous link result.
            if (!Driver.Force)
            {
                var input         = new List <string> ();
                var output        = new List <string> ();
                var cached_output = new List <string> ();

                if (File.Exists(cache_path))
                {
                    cached_output.AddRange(File.ReadAllLines(cache_path));

                    var cached_loaded = new HashSet <string> ();
                    // Only add the previously linked assemblies (and their satellites) as the input/output assemblies.
                    // Do not add assemblies which the linker process removed.
                    foreach (var a in Assemblies)
                    {
                        if (!cached_output.Contains(a.FullPath))
                        {
                            continue;
                        }
                        cached_loaded.Add(a.FullPath);
                        input.Add(a.FullPath);
                        output.Add(Path.Combine(PreBuildDirectory, a.FileName));
                        if (a.Satellites != null)
                        {
                            foreach (var s in a.Satellites)
                            {
                                input.Add(s);
                                output.Add(Path.Combine(PreBuildDirectory, Path.GetFileName(Path.GetDirectoryName(s)), Path.GetFileName(s)));
                            }
                        }
                    }

                    // The linker might have added assemblies that weren't specified/reachable
                    // from the command line arguments (such as I18N assemblies). Those are not
                    // in the Assemblies list at this point (since we haven't run the linker yet)
                    // so make sure we take those into account as well.
                    var not_loaded = cached_output.Except(cached_loaded);
                    foreach (var path in not_loaded)
                    {
                        input.Add(path);
                        output.Add(Path.Combine(PreBuildDirectory, Path.GetFileName(path)));
                    }

                    // Include mtouch here too?
                    // input.Add (Path.Combine (MTouch.MonoTouchDirectory, "usr", "bin", "mtouch"));

                    if (Application.IsUptodate(input, output))
                    {
                        cached_link = true;
                        for (int i = Assemblies.Count - 1; i >= 0; i--)
                        {
                            var a = Assemblies [i];
                            if (!cached_output.Contains(a.FullPath))
                            {
                                Assemblies.RemoveAt(i);
                                continue;
                            }
                            // Load the cached assembly
                            a.LoadAssembly(Path.Combine(PreBuildDirectory, a.FileName));
                            Driver.Log(3, "Target '{0}' is up-to-date.", a.FullPath);
                        }

                        foreach (var path in not_loaded)
                        {
                            var a = new Assembly(this, path);
                            a.LoadAssembly(Path.Combine(PreBuildDirectory, a.FileName));
                            Assemblies.Add(a);
                        }

                        Driver.Watch("Cached assemblies reloaded", 1);

                        return;
                    }
                }
            }

            // Load the assemblies into memory.
            foreach (var a in Assemblies)
            {
                a.LoadAssembly(a.FullPath);
            }

            var assemblies = new List <string> ();

            foreach (var a in Assemblies)
            {
                assemblies.Add(a.FullPath);
            }
            var linked_assemblies = new List <string> (assemblies);

            LinkAssemblies(App.RootAssembly, ref linked_assemblies, PreBuildDirectory, out LinkContext);

            // Remove assemblies that were linked away
            var removed = new HashSet <string> (assemblies);

            removed.ExceptWith(linked_assemblies);

            foreach (var assembly in removed)
            {
                for (int i = Assemblies.Count - 1; i >= 0; i--)
                {
                    var ad = Assemblies [i];
                    if (assembly != ad.FullPath)
                    {
                        continue;
                    }

                    Assemblies.RemoveAt(i);
                }
            }

            // anything added by the linker will have it's original path
            var added = new HashSet <string> ();

            foreach (var assembly in linked_assemblies)
            {
                added.Add(Path.GetFileName(assembly));
            }
            var original = new HashSet <string> ();

            foreach (var assembly in assemblies)
            {
                original.Add(Path.GetFileName(assembly));
            }
            added.ExceptWith(original);

            foreach (var assembly in added)
            {
                // the linker already copied the assemblies (linked or not) into the output directory
                // and we must NOT overwrite the linker work with an original (unlinked) assembly
                string path = Path.Combine(PreBuildDirectory, assembly);
                var    ad   = ManifestResolver.Load(path);
                var    a    = new Assembly(this, ad);
                a.CopyToDirectory(PreBuildDirectory);
                Assemblies.Add(a);
            }

            assemblies = linked_assemblies;

            // Make the assemblies point to the right path.
            foreach (var a in Assemblies)
            {
                a.FullPath = Path.Combine(PreBuildDirectory, a.FileName);
            }

            File.WriteAllText(cache_path, string.Join("\n", linked_assemblies));
        }