// TODO: Move compilation stuff elsewhere. // TODO: Consider IronPython support: http://www.ironpython.info/index.php/Using_Compiled_Python_Classes_from_.NET/CSharp_IP_2.6 internal List <ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary) { List <ExportedAssembly> list = new List <ExportedAssembly>(); // Dynamically compile this project to an in-memory assembly CodeDomProvider provider = GetProvider(); if (provider == null) { return(list); } CompilerParameters cp = new CompilerParameters(); bool isFsharp = false; // TODO: Debug build ? // cp.IncludeDebugInformation = true; cp.GenerateExecutable = false; //cp.OutputAssembly = Name; // TODO: Keep track of built assembly for the project cp.GenerateInMemory = true; cp.TreatWarningsAsErrors = false; // This is attempt to fix the bug reported on the group, where the add-in compilation fails if the add-in is put into c:\ // It is caused by a quirk of the 'Path.GetDirectoryName' function when dealing with the path "c:\test.abc" // - it leaves the last DirectorySeparator in the path in this special case. // Thanks to Nemo for the great fix. //local variable to hold the quoted/unquoted version of the executing dirction string ProcessedExecutingDirectory = DnaLibrary.ExecutingDirectory; if (ProcessedExecutingDirectory.IndexOf(' ') != -1) { ProcessedExecutingDirectory = "\"" + ProcessedExecutingDirectory + "\""; } //set compiler command line vars as needed if (provider is Microsoft.VisualBasic.VBCodeProvider) { cp.CompilerOptions = " /libPath:" + ProcessedExecutingDirectory; if (DefaultImports) { string importsList = "Microsoft.VisualBasic,System,System.Collections,System.Collections.Generic,System.Data,System.Diagnostics,ExcelDna.Integration"; if (Environment.Version.Major >= 4) { importsList += ",System.Linq,System.Xml.Linq"; } cp.CompilerOptions += " /imports:" + importsList; } } else if (provider is Microsoft.CSharp.CSharpCodeProvider) { cp.CompilerOptions = " /lib:" + ProcessedExecutingDirectory; } else if (provider.GetType().FullName.ToLower().IndexOf(".jscript.") != -1) { cp.CompilerOptions = " /lib:" + ProcessedExecutingDirectory; } else if (provider.GetType().FullName == "Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider") { isFsharp = true; cp.CompilerOptions = " --nologo -I " + ProcessedExecutingDirectory; // In F# 2.0, the --nologo is redundant - I leave it because it does no harm. // FSharp 2.0 compiler will target .NET 4 unless we do something to ensure .NET 2.0. // It seems adding an explicit reference to the .NET 2.0 version of mscorlib.dll is good enough. if (Environment.Version.Major < 4) { // Explicitly add a reference to the mscorlib version from the currently running .NET version string libPath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "mscorlib.dll"); cp.ReferencedAssemblies.Add(libPath); } } // TODO: Consider what to do if we can't resolve some of the Reference paths -- do we try to compile anyway, throw an exception, ...what? List <string> refPaths = GetReferencePaths(pathResolveRoot, provider); cp.ReferencedAssemblies.AddRange(refPaths.ToArray()); List <string> sources = GetSources(pathResolveRoot); CompilerResults cr; try { cr = provider.CompileAssemblyFromSource(cp, sources.ToArray()); } catch (Win32Exception wex) { if (isFsharp) { Logger.DnaCompilation.Error("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):"); string fsBinPath = Environment.GetEnvironmentVariable("FSHARP_BIN"); string msg; if (fsBinPath == null) { msg = " Calling the F# compiler failed (\"" + wex.Message + "\").\r\n" + " Please check that the F# compiler is correctly installed.\r\n" + " This error can sometimes be fixed by creating an FSHARP_BIN environment variable.\r\n" + " Create an environment variable FSHARP_BIN with the full path to the directory containing \r\n" + " the F# compiler fsc.exe - for example \r\n" + " \"" + @"C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0\"""; } else { msg = " Calling the F# compiler failed (\"" + wex.Message + "\").\r\n" + " Please check that the F# compiler is correctly installed, and that the FSHARP_BIN environment variable is correct\r\n" + " (it currently points to " + fsBinPath + ")."; } Logger.DnaCompilation.Error(msg); return(list); } throw; } foreach (string path in tempAssemblyPaths) { File.Delete(path); } tempAssemblyPaths.Clear(); if (cr.Errors.HasErrors) { Logger.DnaCompilation.Error("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):"); Logger.DnaCompilation.Error("There were errors when compiling project: " + Name); foreach (CompilerError err in cr.Errors) { Logger.DnaCompilation.Error(" " + err.ToString()); } return(list); } // Success !! // Now add all the references // TODO: How to remove again?? foreach (Reference r in References) { AssemblyReference.AddAssembly(r.Path); } // TODO: Create TypeLib for execution-time compiled assemblies. list.Add(new ExportedAssembly(cr.CompiledAssembly, ExplicitExports, ExplicitRegistration, ComServer, true, null, dnaLibrary)); return(list); }
// TODO: Move compilation stuff elsewhere. public List <Assembly> GetAssemblies() { List <Assembly> list = new List <Assembly>(); // Dynamically compile this project to an in-memory assembly CodeDomProvider provider = GetProvider(); if (provider == null) { return(list); } CompilerParameters cp = new CompilerParameters(); // TODO: Debug build ? // cp.IncludeDebugInformation = true; cp.GenerateExecutable = false; //cp.OutputAssembly = Name; // TODO: Keep track of built assembly for the project cp.GenerateInMemory = true; cp.TreatWarningsAsErrors = false; if (provider is Microsoft.VisualBasic.VBCodeProvider) { cp.CompilerOptions = " /libPath:\"" + DnaLibrary.ExecutingDirectory + "\" "; if (DefaultImports) { string importsList = "Microsoft.VisualBasic,System,System.Collections,System.Collections.Generic,System.Data,System.Diagnostics,ExcelDna.Integration"; cp.CompilerOptions += " /imports:" + importsList; } } else if (provider is Microsoft.CSharp.CSharpCodeProvider) { cp.CompilerOptions = " /lib:\"" + DnaLibrary.ExecutingDirectory + "\" "; } else if (provider.GetType().FullName == "Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider") { cp.CompilerOptions = " --nologo -I " + DnaLibrary.ExecutingDirectory; } List <string> references = GetReferences().ConvertAll <string>(delegate(Reference item) { return(item.AssemblyPath); }); cp.ReferencedAssemblies.AddRange(references.ToArray()); List <string> sources = GetSourceItems().ConvertAll <string>(delegate(SourceItem item) { return(item.Code); }); CompilerResults cr = provider.CompileAssemblyFromSource(cp, sources.ToArray()); // TODO: URGENT: Revisit... if (tempIntegrationAssemblyPath != null) { File.Delete(tempIntegrationAssemblyPath); tempIntegrationAssemblyPath = null; } if (cr.Errors.HasErrors) { ExcelDna.Logging.LogDisplay.WriteLine("There were errors when compiling project: " + Name); foreach (CompilerError err in cr.Errors) { ExcelDna.Logging.LogDisplay.WriteLine(err.ToString()); } return(list); } // Success !! // Now add all the references // TODO: How to remove again?? foreach (Reference r in References) { AssemblyReference.AddAssembly(r.AssemblyPath); } list.Add(cr.CompiledAssembly); return(list); }