⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cppnetbindingcompilermanager.cs

📁 SharpDevelop2.0.0 c#开发免费工具
💻 CS
📖 第 1 页 / 共 2 页
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
//     <version value="$version"/>
// </file>

using System;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.CodeDom.Compiler;

using ICSharpCode.Core;

using ICSharpCode.SharpDevelop.Internal.Project;
using ICSharpCode.SharpDevelop.Gui;
using System.Windows.Forms;

namespace CPPBinding
{
	/// <summary>
	/// This class controls the compilation of C Sharp files and C Sharp projects
	/// </summary>
	public class CPPBindingCompilerManager
	{	
		private FileUtilityService _fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
		private StringBuilder _inputFiles   = new StringBuilder();
		private StringBuilder _buildProcess = new StringBuilder();
		private StringBuilder _results      = new StringBuilder();
		private bool _treatWarningsAsErrors;
		
		
		// we have 2 formats for the error output the csc gives :
		// d:\vc\include\xstring(1466) : warning C4701: local variable '_Ptr' may be used without hav
		readonly static Regex normalError  = new Regex(@"(?<file>.*)\((?<line>\d+)\)\s+\:\s+(?<error>.+?)\s+(?<number>[\d\w]+):\s+(?<message>.*)", RegexOptions.Compiled);
		// cl : Command line error D2016 : '/clr' and '/ML' command-line options are incompatible
		readonly static Regex generalError = new Regex(@"(?<error>.+)\s+(?<number>[\d\w]+)\s*:\s+(?<message>.*)", RegexOptions.Compiled);
			
		
		public string GetCompiledOutputName(string fileName)
		{
			return Path.ChangeExtension(fileName, ".exe");
		}
		
		public string GetCompiledOutputName(IProject project)
		{
			CPPCompilerParameters compilerparameters = (CPPCompilerParameters)project.ActiveConfiguration;
			return compilerparameters.OutputFile;
		}
		
		public bool CanCompile(string fileName)
		{
			return Path.GetExtension(fileName) == ".cpp" || Path.GetExtension(fileName) == ".c" || Path.GetExtension(fileName) == ".cxx";
		}
		
		public ICompilerResult CompileFile(string filename, CPPCompilerParameters compilerparameters)
		{
			
			if (!CanCompile(filename))
			{
				MessageBox.Show("File " + filename + " is not a source file.", "Compilation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
				return new DefaultCompilerResult(new CompilerResults(new TempFileCollection()), "");
			}
			string output = "";
			string error  = "";
			string exe = Path.ChangeExtension(filename, ".exe");
			if (compilerparameters.OutputAssembly != null && compilerparameters.OutputAssembly.Length > 0) {
				exe = compilerparameters.OutputAssembly;
			}
			_treatWarningsAsErrors = compilerparameters.TreatWarningsAsErrors;
			string responseFileName = Path.GetTempFileName();
					
			StreamWriter writer = new StreamWriter(responseFileName);

			writer.WriteLine("/nologo");
			if (compilerparameters.UseManagedExtensions) 
			{
				writer.WriteLine("/clr");
			}
			writer.WriteLine("/Fe\"" + exe + "\"");
			
			writer.WriteLine('"' + filename + '"');
			
			TempFileCollection tf = new TempFileCollection();
			
			writer.Close();
			
			string compilerName = GetCompilerName();
			string outstr =  compilerName + " \"@" + responseFileName + "\"";
			string currDir = Directory.GetCurrentDirectory();
			string intDir = compilerparameters.IntermediateDirectory;
			if (intDir == null || intDir.Length == 0) {
				intDir = compilerparameters.OutputDirectory;
			}
			
			Directory.SetCurrentDirectory(intDir);
			ICompilerResult result;
			try {
				Executor.ExecWaitWithCapture(outstr, currDir, tf, ref output, ref error);
				result = ParseOutput(tf, output, error);
			}
			catch (System.Runtime.InteropServices.ExternalException e) {
				ShowErrorBox(e);
				result = CreateErrorCompilerResult(tf, e);
			}
			finally {
				File.Delete(responseFileName);
				File.Delete(output);
				File.Delete(error);
				Directory.SetCurrentDirectory(currDir);	
			}
			return result;
		}

		private void ShowErrorBox(System.Runtime.InteropServices.ExternalException e)
		{
			MessageBox.Show("It seems cl.exe is not installed or not found.\n\nInstall compiler and set PATH environment variable.\n\nException: " + e, "Compile Error", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
		}
		
		public ICompilerResult CompileProject(IProject project, bool force)
		{
			_inputFiles   = new StringBuilder();
			_buildProcess = new StringBuilder();
			_results      = new StringBuilder();
					
			CPPProject p = (CPPProject)project;
			CPPCompilerParameters compilerparameters = (CPPCompilerParameters)p.ActiveConfiguration;
			_treatWarningsAsErrors = compilerparameters.TreatWarningsAsErrors;
			
			CheckDirectory(Path.GetDirectoryName(compilerparameters.OutputFile));
			CheckDirectory(Path.GetDirectoryName(compilerparameters.IntermediateDirectory));
			
			StringBuilder output = new StringBuilder();
			
			ICompilerResult result;
					
			if (compilerparameters.PreCompileHeader) {
				result = InternalCompileProject(p, true, force);
				if (result != null) {
					output.Append(result.CompilerOutput);
					if (HasErrors(result)) {
						goto exit;
					}
				}
			}
			
			result = InternalCompileProject(p, false, force);
			if (result != null) {
				output.Append(result.CompilerOutput);
				if (HasErrors(result)) {
					goto exit;
				}
			}
			if (result != null || !File.Exists(Path.GetFullPath(compilerparameters.OutputFile))) {
				result = LinkProject(p);
				output.Append(result.CompilerOutput);
			}
		exit:
			WriteResultFile(p);
			CompilerResults cr = result != null ? result.CompilerResults : new CompilerResults(new TempFileCollection());
			return new DefaultCompilerResult(cr, output.ToString());
		}
		
		private bool HasErrors(ICompilerResult compilerResult)
		{
			bool result = false;
			if (compilerResult.CompilerResults.Errors.Count > 0)
			{
				if (_treatWarningsAsErrors)
				{
					result = true;
				}
				else {
					foreach (CompilerError error in compilerResult.CompilerResults.Errors)
					{
						if (!error.IsWarning)
						{
							result = true;
							break;
						}
					}
				}
			}
			return result;
		}

		private void CheckDirectory(string directory)
		{
			if (!Directory.Exists(directory)) {
				Directory.CreateDirectory(directory);
			}
		}
		
		private void WriteResultFile(CPPProject p)
		{
			CPPCompilerParameters compilerparameters = (CPPCompilerParameters)p.ActiveConfiguration;
			string directory  = Path.GetDirectoryName(compilerparameters.OutputFile);
			string resultFile = Path.Combine(directory, "BuildLog.html");
			_results.Append("writing result file to : " + resultFile);
			
			StreamWriter writer = new StreamWriter(resultFile);
			writer.Write("<HTML><HEAD></HEAD><BODY>");
			writer.Write("<TABLE WIDTH=100% BGCOLOR=LightBlue><TR><TD><FONT FACE=ARIAL SIZE=+3><B>Build Log from</B>: " + p.Name + "(" + compilerparameters.Name + ")</FONT></TABLE>");
			writer.Write("Build started.");
			writer.Write("<TABLE WIDTH=100% BGCOLOR=LightBlue><TR><TD><FONT FACE=ARIAL SIZE=+2>Command Line</FONT></TD></TR></TABLE>");
			writer.WriteLine(_inputFiles.ToString());
			
			writer.Write("<TABLE WIDTH=100% BGCOLOR=LightBlue><TR><TD><FONT FACE=ARIAL SIZE=+2>Output</FONT></TD></TR></TABLE>");
			writer.Write("<PRE>");
			writer.WriteLine(_buildProcess.ToString());
			writer.Write("</PRE>");
			
			writer.Write("<TABLE WIDTH=100% BGCOLOR=LightBlue><TR><TD><FONT FACE=ARIAL SIZE=+2>Results</FONT></TD></TR></TABLE>");
			writer.Write("<PRE>");
			writer.WriteLine(_results.ToString());
			writer.Write("</PRE>");
			writer.Write("Build finished.");
			writer.Write("</BODY></HTML>");
			writer.Close();
		}
		
		#region COMPILER
		private string GetCompilerName()
		{
			return @"cl.exe";
		}
		
		private string WriteCompilerParameters(CPPProject p, bool preCompiledHeader, bool force)
		{
			CPPCompilerParameters compilerparameters = (CPPCompilerParameters)p.ActiveConfiguration;
			StringBuilder sb = new StringBuilder();
			
			sb.Append("/c\n");
			
			if (compilerparameters.UseManagedExtensions) {
				sb.Append("/clr\n");
			}
			string directory = Path.GetDirectoryName(compilerparameters.OutputFile);
			sb.Append("/Fo\"");
			sb.Append(directory);
			sb.Append("/\"\n");
			
			IProjectService projectService = (IProjectService)ICSharpCode.Core.ServiceManager.Services.GetService(typeof(IProjectService));
			ArrayList allProjects = Combine.GetAllProjects(projectService.CurrentOpenCombine);
			if (preCompiledHeader) {
				sb.Append(compilerparameters.GetPreCompiledHeaderOptions());
			} else {
				sb.Append(compilerparameters.GetCompilerOptions());
			}
			if (compilerparameters.AdditionalCompilerOptions != null && compilerparameters.AdditionalCompilerOptions.Length > 0) {
				foreach (string option in compilerparameters.AdditionalCompilerOptions.Split(';')) {
					sb.Append(option);
					sb.Append("\n");
				}
			}
			
			foreach (ProjectReference lib in p.ProjectReferences) {
				sb.Append("/FU\"");
				sb.Append(lib.GetReferencedFileName(p));
				sb.Append("\"\n");
			}
			
			switch (compilerparameters.ConfigurationType) {
				case ConfigurationType.Dll:
					sb.Append("/LD\n");
					break;
			}
			bool includedFile = false;
			foreach (ProjectFile finfo in p.ProjectFiles) {
				if (finfo.Subtype != Subtype.Directory) {
					switch (finfo.BuildAction) {
						case BuildAction.Compile:
							if (CanCompile(finfo.Name))
							{
								string fileName   = Path.GetFileNameWithoutExtension(Path.GetFullPath(finfo.Name)).ToLower();
								string headerFile = Path.GetFileNameWithoutExtension(compilerparameters.preCompiledHeaderCPPOptions.HeaderFile).ToLower();
								bool isPreHeader  = fileName == headerFile;
							
								if (!(preCompiledHeader ^ isPreHeader)) {
									if (force || ShouldCompileFile(p, finfo.Name)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -