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)); }
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)); }
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)); }