/src/sys/dotnet/fanx/tools/Tool.cs
C# | 314 lines | 228 code | 33 blank | 53 comment | 23 complexity | 25c7bbdb6ae45ff376b454526d0edd63 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- //
- // Copyright (c) 2006, Brian Frank and Andy Frank
- // Licensed under the Academic Free License version 3.0
- //
- // History:
- // 4 Jan 06 Andy Frank Creation
- //
- using System;
- using System.Collections;
- using System.IO;
- using System.Reflection;
- using System.Text;
- using Depend = Fan.Sys.Depend;
- using Err = Fan.Sys.Err;
- using List = Fan.Sys.List;
- using Pod = Fan.Sys.Pod;
- using Sys = Fan.Sys.Sys;
- using SysProps = Fan.Sys.SysProps;
- using Fanx.Emit;
- using Fanx.Fcode;
- using Fanx.Util;
- namespace Fanx.Tools
- {
- public abstract class Tool
- {
- //////////////////////////////////////////////////////////////////////////
- // Fantom Assembly Loading
- //////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// Register the assembly resolver.
- /// </summary>
- protected Tool()
- {
- AppDomain domain = AppDomain.CurrentDomain;
- domain.AssemblyResolve += new ResolveEventHandler(resolveAssembly);
- }
- /// <summary>
- /// Get the assembly name from the specified fullName. The fullName
- /// has the following format:
- ///
- /// <name>, Version=<major.minor.build.patch>, Culture=<...>, PublicKeyToken=<...>
- ///
- /// </summary>
- public static string getAssemblyName(string fullName)
- {
- int sep = fullName.IndexOf(',');
- if (sep == -1)
- return fullName;
- else
- return fullName.Substring(0, sep);
- }
- /// <summary>
- /// Resolve an assembly that cannot be found in
- /// the current AppDomain.
- /// </summary>
- public static Assembly resolveAssembly(object sender, ResolveEventArgs args)
- {
- string asmName = getAssemblyName(args.Name);
- AppDomain domain = AppDomain.CurrentDomain;
- // check if already loaded
- Assembly[] current = domain.GetAssemblies();
- for (int i=0; i<current.Length; i++)
- if (asmName == current[i].GetName().Name)
- return current[i];
- // otherwise load it from disk
- string libDir = FileUtil.combine(Sys.m_homeDir, "lib", "dotnet");
- string dll = FileUtil.combine(libDir, asmName + ".dll");
- FileInfo f = new FileInfo(dll);
- if (!f.Exists)
- {
- // check tmp dir
- string tmpDir = FileUtil.combine(Sys.m_homeDir, "lib", "tmp");
- dll = FileUtil.combine(tmpDir, asmName + ".dll");
- f = new FileInfo(dll);
- }
- if (!f.Exists)
- {
- // not emitted yet, emit
- Pod pod = Pod.find(asmName, true);
- return FTypeEmit.emitPod(pod.fpod, true, null);
- }
- // the file may have been generated by another process, so
- // check if we need to emit to flush out things this process
- // will need from FTypeEmit
- if (!asmName.EndsWith("Native_") && !FTypeEmit.isEmitted(asmName))
- {
- Pod pod = Pod.find(asmName, true);
- return FTypeEmit.emitPod(pod.fpod, true, null);
- }
- BinaryReader fIn = new BinaryReader(f.OpenRead());
- byte[] asm = fIn.ReadBytes((int)f.Length);
- fIn.Close();
- if (asm.Length != f.Length)
- throw new Exception("Could not read " + dll + ": " + asm.Length + " != " + f.Length);
- Assembly result = domain.Load(asm);
- return result;
- }
- /// <summary>
- /// Return the cmd line arguments passed for the
- /// Fantom launcher code.
- /// </summary>
- public static string[] getArgv()
- {
- return argv;
- }
- /// <summary>
- /// Initialize the .NET enviornement.
- /// </summary>
- public static void sysInit(string reserved)
- {
- if (isInit) return;
- try
- {
- string[] s = reserved.Split('\n');
- // get fan.home
- string fanHome = s[0];
- SysProps.putProperty("fan.home", fanHome);
- // get correct cmd line args
- argv = new string[s.Length-1];
- Array.Copy(s, 1, argv, 0, argv.Length);
- // check for dll reuse
- verifyDlls();
- }
- catch (Exception e)
- {
- Err.dumpStack(e);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Verify Dlls
- //////////////////////////////////////////////////////////////////////////
- static void verifyDlls()
- {
- // get dirs
- string podDir = FileUtil.combine(Sys.m_homeDir, "lib", "fan");
- string tmpDir = FileUtil.combine(Sys.m_homeDir, "lib", "tmp");
- // check our tmp dir - cleaning up out-of-date DLL and PDB files
- if (Directory.Exists(tmpDir))
- {
- string[] tmp = Directory.GetFiles(tmpDir, "*.dll");
- Hashtable keep = new Hashtable();
- string sysDll = FileUtil.combine(Sys.m_homeDir, "lib", "dotnet", "sys.dll");
- DateTime sysModified = File.GetLastWriteTime(sysDll);
- if (debug)
- {
- System.Console.WriteLine("\n sys " + sysModified + "\n");
- System.Console.WriteLine(pad(" pod", 15) + pad("action", 10) + pad("podTime", 25) + pad("dllTime", 25));
- System.Console.WriteLine(pad(" ---", 15) + pad("------", 10) + pad("-------", 25) + pad("-------", 25));
- }
- for (int i=0; i<tmp.Length; i++)
- {
- string dll = tmp[i];
- int start = dll.LastIndexOf("\\")+1;
- int end = dll.IndexOf(".");
- string name = dll.Substring(start, end-start);
- DateTime podModified = DateTime.MinValue;
- DateTime dllModified = DateTime.MinValue;
- // native get handled by pod
- if (name.EndsWith("Native_")) continue;
- // check for pod
- string pod = FileUtil.combine(podDir, name+".pod");
- if (File.Exists(pod))
- {
- // if the DLL is still up-to-date, just reuse it
- podModified = File.GetLastWriteTime(pod);
- dllModified = File.GetLastWriteTime(dll);
- if (podModified < dllModified)
- keep[name] = new PodInfo(Pod.find(name, false), dllModified);
- }
- if (debug)
- {
- PodInfo info = keep[name] as PodInfo;
- StringBuilder b = new StringBuilder(pad(" "+name, 15));
- b.Append(pad(keep[name] != null ? "[keep]" : "[delete]", 10));
- if (podModified != DateTime.MinValue) b.Append(pad(podModified.ToString(), 25));
- if (dllModified != DateTime.MinValue) b.Append(pad(dllModified.ToString(), 25));
- System.Console.WriteLine(b);
- }
- }
- if (debug) System.Console.WriteLine("");
- // check pod dependencies
- string[] keys = new string[keep.Count];
- keep.Keys.CopyTo(keys, 0);
- for (int k=0; k<keys.Length; k++)
- {
- string name = keys[k];
- PodInfo info = keep[name] as PodInfo;
- // check sys first
- if (info.modified < sysModified)
- {
- keep.Remove(name);
- if (debug) System.Console.WriteLine(pad(" "+name,15)+"[delete] due to sys");
- continue;
- }
- // check for out-of-date depends
- List depends = info.pod.depends();
- for (int i=0; i<depends.sz(); i++)
- {
- Depend d = depends.get(i) as Depend;
- string n = d.name();
- if (n == "sys") continue; // skip sys
- if (keep[n] == null)
- {
- keep.Remove(name);
- if (debug) System.Console.WriteLine(pad(" "+name,15)+"[delete] due to " + n);
- break;
- }
- }
- }
- if (debug)
- {
- if (keep.Count > 0)
- {
- System.Console.WriteLine("");
- foreach (string key in keep.Keys)
- System.Console.WriteLine(" [keep] " + key);
- }
- System.Console.WriteLine("");
- }
- // delete out-of-date
- for (int i=0; i<tmp.Length; i++)
- {
- string dll = tmp[i];
- int start = dll.LastIndexOf("\\")+1;
- int end = dll.IndexOf(".");
- string name = dll.Substring(start, end-start);
- string pdb = FileUtil.combine(tmpDir, name+".pdb");
- // native get handled by pod
- if (name.EndsWith("Native_"))
- name = name.Substring(0, name.Length-"Native_".Length);
- // if keep, skip
- if (keep[name] != null) continue;
- // nuke it!
- if (debug)
- {
- System.Console.WriteLine(" [delete] " + tmp[i]);
- if (File.Exists(pdb)) System.Console.WriteLine(" [delete] " + pdb);
- }
- File.Delete(dll);
- File.Delete(pdb);
- }
- if (debug) System.Console.WriteLine("");
- }
- // mark env as initialized
- isInit = true;
- }
- static string pad(string str, int pad)
- {
- int sp = pad-str.Length;
- if (sp <= 0) return str;
- StringBuilder b = new StringBuilder(str);
- for (int i=0; i<sp; i++) b.Append(" ");
- return b.ToString();
- }
- class PodInfo
- {
- public PodInfo(Pod pod, DateTime modified)
- {
- this.pod = pod;
- this.modified = modified;
- }
- public Pod pod;
- public DateTime modified;
- }
- //////////////////////////////////////////////////////////////////////////
- // Fields
- //////////////////////////////////////////////////////////////////////////
- static bool isInit = false;
- static string[] argv = new string[0];
- static bool debug = false;
- }
- }