Ejemplo n.º 1
0
 /// <summary>
 /// This method is intended to be called at executable init time.
 /// It let us avoid exceptions when executing sharpmake several times in loops(exception can occur in the cs compiler
 /// when it tries to create pdb files and some already exists. Maybe that previous sharpmake sometimes still has some handles to the file?).
 /// With this cleanup code active there is no exception anymore on my PC. Previously I had the exception almost 100% on the second or third iteration
 /// of a stability test(executing sharpmake in loop to insure it always generate the same thing).
 /// </summary>
 /// <remarks>
 /// Was previously having the following exception when running stability tests(on subsequents sharpmake execution runs):
 /// Unexpected error creating debug information file 'c:\Users\xxxx\AppData\Local\Temp\Sharpmake.Assembler_1.tmp.PDB' -- 'c:\Users\xxxx\AppData\Local\Temp\Sharpmake.Assembler_1.tmp.pdb: The process cannot access the file because it is being used by another process.
 /// </remarks>
 private static void CleanupTmpAssemblies()
 {
     // Erase any remaining file that has the prefix that will be used for temporary assemblies(dll, pdb, etc...)
     // This avoids exceptions occurring when executing sharpmake several times in loops(for example when running stability tests)
     string[] oldTmpFiles = Directory.GetFiles(GetTmpAssemblyBasePath(), GetTmpAssemblyFilePrefix() + "*.*", SearchOption.TopDirectoryOnly);
     foreach (string f in oldTmpFiles)
     {
         Util.TryDeleteFile(f);
     }
 }
Ejemplo n.º 2
0
        private string GetTmpAssemblyFile()
        {
            // try to re use the same file name to not pollute tmp directory
            string tmpFilePrefix = GetType().FullName + "_";
            string tmpFileSuffix = ".tmp.dll";

            while (s_nextTempFile < int.MaxValue)
            {
                int    currentTempFile = Interlocked.Increment(ref s_nextTempFile);
                string tmpFile         = Path.Combine(Path.GetTempPath(), tmpFilePrefix + currentTempFile + tmpFileSuffix);
                if (!File.Exists(tmpFile) || Util.TryDeleteFile(tmpFile))
                {
                    return(tmpFile);
                }
            }
            return(null);
        }
Ejemplo n.º 3
0
        public static TDelegate BuildDelegate <TDelegate>(string functionBody, string functionNamespace, string[] usingNamespaces, Assembly[] assemblies)
            where TDelegate : class
        {
            Assembler assembler = new Assembler();

            assembler.UseDefaultReferences = false;
            assembler.Assemblies.AddRange(assemblies);

            const string className  = "AssemblerBuildFunction_Class";
            const string methodName = "AssemblerBuildFunction_Method";

            // Fix : Bug with -> Path.GetTempFileName
            // http://msdn.microsoft.com/en-ca/library/windows/desktop/aa364991(v=vs.85).aspx
            // Limit of 65535 limit on files when generating the temp file. New temp file will use
            // a new Guid as filename and Sharpmake will clean the temporary files when done by aggregating
            // the temp files and deleting them.
            // eg. "C:\\fastbuild-work\\85f7d472c25d494ca09f2ea7fe282d50"
            //string sourceTmpFile = Path.GetTempFileName();
            string sourceTmpFile = Path.Combine(Path.GetTempPath(), (Guid.NewGuid().ToString("N") + ".tmp.sharpmake.cs"));

            Type delegateType = typeof(TDelegate);

            Error.Valid(IsDelegate(delegateType), "BuildDelegate<TDelegate>(), TDelegate is not a delegate");

            MethodInfo methodInfo = GetDelegateMethodInfo(delegateType);

            using (StreamWriter writer = new StreamWriter(sourceTmpFile))
            {
                // add using namespace...
                foreach (string usingNamespace in usingNamespaces)
                {
                    writer.WriteLine("using {0};", usingNamespace);
                }
                writer.WriteLine();

                // namespace name
                writer.WriteLine("namespace {0}", functionNamespace);
                writer.WriteLine("{");
                writer.WriteLine("    public static class {0}", className);
                writer.WriteLine("    {");

                // write method signature
                string returnTypeName = methodInfo.ReturnType == typeof(void) ? "void" : methodInfo.ReturnType.FullName;
                writer.Write("        public static {0} {1}(", returnTypeName, methodName);
                ParameterInfo[] parameters = methodInfo.GetParameters();
                for (int i = 0; i < parameters.Length; i++)
                {
                    string parametersName = parameters[i].Name;
                    string parametersType = (parameters[i].ParameterType == typeof(object)) ? "Object" : parameters[i].ParameterType.FullName;

                    writer.Write("{0}{1} {2}", i == 0 ? "" : ", ", parametersType, parametersName);
                }
                writer.WriteLine(")");
                // write method body
                writer.WriteLine("        {");
                writer.WriteLine("            {0}" + Environment.NewLine, functionBody.Replace("\n", "\n            "));
                writer.WriteLine("        }");
                writer.WriteLine("    }");
                writer.WriteLine("}");
            }

            // build in memory
            Assembly assembly = assembler.Build(builderContext: null, libraryFile: null, sources: sourceTmpFile).Assembly;

            InternalError.Valid(assembly != null);

            // Try to delete tmp file to prevent pollution, but useful while debugging
            //if (!System.Diagnostics.Debugger.IsAttached)
            Util.TryDeleteFile(sourceTmpFile);

            // Scan assembly to find our tmp class
            string fullClassName = functionNamespace + "." + className;
            Type   buildedType   = assembly.GetType(fullClassName);

            // get out method to bind into the delegate
            MethodInfo builtMethod = buildedType.GetMethod(methodName);

            InternalError.Valid(builtMethod != null);

            // bind the method
            Delegate returnDelegate;

            try
            {
                returnDelegate = builtMethod.CreateDelegate(delegateType);
                InternalError.Valid(returnDelegate != null);
            }
            catch (Exception e)
            {
                throw new InternalError(e);
            }

            TDelegate result = returnDelegate as TDelegate;

            InternalError.Valid(result != null, "Cannot cast built delegate into user delegate");

            return(result);
        }