PageRenderTime 1293ms CodeModel.GetById 28ms RepoModel.GetById 2ms app.codeStats 0ms

/src/sys/dotnet/fanx/tools/Tool.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 314 lines | 228 code | 33 blank | 53 comment | 23 complexity | 25c7bbdb6ae45ff376b454526d0edd63 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2006, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 4 Jan 06 Andy Frank Creation
  7. //
  8. using System;
  9. using System.Collections;
  10. using System.IO;
  11. using System.Reflection;
  12. using System.Text;
  13. using Depend = Fan.Sys.Depend;
  14. using Err = Fan.Sys.Err;
  15. using List = Fan.Sys.List;
  16. using Pod = Fan.Sys.Pod;
  17. using Sys = Fan.Sys.Sys;
  18. using SysProps = Fan.Sys.SysProps;
  19. using Fanx.Emit;
  20. using Fanx.Fcode;
  21. using Fanx.Util;
  22. namespace Fanx.Tools
  23. {
  24. public abstract class Tool
  25. {
  26. //////////////////////////////////////////////////////////////////////////
  27. // Fantom Assembly Loading
  28. //////////////////////////////////////////////////////////////////////////
  29. /// <summary>
  30. /// Register the assembly resolver.
  31. /// </summary>
  32. protected Tool()
  33. {
  34. AppDomain domain = AppDomain.CurrentDomain;
  35. domain.AssemblyResolve += new ResolveEventHandler(resolveAssembly);
  36. }
  37. /// <summary>
  38. /// Get the assembly name from the specified fullName. The fullName
  39. /// has the following format:
  40. ///
  41. /// <name>, Version=<major.minor.build.patch>, Culture=<...>, PublicKeyToken=<...>
  42. ///
  43. /// </summary>
  44. public static string getAssemblyName(string fullName)
  45. {
  46. int sep = fullName.IndexOf(',');
  47. if (sep == -1)
  48. return fullName;
  49. else
  50. return fullName.Substring(0, sep);
  51. }
  52. /// <summary>
  53. /// Resolve an assembly that cannot be found in
  54. /// the current AppDomain.
  55. /// </summary>
  56. public static Assembly resolveAssembly(object sender, ResolveEventArgs args)
  57. {
  58. string asmName = getAssemblyName(args.Name);
  59. AppDomain domain = AppDomain.CurrentDomain;
  60. // check if already loaded
  61. Assembly[] current = domain.GetAssemblies();
  62. for (int i=0; i<current.Length; i++)
  63. if (asmName == current[i].GetName().Name)
  64. return current[i];
  65. // otherwise load it from disk
  66. string libDir = FileUtil.combine(Sys.m_homeDir, "lib", "dotnet");
  67. string dll = FileUtil.combine(libDir, asmName + ".dll");
  68. FileInfo f = new FileInfo(dll);
  69. if (!f.Exists)
  70. {
  71. // check tmp dir
  72. string tmpDir = FileUtil.combine(Sys.m_homeDir, "lib", "tmp");
  73. dll = FileUtil.combine(tmpDir, asmName + ".dll");
  74. f = new FileInfo(dll);
  75. }
  76. if (!f.Exists)
  77. {
  78. // not emitted yet, emit
  79. Pod pod = Pod.find(asmName, true);
  80. return FTypeEmit.emitPod(pod.fpod, true, null);
  81. }
  82. // the file may have been generated by another process, so
  83. // check if we need to emit to flush out things this process
  84. // will need from FTypeEmit
  85. if (!asmName.EndsWith("Native_") && !FTypeEmit.isEmitted(asmName))
  86. {
  87. Pod pod = Pod.find(asmName, true);
  88. return FTypeEmit.emitPod(pod.fpod, true, null);
  89. }
  90. BinaryReader fIn = new BinaryReader(f.OpenRead());
  91. byte[] asm = fIn.ReadBytes((int)f.Length);
  92. fIn.Close();
  93. if (asm.Length != f.Length)
  94. throw new Exception("Could not read " + dll + ": " + asm.Length + " != " + f.Length);
  95. Assembly result = domain.Load(asm);
  96. return result;
  97. }
  98. /// <summary>
  99. /// Return the cmd line arguments passed for the
  100. /// Fantom launcher code.
  101. /// </summary>
  102. public static string[] getArgv()
  103. {
  104. return argv;
  105. }
  106. /// <summary>
  107. /// Initialize the .NET enviornement.
  108. /// </summary>
  109. public static void sysInit(string reserved)
  110. {
  111. if (isInit) return;
  112. try
  113. {
  114. string[] s = reserved.Split('\n');
  115. // get fan.home
  116. string fanHome = s[0];
  117. SysProps.putProperty("fan.home", fanHome);
  118. // get correct cmd line args
  119. argv = new string[s.Length-1];
  120. Array.Copy(s, 1, argv, 0, argv.Length);
  121. // check for dll reuse
  122. verifyDlls();
  123. }
  124. catch (Exception e)
  125. {
  126. Err.dumpStack(e);
  127. }
  128. }
  129. //////////////////////////////////////////////////////////////////////////
  130. // Verify Dlls
  131. //////////////////////////////////////////////////////////////////////////
  132. static void verifyDlls()
  133. {
  134. // get dirs
  135. string podDir = FileUtil.combine(Sys.m_homeDir, "lib", "fan");
  136. string tmpDir = FileUtil.combine(Sys.m_homeDir, "lib", "tmp");
  137. // check our tmp dir - cleaning up out-of-date DLL and PDB files
  138. if (Directory.Exists(tmpDir))
  139. {
  140. string[] tmp = Directory.GetFiles(tmpDir, "*.dll");
  141. Hashtable keep = new Hashtable();
  142. string sysDll = FileUtil.combine(Sys.m_homeDir, "lib", "dotnet", "sys.dll");
  143. DateTime sysModified = File.GetLastWriteTime(sysDll);
  144. if (debug)
  145. {
  146. System.Console.WriteLine("\n sys " + sysModified + "\n");
  147. System.Console.WriteLine(pad(" pod", 15) + pad("action", 10) + pad("podTime", 25) + pad("dllTime", 25));
  148. System.Console.WriteLine(pad(" ---", 15) + pad("------", 10) + pad("-------", 25) + pad("-------", 25));
  149. }
  150. for (int i=0; i<tmp.Length; i++)
  151. {
  152. string dll = tmp[i];
  153. int start = dll.LastIndexOf("\\")+1;
  154. int end = dll.IndexOf(".");
  155. string name = dll.Substring(start, end-start);
  156. DateTime podModified = DateTime.MinValue;
  157. DateTime dllModified = DateTime.MinValue;
  158. // native get handled by pod
  159. if (name.EndsWith("Native_")) continue;
  160. // check for pod
  161. string pod = FileUtil.combine(podDir, name+".pod");
  162. if (File.Exists(pod))
  163. {
  164. // if the DLL is still up-to-date, just reuse it
  165. podModified = File.GetLastWriteTime(pod);
  166. dllModified = File.GetLastWriteTime(dll);
  167. if (podModified < dllModified)
  168. keep[name] = new PodInfo(Pod.find(name, false), dllModified);
  169. }
  170. if (debug)
  171. {
  172. PodInfo info = keep[name] as PodInfo;
  173. StringBuilder b = new StringBuilder(pad(" "+name, 15));
  174. b.Append(pad(keep[name] != null ? "[keep]" : "[delete]", 10));
  175. if (podModified != DateTime.MinValue) b.Append(pad(podModified.ToString(), 25));
  176. if (dllModified != DateTime.MinValue) b.Append(pad(dllModified.ToString(), 25));
  177. System.Console.WriteLine(b);
  178. }
  179. }
  180. if (debug) System.Console.WriteLine("");
  181. // check pod dependencies
  182. string[] keys = new string[keep.Count];
  183. keep.Keys.CopyTo(keys, 0);
  184. for (int k=0; k<keys.Length; k++)
  185. {
  186. string name = keys[k];
  187. PodInfo info = keep[name] as PodInfo;
  188. // check sys first
  189. if (info.modified < sysModified)
  190. {
  191. keep.Remove(name);
  192. if (debug) System.Console.WriteLine(pad(" "+name,15)+"[delete] due to sys");
  193. continue;
  194. }
  195. // check for out-of-date depends
  196. List depends = info.pod.depends();
  197. for (int i=0; i<depends.sz(); i++)
  198. {
  199. Depend d = depends.get(i) as Depend;
  200. string n = d.name();
  201. if (n == "sys") continue; // skip sys
  202. if (keep[n] == null)
  203. {
  204. keep.Remove(name);
  205. if (debug) System.Console.WriteLine(pad(" "+name,15)+"[delete] due to " + n);
  206. break;
  207. }
  208. }
  209. }
  210. if (debug)
  211. {
  212. if (keep.Count > 0)
  213. {
  214. System.Console.WriteLine("");
  215. foreach (string key in keep.Keys)
  216. System.Console.WriteLine(" [keep] " + key);
  217. }
  218. System.Console.WriteLine("");
  219. }
  220. // delete out-of-date
  221. for (int i=0; i<tmp.Length; i++)
  222. {
  223. string dll = tmp[i];
  224. int start = dll.LastIndexOf("\\")+1;
  225. int end = dll.IndexOf(".");
  226. string name = dll.Substring(start, end-start);
  227. string pdb = FileUtil.combine(tmpDir, name+".pdb");
  228. // native get handled by pod
  229. if (name.EndsWith("Native_"))
  230. name = name.Substring(0, name.Length-"Native_".Length);
  231. // if keep, skip
  232. if (keep[name] != null) continue;
  233. // nuke it!
  234. if (debug)
  235. {
  236. System.Console.WriteLine(" [delete] " + tmp[i]);
  237. if (File.Exists(pdb)) System.Console.WriteLine(" [delete] " + pdb);
  238. }
  239. File.Delete(dll);
  240. File.Delete(pdb);
  241. }
  242. if (debug) System.Console.WriteLine("");
  243. }
  244. // mark env as initialized
  245. isInit = true;
  246. }
  247. static string pad(string str, int pad)
  248. {
  249. int sp = pad-str.Length;
  250. if (sp <= 0) return str;
  251. StringBuilder b = new StringBuilder(str);
  252. for (int i=0; i<sp; i++) b.Append(" ");
  253. return b.ToString();
  254. }
  255. class PodInfo
  256. {
  257. public PodInfo(Pod pod, DateTime modified)
  258. {
  259. this.pod = pod;
  260. this.modified = modified;
  261. }
  262. public Pod pod;
  263. public DateTime modified;
  264. }
  265. //////////////////////////////////////////////////////////////////////////
  266. // Fields
  267. //////////////////////////////////////////////////////////////////////////
  268. static bool isInit = false;
  269. static string[] argv = new string[0];
  270. static bool debug = false;
  271. }
  272. }