/// <summary> /// Compiles C# script file. /// </summary> private string Compile(string scriptFileName) { bool generateExe = options.buildExecutable; string scriptDir = Path.GetDirectoryName(scriptFileName); string assemblyFileName = ""; string tempDir = Path.GetDirectoryName(GetScriptTempFile()); //options may be uninitialized in case we are compileng from CSScriptLibrary if (options.searchDirs.Length == 0) options.searchDirs = new string[]{scriptDir}; //parse source file in order to find all referenced assemblies //ASSUMPTION: assembly name is the same as namespace + ".dll" //if script doesn't follow this assumption user will need to //specify assemblies explicitly ScriptParser parser = new ScriptParser(scriptFileName, options.searchDirs); ICodeCompiler compiler; if (options.altCompiler == "") { compiler = (new CSharpCodeProvider()).CreateCompiler(); } else { try { Assembly asm = Assembly.LoadFrom(Path.IsPathRooted(options.altCompiler) ? options.altCompiler : Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), options.altCompiler)); Type[] types = asm.GetModules()[0].FindTypes(Module.FilterTypeName, "CSSCodeProvider"); MethodInfo method = types[0].GetMethod("CreateCompiler"); compiler = (ICodeCompiler)method.Invoke(null, new object[]{scriptFileName}); } catch (Exception ex) { throw new Exception("Cannot use alternative compiler", ex); } } CompilerParameters compileParams = new CompilerParameters(); if (options.DBG) compileParams.CompilerOptions = "/d:DEBUG /d:TRACE "; if (options.compilerOptions != string.Empty) compileParams.CompilerOptions += options.compilerOptions; compileParams.IncludeDebugInformation = options.DBG; compileParams.GenerateExecutable = generateExe; compileParams.GenerateInMemory = !generateExe; ArrayList refAssemblies = new ArrayList(); //add assemblies were referenced from command line foreach (string asmName in options.refAssemblies) compileParams.ReferencedAssemblies.AddRange(AssemblyResolver.FindAssembly(asmName, options.searchDirs)); AssemblyResolver.ignoreFileName = Path.GetFileNameWithoutExtension(scriptFileName) + ".dll"; //add local and global assemblies (if found) that have the same assembly name as a namespace foreach (string nmSpace in parser.ReferencedNamespaces) compileParams.ReferencedAssemblies.AddRange(AssemblyResolver.FindAssembly(nmSpace, options.searchDirs)); //add assemblies referenced from code foreach (string asmName in parser.ReferencedAssemblies) if (asmName.StartsWith("\"") && asmName.EndsWith("\"")) compileParams.ReferencedAssemblies.Add(asmName.Replace("\"", "")); //not-searchable assemblies else compileParams.ReferencedAssemblies.AddRange(AssemblyResolver.FindAssembly(asmName, options.searchDirs)); //add resources referenced from code foreach (string resFile in parser.ReferencedResources) { string file = null; foreach (string dir in options.searchDirs) { file = Path.IsPathRooted(resFile) ? Path.GetFullPath(resFile) : Path.Combine(dir, resFile); if (File.Exists(file)) break; } if (file == null) file = resFile; compileParams.CompilerOptions += "\"/res:" + file + "\" "; //eg. /res:C:\\Scripting.Form1.resources"; } if (options.forceOutputAssembly != "") { assemblyFileName = options.forceOutputAssembly; } else { if (generateExe) assemblyFileName = Path.Combine(scriptDir, Path.GetFileNameWithoutExtension(scriptFileName) + ".exe"); else if (options.useCompiled || options.DLLExtension) { if (options.DLLExtension) assemblyFileName = Path.Combine(scriptDir, Path.GetFileNameWithoutExtension(scriptFileName) + ".dll"); else if (options.hideTemp != Settings.HideOptions.DoNotHide) assemblyFileName = Path.Combine(CSExecutor.ScriptCacheDir, Path.GetFileName(scriptFileName) + "c"); else assemblyFileName = scriptFileName + "c"; } else { string tempFile = Path.GetTempFileName(); if (File.Exists(tempFile)) File.Delete(tempFile); assemblyFileName = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(tempFile)+".dll"); } } if (generateExe && options.buildWinExecutable) compileParams.CompilerOptions += "/target:winexe "; if (File.Exists(assemblyFileName)) File.Delete(assemblyFileName); compileParams.OutputAssembly = assemblyFileName; CompilerResults results; if (generateExe) { results = compiler.CompileAssemblyFromFileBatch(compileParams, parser.FilesToCompile); } else { string originalExtension = Path.GetExtension(compileParams.OutputAssembly); if (originalExtension != ".dll") { //Despite the usage of .dll file name is not required for MS C# compiler we need to do this because //some compilers (Mono, VB) accept only dll or exe file extensions. compileParams.OutputAssembly = Path.ChangeExtension(compileParams.OutputAssembly, ".dll"); if (File.Exists(compileParams.OutputAssembly)) File.Delete(compileParams.OutputAssembly); results = compiler.CompileAssemblyFromFileBatch(compileParams, parser.FilesToCompile); if (File.Exists(compileParams.OutputAssembly)) { while (true) { //There were reports of MS C# compiler (csc.exe) notr releasing OutputAssembly file //after compilation finished. Thus wait a little... try { using (File.Open(compileParams.OutputAssembly, FileMode.Open, FileAccess.Read, FileShare.None)) break; } catch { Thread.Sleep(100); } } File.Move(compileParams.OutputAssembly, Path.ChangeExtension(compileParams.OutputAssembly, originalExtension)); } } else { if (File.Exists(compileParams.OutputAssembly)) File.Delete(compileParams.OutputAssembly); results = compiler.CompileAssemblyFromFileBatch(compileParams, parser.FilesToCompile); } } if (results.Errors.Count != 0) { StringBuilder compileErr = new StringBuilder(); foreach (CompilerError err in results.Errors) { if (err.IsWarning && options.hideCompilerWarnings) continue; compileErr.Append(err.ToString()); compileErr.Append(Environment.NewLine); compileErr.Append(Environment.NewLine); } throw new Exception(compileErr.ToString()); } else { if (!options.DBG) //.pdb and imported files might be needed for the debugger { parser.DeleteImportedFiles(); string pdbFile = Path.Combine(Path.GetDirectoryName(assemblyFileName), Path.GetFileNameWithoutExtension(assemblyFileName)+".pdb"); if (File.Exists(pdbFile)) File.Delete(pdbFile); } if (options.useCompiled) { if (options.useSmartCaching) { MetaDataItems depInfo = new MetaDataItems(); //save referenced local assemblies info foreach(string assembly in compileParams.ReferencedAssemblies) { foreach(string dir in options.searchDirs) if (string.Compare(dir, Path.GetDirectoryName(assembly), true) == 0) { FileInfo assemblyInfo = new FileInfo(assembly); depInfo.AddItem(Path.GetFileName(assembly), assemblyInfo.LastWriteTimeUtc, true); break; } } //save imported scripts info foreach(string script in parser.ImportedFiles) { FileInfo scriptInfo = new FileInfo(script); bool local = false; foreach (string dir in options.searchDirs) if ((local = (string.Compare(dir, Path.GetDirectoryName(scriptInfo.FullName), true) == 0))) break; if (local) depInfo.AddItem(Path.GetFileName(script), scriptInfo.LastWriteTimeUtc, false); else depInfo.AddItem(script, scriptInfo.LastWriteTimeUtc, false); } depInfo.StampFile(assemblyFileName); } FileInfo scriptFile = new FileInfo(scriptFileName); FileInfo asmFile = new FileInfo(assemblyFileName); if (scriptFile!= null && asmFile != null) { //Console.WriteLine("Update LastWriteTime"+assemblyFileName); //temp os asmFile.LastWriteTime = scriptFile.LastWriteTime; asmFile.LastWriteTimeUtc = scriptFile.LastWriteTimeUtc; } } } return assemblyFileName; }
void ProcessCompilingResult(CompilerResults results, CompilerParameters compilerParams, ScriptParser parser, string scriptFileName, string assemblyFileName, string[] additionalDependencies) { LastCompileResult = results; if (results.Errors.HasErrors) { CompilerException ex = CompilerException.Create(results.Errors, options.hideCompilerWarnings); if (options.syntaxCheck) Console.WriteLine("Compile: {0} error(s)\n{1}", ex.ErrorCount, ex.Message); else throw ex; } else { if (options.syntaxCheck) Console.WriteLine("Compile: OK"); if (options.verbose) { Console.WriteLine(" Compiler Output: ", options); foreach (CompilerError err in results.Errors) Console.WriteLine(" {0}({1},{2}):{3} {4} {5}", err.FileName, err.Line, err.Column, (err.IsWarning ? "warning" : "error"), err.ErrorNumber, err.ErrorText); Console.WriteLine("> ----------------", options); } if (!options.DBG) //.pdb and imported files might be needed for the debugger { parser.DeleteImportedFiles(); string pdbFile = Path.Combine(Path.GetDirectoryName(assemblyFileName), Path.GetFileNameWithoutExtension(assemblyFileName) + ".pdb"); Utils.FileDelete(pdbFile); } if (options.useCompiled) { if (options.useSmartCaching) { MetaDataItems depInfo = new MetaDataItems(); string[] searchDirs = Utils.RemovePathDuplicates(options.searchDirs); //save imported scripts info depInfo.AddItems(parser.ImportedFiles, false, searchDirs); //additionalDependencies (precompilers) are warranted to be as absolute path so no need to pass searchDirs or isAssembly depInfo.AddItems(additionalDependencies, false, new string[0]); //save referenced local assemblies info string[] newProbingDirs = depInfo.AddItems(compilerParams.ReferencedAssemblies, true, searchDirs); foreach (string dir in newProbingDirs) options.AddSearchDir(dir); //needed to be added at Compilation for further resolving during the Invoking stage depInfo.StampFile(assemblyFileName); } FileInfo scriptFile = new FileInfo(scriptFileName); FileInfo asmFile = new FileInfo(assemblyFileName); if (scriptFile != null && asmFile != null) { asmFile.LastWriteTimeUtc = scriptFile.LastWriteTimeUtc; } } } }
private void ProcessCompilingResult(CompilerResults results, CompilerParameters compilerParams, ScriptParser parser, string scriptFileName, string assemblyFileName, string[] additionalDependencies) { LastCompileResult = results; if (results.Errors.Count != 0) { throw CompilerException.Create(results.Errors, options.hideCompilerWarnings); } else { if (!options.DBG) //.pdb and imported files might be needed for the debugger { parser.DeleteImportedFiles(); string pdbFile = Path.Combine(Path.GetDirectoryName(assemblyFileName), Path.GetFileNameWithoutExtension(assemblyFileName) + ".pdb"); if (File.Exists(pdbFile)) File.Delete(pdbFile); } if (options.useCompiled) { if (options.useSmartCaching) { MetaDataItems depInfo = new MetaDataItems(); string[] searchDirs = Utils.RemovePathDuplicates(options.searchDirs); //save imported scripts info depInfo.AddItems(parser.ImportedFiles, false, searchDirs); //additionalDependencies (precompilers) are warranted to be as absolute path so no need to pass searchDirs or isAssembly depInfo.AddItems(additionalDependencies, false, new string[0]); //save referenced local assemblies info string[] newProbingDirs = depInfo.AddItems(compilerParams.ReferencedAssemblies, true, searchDirs); foreach (string dir in newProbingDirs) options.AddSearchDir(dir); //needed to be added at Compilation for further resolving during the Invoking stage depInfo.StampFile(assemblyFileName); } FileInfo scriptFile = new FileInfo(scriptFileName); FileInfo asmFile = new FileInfo(assemblyFileName); if (scriptFile != null && asmFile != null) { asmFile.LastWriteTimeUtc = scriptFile.LastWriteTimeUtc; } } } }