Esempio n. 1
0
		/// <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;
		}
Esempio n. 2
0
        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;
                    }
                }
            }
        }
Esempio n. 3
0
        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;
                    }
                }
            }
        }