示例#1
0
        private EmitOptions GetEmitOptions(out bool emitPdb)
        {
            var emitOptions = new EmitOptions();

            var usePortablePdbString = Environment.GetEnvironmentVariable(EnvironmentNames.PortablePdb);

            // Use portable pdbs if explicitly specified or the platform doesn't support pdb generation
            var usePortablePdb = string.Equals(usePortablePdbString, "true", StringComparison.OrdinalIgnoreCase) ||
                                 string.Equals(usePortablePdbString, "1", StringComparison.OrdinalIgnoreCase);

            if (usePortablePdb)
            {
                Logger.TraceInformation("Using portable pdb format");

                // Emit the portable pdb format if explicitly specified.
                // TODO: Make a decision about when we use the portable pdb by default.
                // On mono < 4.2 Emitting the portable PDB just hangs for some odd reason.
                emitPdb = true;
                return(emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb));
            }

            // Otherwise, emit the regular pdb format if the platfom supports it
            emitPdb = _supportsPdbGeneration.Value;

            return(emitOptions);
        }
示例#2
0
        public static CompilerResults Compile(CompilerParameters args, string[] files)
        {
            var name    = Path.GetFileNameWithoutExtension(args.OutputAssembly);
            var pdbPath = Path.ChangeExtension(args.OutputAssembly, "pdb");

            var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                          .WithOptimizationLevel(args.IncludeDebugInformation ? OptimizationLevel.Debug : OptimizationLevel.Release)
                          .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);

            var parseOptions = new CSharpParseOptions(LanguageVersion.Latest);

            var emitOptions = new EmitOptions();

            if (Type.GetType("Mono.Runtime") != null)
            {
                emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
            }

            var refs = args.ReferencedAssemblies.Cast <string>().Select(s => MetadataReference.CreateFromFile(s));
            var src  = files.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, f, Encoding.UTF8));
            var comp = CSharpCompilation.Create(name, src, refs, options);

            EmitResult results;

            using (var peStream = File.OpenWrite(args.OutputAssembly))
                using (var pdbStream = args.IncludeDebugInformation ? File.OpenWrite(pdbPath) : null) {
                    results = comp.Emit(peStream, pdbStream, options: emitOptions);
                }

            var cRes = new CompilerResults(args.TempFiles);

            foreach (var d in results.Diagnostics)
            {
                if (d.Severity != DiagnosticSeverity.Error)
                {
                    continue;
                }

                var loc = d.Location.GetLineSpan();
                var pos = loc.StartLinePosition;
                cRes.Errors.Add(new CompilerError(loc.Path ?? "", pos.Line, pos.Character, d.Id, d.GetMessage()));
            }

            return(cRes);
        }
示例#3
0
        public static CompilerErrorCollection Compile(string name, string outputPath, string[] references, string[] files, bool includePdb)
        {
            var pdbPath = Path.ChangeExtension(outputPath, "pdb");

            var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                          .WithOptimizationLevel(OptimizationLevel.Debug)       // currently no way to specify debug vs release. We still want pdb files with release mode for bug reports
                          .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);

            var parseOptions = new CSharpParseOptions(LanguageVersion.Latest);

            var emitOptions = new EmitOptions();

            if (Type.GetType("Mono.Runtime") != null)
            {
                emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
            }

            var refs = references.Select(s => MetadataReference.CreateFromFile(s));
            var src  = files.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, f, Encoding.UTF8));
            var comp = CSharpCompilation.Create(name, src, refs, options);

            EmitResult results;

            using (var peStream = File.OpenWrite(outputPath))
                using (var pdbStream = includePdb ? File.OpenWrite(pdbPath) : null) {
                    results = comp.Emit(peStream, pdbStream, options: emitOptions);
                }

            var errors = new CompilerErrorCollection();

            foreach (var d in results.Diagnostics.Where(d => d.Severity >= DiagnosticSeverity.Warning))
            {
                var loc = d.Location.GetLineSpan();
                errors.Add(new CompilerError {
                    ErrorNumber = d.Id,
                    IsWarning   = d.Severity == DiagnosticSeverity.Warning,
                    ErrorText   = d.GetMessage(),
                    FileName    = loc.Path ?? "",
                    Line        = loc.StartLinePosition.Line,
                    Column      = loc.StartLinePosition.Character
                });
            }

            return(errors);
        }
示例#4
0
        public override Tuple <Type, CompilationData> CompileType(TypeContext context)
        {
            var sourceCode   = GetCodeCompileUnit(context);
            var assemblyName = GetAssemblyName(context);

            (new PermissionSet(PermissionState.Unrestricted)).Assert();
            var tempDir = GetTemporaryDirectory();

            var sourceCodeFile = Path.Combine(tempDir, String.Format("{0}.{1}", assemblyName, SourceFileExtension));

            File.WriteAllText(sourceCodeFile, sourceCode);

            var references = GetAllReferences(context);

            var compilation =
                GetEmptyCompilation(assemblyName)
                .AddSyntaxTrees(
                    GetSyntaxTree(sourceCode, sourceCodeFile))
                .AddReferences(GetMetadataReferences(references));

            compilation =
                compilation
                .WithOptions(
                    CreateOptions(context)
                    .WithOutputKind(OutputKind.DynamicallyLinkedLibrary)
                    .WithPlatform(Platform.AnyCpu)
                    .WithSourceReferenceResolver(new RazorEngineSourceReferenceResolver(sourceCodeFile)));

            var assemblyFile = Path.Combine(tempDir, String.Format("{0}.dll", assemblyName));

            var assemblyPdbFile = Path.Combine(tempDir, String.Format("{0}.pdb", assemblyName));
            var compilationData = new CompilationData(sourceCode, tempDir);

            using (var assemblyStream = File.Open(assemblyFile, FileMode.Create, FileAccess.ReadWrite))
                using (var pdbStream = File.Open(assemblyPdbFile, FileMode.Create, FileAccess.ReadWrite))
                {
                    var opts = new EmitOptions()
                               .WithPdbFilePath(assemblyPdbFile);
                    var pdbStreamHelper = pdbStream;

                    if (IsMono())
                    {
                        opts = opts.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
                    }

                    EmitResult result = null;
                    if (Debugger.IsAttached)
                    {
                        result = compilation.Emit(assemblyStream, pdbStreamHelper, options: opts);
                    }
                    else
                    {
                        result = compilation.Emit(assemblyStream);
                    }
                    //var result = compilation.Emit(assemblyStream, pdbStreamHelper, options: opts);
                    //var result = compilation.Emit(assemblyStream);
                    if (!result.Success)
                    {
                        var errors =
                            result.Diagnostics.Select(diag =>
                        {
                            var lineSpan = diag.Location.GetLineSpan();
                            return(new Templating.RazorEngineCompilerError(
                                       string.Format("{0}", diag.GetMessage()),
                                       lineSpan.Path,
                                       lineSpan.StartLinePosition.Line,
                                       lineSpan.StartLinePosition.Character,
                                       diag.Id,
                                       diag.Severity != DiagnosticSeverity.Error));
                        });

                        throw new Templating.TemplateCompilationException(errors, compilationData, context.TemplateContent);
                    }
                }

            // load file and return loaded type.
            Assembly assembly;

            if (DisableTempFileLocking)
            {
                assembly = File.Exists(assemblyPdbFile)
                    ? Assembly.Load(File.ReadAllBytes(assemblyFile), File.ReadAllBytes(assemblyPdbFile))
                    : Assembly.Load(File.ReadAllBytes(assemblyFile));
            }
            else
            {
                assembly = Assembly.LoadFrom(assemblyFile);
            }
            var type = assembly.GetType(DynamicTemplateNamespace + "." + context.ClassName);

            return(Tuple.Create(type, compilationData));
        }
        /// <summary>
        /// Generates and compiles an assembly for the provided syntax.
        /// </summary>
        /// <param name="generatedSyntax">
        /// The generated code.
        /// </param>
        /// <param name="assemblyName">
        /// The name for the generated assembly.
        /// </param>
        /// <param name="emitDebugSymbols">
        /// Whether or not to emit debug symbols for the generated assembly.
        /// </param>
        /// <returns>
        /// The raw assembly.
        /// </returns>
        /// <exception cref="CodeGenerationException">
        /// An error occurred generating code.
        /// </exception>
        private Assembly CompileAssembly(GeneratedSyntax generatedSyntax, string assemblyName, bool emitDebugSymbols)
        {
            // Add the generated code attribute.
            var code = CodeGeneratorCommon.AddGeneratedCodeAttribute(generatedSyntax);

            // Reference everything which can be referenced.
            var assemblies =
                AppDomain.CurrentDomain.GetAssemblies()
                .Where(asm => !asm.IsDynamic && !string.IsNullOrWhiteSpace(asm.Location))
                .Select(asm => MetadataReference.CreateFromFile(asm.Location))
                .Cast <MetadataReference>()
                .ToArray();

            // Generate the code.
            var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);

#if NETSTANDARD2_0
            // CoreFX bug https://github.com/dotnet/corefx/issues/5540
            // to workaround it, we are calling internal WithTopLevelBinderFlags(BinderFlags.IgnoreCorLibraryDuplicatedTypes)
            // TODO: this API will be public in the future releases of Roslyn.
            // This work is tracked in https://github.com/dotnet/roslyn/issues/5855
            // Once it's public, we should replace the internal reflection API call by the public one.
            var method = typeof(CSharpCompilationOptions).GetMethod("WithTopLevelBinderFlags", BindingFlags.NonPublic | BindingFlags.Instance);
            // we need to pass BinderFlags.IgnoreCorLibraryDuplicatedTypes, but it's an internal class
            // http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp/Binder/BinderFlags.cs,00f268571bb66b73
            options = (CSharpCompilationOptions)method.Invoke(options, new object[] { 1u << 26 });
#endif

            string source = null;
            if (this.logger.IsEnabled(LogLevel.Debug))
            {
                source = CodeGeneratorCommon.GenerateSourceCode(code);

                // Compile the code and load the generated assembly.
                this.logger.Debug(
                    ErrorCode.CodeGenSourceGenerated,
                    "Generating assembly {0} with source:\n{1}",
                    assemblyName,
                    source);
            }

            var compilation =
                CSharpCompilation.Create(assemblyName)
                .AddSyntaxTrees(code.SyntaxTree)
                .AddReferences(assemblies)
                .WithOptions(options);

            using (var outputStream = new MemoryStream())
            {
                var emitOptions = new EmitOptions()
                                  .WithEmitMetadataOnly(false)
                                  .WithIncludePrivateMembers(true);

                if (emitDebugSymbols)
                {
                    emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.Embedded);
                }

                var compilationResult = compilation.Emit(outputStream, options: emitOptions);
                if (!compilationResult.Success)
                {
                    source = source ?? CodeGeneratorCommon.GenerateSourceCode(code);
                    var errors = string.Join("\n", compilationResult.Diagnostics.Select(_ => _.ToString()));
                    this.logger.Warn(
                        ErrorCode.CodeGenCompilationFailed,
                        "Compilation of assembly {0} failed with errors:\n{1}\nGenerated Source Code:\n{2}",
                        assemblyName,
                        errors,
                        source);
                    throw new CodeGenerationException(errors);
                }

                this.logger.Debug(
                    ErrorCode.CodeGenCompilationSucceeded,
                    "Compilation of assembly {0} succeeded.",
                    assemblyName);
                return(Assembly.Load(outputStream.ToArray()));
            }
        }
示例#6
0
        CodeCompilerResult CompileFileInternal(
            CodeCompilerArguments arguments,
            TextWriter log,
            CancellationToken token)
        {
            CSharpCommandLineArguments args = null;

            if (arguments.AdditionalArguments != null)
            {
                var splitArgs = CommandLineParser.SplitCommandLineIntoArguments(arguments.AdditionalArguments, false);
                if (splitArgs.Any())
                {
                    args = CSharpCommandLineParser.Default.Parse(splitArgs, arguments.TempDirectory, null, null);
                }
            }

            var references = new List <MetadataReference> ();

            foreach (var assemblyReference in AssemblyResolver.GetResolvedReferences(runtime, arguments.AssemblyReferences))
            {
                references.Add(MetadataReference.CreateFromFile(assemblyReference));
            }

            var parseOptions = args?.ParseOptions ?? new CSharpParseOptions();

            if (arguments.LangVersion != null)
            {
                if (LanguageVersionFacts.TryParse(arguments.LangVersion, out var langVersion))
                {
                    parseOptions = parseOptions.WithLanguageVersion(langVersion);
                }
                else
                {
                    throw new System.Exception($"Unknown value '{arguments.LangVersion}' for langversion");
                }
            }
            else
            {
                // need to update this when updating referenced roslyn binaries
                CSharpLangVersionHelper.GetBestSupportedLangVersion(runtime, CSharpLangVersion.v9_0);
            }

            var syntaxTrees = new List <SyntaxTree> ();

            foreach (var sourceFile in arguments.SourceFiles)
            {
                using var stream = File.OpenRead(sourceFile);
                var        sourceText = SourceText.From(stream, Encoding.UTF8, canBeEmbedded: true);
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceText, parseOptions, cancellationToken: token, path: sourceFile);
                syntaxTrees.Add(syntaxTree);
            }

            var compilationOptions = (args?.CompilationOptions ?? new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
                                     .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            var compilation = CSharpCompilation.Create(
                "GeneratedTextTransformation",
                syntaxTrees,
                references,
                compilationOptions
                );


            EmitOptions emitOptions = args?.EmitOptions ?? new EmitOptions();

            if (arguments.Debug)
            {
                var embeddedTexts = syntaxTrees.Select(st => EmbeddedText.FromSource(st.FilePath, st.GetText())).ToList();
                emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.Embedded);
            }

            using var fs = File.OpenWrite(arguments.OutputPath);
            EmitResult result = compilation.Emit(fs, options: emitOptions, cancellationToken: token);

            if (result.Success)
            {
                return(new CodeCompilerResult {
                    Output = new List <string> (),
                    Success = true,
                    Errors = new List <CodeCompilerError> ()
                });
            }

            var failures = result.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error);
            var errors   = failures.Select(x => {
                var location          = x.Location.GetMappedLineSpan();
                var startLinePosition = location.StartLinePosition;
                var endLinePosition   = location.EndLinePosition;
                return(new CodeCompilerError {
                    Message = x.GetMessage(),
                    Column = startLinePosition.Character,
                    Line = startLinePosition.Line,
                    EndLine = endLinePosition.Line,
                    EndColumn = endLinePosition.Character,
                    IsError = x.Severity == DiagnosticSeverity.Error,
                    Origin = location.Path
                });
            }).ToList();

            return(new CodeCompilerResult {
                Success = false,
                Output = new List <string> (),
                Errors = errors
            });
        }
示例#7
0
        /// <summary>
        /// Compiles <paramref name="code"/> and creates script.
        /// </summary>
        /// <param name="options">Compilation options.</param>
        /// <param name="code">Code to be compiled.</param>
        /// <param name="builder">Assembly builder.</param>
        /// <param name="previousSubmissions">Enumeration of scripts that were evaluated within current context. New submission may reference them.</param>
        /// <returns>New script representing the compiled code.</returns>
        public static Script Create(Context.ScriptOptions options, string code, PhpCompilationFactory builder, IEnumerable <Script> previousSubmissions)
        {
            // use the language version of the requesting context
            var languageVersion = options.LanguageVersion;
            var shortOpenTags   = false;

            var language = options.Context.TargetPhpLanguage;

            if (language != null)
            {
                shortOpenTags = language.ShortOpenTag;
                languageVersion ??= language.LanguageVersion;
            }

            // unique in-memory assembly name
            var name = builder.GetNewSubmissionName();

            // submission do not have the opening "<?php" script tag:
            var kind = options.IsSubmission ? SourceCodeKind.Script : SourceCodeKind.Regular;

            if (kind == SourceCodeKind.Script && options.EmitDebugInformation)
            {
                // since submission do not have the opening "<?php" tag,
                // add a comment with the opening tag, so source code editors don't get confused and colorize the code properly:
                code = $"#<?php\n{code}";
            }

            // parse the source code
            var tree = PhpSyntaxTree.ParseCode(
                SourceText.From(code, Encoding.UTF8, SourceHashAlgorithm.Sha256),
                new PhpParseOptions(
                    kind: kind,
                    languageVersion: languageVersion,
                    shortOpenTags: shortOpenTags),
                PhpParseOptions.Default,
                options.IsSubmission ? BuildSubmissionFileName(options.Location.Path, name.Name) : options.Location.Path
                );

            var diagnostics = tree.Diagnostics;

            if (!HasErrors(diagnostics))
            {
                // TODO: collect required types from {tree}, remember as a script dependencies
                // TODO: perform class autoload (now before compilation, and then always before invocation)

                // list of scripts that were eval'ed in the context already,
                // our compilation may depend on them
                var dependingSubmissions = previousSubmissions.Where(s => !s.Image.IsDefaultOrEmpty);
                IEnumerable <MetadataReference> metadatareferences
                    = dependingSubmissions.Select(s => MetadataReference.CreateFromImage(s.Image));

                if (options.AdditionalReferences != null)
                {
                    // add additional script references
                    metadatareferences
                        = metadatareferences.Concat(options.AdditionalReferences.Select(r => MetadataReference.CreateFromFile(r)));
                }

                // create the compilation object
                // TODO: add conditionally declared types into the compilation tables
                var compilation = (PhpCompilation)builder.CoreCompilation
                                  .WithLangVersion(languageVersion)
                                  .WithAssemblyName(name.Name)
                                  .AddSyntaxTrees(tree)
                                  .AddReferences(metadatareferences);

                var emitOptions   = new EmitOptions();
                var embeddedTexts = default(IEnumerable <EmbeddedText>);

                if (options.EmitDebugInformation)
                {
                    compilation = compilation.WithPhpOptions(compilation.Options.WithOptimizationLevel(OptimizationLevel.Debug).WithDebugPlusMode(true));
                    emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);

                    if (options.IsSubmission)
                    {
                        embeddedTexts = new[] { EmbeddedText.FromSource(tree.FilePath, tree.GetText()) };
                    }
                }
                else
                {
                    compilation = compilation.WithPhpOptions(compilation.Options.WithOptimizationLevel(OptimizationLevel.Release));
                }

                diagnostics = compilation.GetDeclarationDiagnostics();
                if (!HasErrors(diagnostics))
                {
                    var peStream  = new MemoryStream();
                    var pdbStream = options.EmitDebugInformation ? new MemoryStream() : null;

                    var result = compilation.Emit(peStream,
                                                  pdbStream: pdbStream,
                                                  options: emitOptions,
                                                  embeddedTexts: embeddedTexts
                                                  );

                    if (result.Success)
                    {
                        return(new Script(name, peStream, pdbStream, builder, previousSubmissions));
                    }
                    else
                    {
                        diagnostics = result.Diagnostics;
                    }
                }
            }

            //
            return(CreateInvalid(diagnostics));
        }
示例#8
0
        private CompilerResults CompileWithRoslyn(List <string> filenames, List <string> sources, ICollection <Assembly> referencedAssemblies)
        {
#if ROSLYN
            CompilerResults          cr;
            CSharpCompilationOptions options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
            EmitOptions emitOptions          = new EmitOptions();
            if (includeDebugInformation)
            {
                // Embedded option doesn't seem to work
                // Explanation of options: https://github.com/dotnet/designs/blob/master/accepted/diagnostics/debugging-with-symbols-and-sources.md
                emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
            }
            else
            {
                emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.Embedded);
            }
            if (optimizeCode)
            {
                options = options.WithOptimizationLevel(OptimizationLevel.Release);
            }

            // If running on the Mono VM, disable all warnings in the generated
            // code because these are treated as errors by the Mono compiler.
            if (runningOnMono)
            {
                options = options.WithWarningLevel(0);
            }

            List <MetadataReference> references = new List <MetadataReference>();
            foreach (Assembly assembly in referencedAssemblies)
            {
                try
                {
                    references.Add(MetadataReference.CreateFromFile(assembly.Location));
                }
                catch (NotSupportedException)
                {
                    // do nothing - this assembly does not have a location e.g. it is in memory
                }
                catch (Exception e)
                {
                    Console.WriteLine("Warning, could not add location for assembly: " + assembly);
                    Console.WriteLine(e);
                }
            }
            // we must only add references to assemblies that are actually referenced by the code -- not all the assemblies in memory during model compilation (that could be a much larger set)

            SyntaxTree[] trees;
            if (!writeSourceFiles)
            {
                // Note: Without source files, the debugger cannot step into generated code, even if a pdb is generated.
                // Theoretically, it should be possible to embed the source into the pdb.
                trees = sources.Select(s => CSharpSyntaxTree.ParseText(s, encoding: Encoding.UTF8)).ToArray();
            }
            else
            {
                trees = filenames.Select(fn => CSharpSyntaxTree.ParseText(File.ReadAllText(fn), null, fn, Encoding.UTF8)).ToArray();
            }

            string targetAssemblyPath = "";
            string pdbPath            = "";
            string targetAssemblyName;
            if (!generateInMemory)
            {
                targetAssemblyPath = Path.ChangeExtension(filenames[0], ".dll");
                try
                {
                    if (File.Exists(targetAssemblyPath))
                    {
                        File.Delete(targetAssemblyPath);
                    }
                }
                catch
                {
                    for (int i = 0; ; i++)
                    {
                        targetAssemblyPath = Path.ChangeExtension(Path.ChangeExtension(filenames[0], null) + DateTime.Now.Millisecond, ".dll");
                        try
                        {
                            if (File.Exists(targetAssemblyPath))
                            {
                                File.Delete(targetAssemblyPath);
                            }
                            break;
                        }
                        catch
                        {
                        }
                    }
                }
                targetAssemblyName = Path.GetFileNameWithoutExtension(targetAssemblyPath);
                pdbPath            = Path.ChangeExtension(targetAssemblyPath, ".pdb");
                emitOptions        = emitOptions.WithPdbFilePath(pdbPath);
            }
            else
            {
                targetAssemblyName = Guid.NewGuid().ToString(); // Empty names are not allowed
            }

            Compilation compilation    = CSharpCompilation.Create(targetAssemblyName, trees, references, options);
            Assembly    resultAssembly = null;
            EmitResult  result;
            using (Stream assemblyStream = generateInMemory ? (Stream) new MemoryStream() : File.Create(targetAssemblyPath))
            {
                using (Stream pdbStream = generateInMemory ? (Stream) new MemoryStream() : File.Create(pdbPath))
                {
                    if (emitOptions.DebugInformationFormat == DebugInformationFormat.Embedded)
                    {
                        result = compilation.Emit(assemblyStream, options: emitOptions);
                    }
                    else
                    {
                        result = compilation.Emit(assemblyStream, pdbStream, options: emitOptions);
                    }
                    if (result.Success)
                    {
                        // TODO: allow compiled assemblies to be unloaded
                        assemblyStream.Seek(0, SeekOrigin.Begin);
                        var asmBin = new BinaryReader(assemblyStream).ReadBytes((int)assemblyStream.Length);
                        if (emitOptions.DebugInformationFormat == DebugInformationFormat.Embedded)
                        {
                            resultAssembly = Assembly.Load(asmBin);
                        }
                        else
                        {
                            pdbStream.Seek(0, SeekOrigin.Begin);
                            var pdbBin = new BinaryReader(pdbStream).ReadBytes((int)pdbStream.Length);
                            resultAssembly = Assembly.Load(asmBin, pdbBin);
                        }
                    }
                }
            }
            cr = new CompilerResults(resultAssembly, result.Success, result.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.ToString()).ToList());
            return(cr);
#else
            throw new NotSupportedException("This assembly was compiled without Roslyn support.  To use Roslyn, recompile with the ROSLYN compiler flag.");
#endif
        }
示例#9
0
        private EmitOptions GetEmitOptions(out bool emitPdb)
        {
            var emitOptions = new EmitOptions();

            var usePortablePdbString = Environment.GetEnvironmentVariable(EnvironmentNames.PortablePdb);

            // Use portable pdbs if explicitly specified or the platform doesn't support pdb generation
            var usePortablePdb = string.Equals(usePortablePdbString, "true", StringComparison.OrdinalIgnoreCase) ||
                                 string.Equals(usePortablePdbString, "1", StringComparison.OrdinalIgnoreCase);

            if (usePortablePdb)
            {
                Logger.TraceInformation("Using portable pdb format");

                // Emit the portable pdb format if explicitly specified.
                // TODO: Make a decision about when we use the portable pdb by default.
                // On mono < 4.2 Emitting the portable PDB just hangs for some odd reason.
                emitPdb = true;
                return emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
            }

            // Otherwise, emit the regular pdb format if the platfom supports it
            emitPdb = _supportsPdbGeneration.Value;

            return emitOptions;
        }
示例#10
0
        public bool Compile(
            CompilerProvider compiler, string assname, bool debug,
            IReadOnlyCollection <string> files,
            out ImmutableArray <Diagnostic> diagnostics,
            out byte[] rawassembly, out byte[] rawsymbols)
        {
            rawassembly = null;
            rawsymbols  = null;

            var success = true;
            var trees   = files.Select(f => GetOrAddFile(f)).ToList();

            foreach (var x in trees)
            {
                success &= IsSuccess(x.Diagnostics);
            }

            if (!success)
            {
                diagnostics = trees.SelectMany(x => x.Diagnostics).ToImmutableArray();
                return(false);
            }

            var compilation = compiler.CreateCompilation(assname, trees, debug);

            var analysis = compilation.GetDiagnostics();

            if (IsSuccess(analysis))
            {
                var peStream    = new MemoryStream();
                var pdbStream   = debug ? new MemoryStream() : null;
                var emitOptions = new EmitOptions();

                if (debug)
                {
                    emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
                }

                var result = compilation.Emit(peStream,
                                              pdbStream: pdbStream,
                                              options: emitOptions);

                diagnostics = result.Diagnostics;

                if (result.Success)
                {
                    rawassembly = peStream.ToArray();
                    rawsymbols  = pdbStream?.ToArray();
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                diagnostics = analysis;
                return(false);
            }
        }
示例#11
0
        public static CompilerResults CompileScript(string scriptSetup, string scriptSource, string outputDllFile)
#endif
        {
            var source  = @"# pragma warning disable 0168 // variable declared but not used.
# pragma warning disable 0219 // variable assigned but not used.
# pragma warning disable 0414 // private field assigned but not used.

{using}

namespace HomeGenie.Automation.Scripting
{
    [Serializable]
    public class ScriptingInstance : ScriptingHost
    {
        private void RunCode(string PROGRAM_OPTIONS_STRING)
        {
//////////////////////////////////////////////////////////////////
// NOTE: user code start line is 16 *** please add new code after this method, do not alter start line! ***
{source}
//////////////////////////////////////////////////////////////////
        }

        #pragma warning disable 0162
        private bool SetupCode()
        {
//////////////////////////////////////////////////////////////////
// NOTE: user code start line is ??? *** please add new code after this method, do not alter start line! ***
{setup}
//////////////////////////////////////////////////////////////////
            return false;
        }
        #pragma warning restore 0162

        private HomeGenie.Automation.MethodRunResult Run(string PROGRAM_OPTIONS_STRING)
        {
            Exception ex = null;
            try
            {
                RunCode(PROGRAM_OPTIONS_STRING);
            }
            catch (Exception e)
            {
                ex = e;
            }
            return new HomeGenie.Automation.MethodRunResult(){ Exception = ex, ReturnValue = null };
        }

        private HomeGenie.Automation.MethodRunResult Setup()
        {
            Exception ex = null;
            bool retval = false;
            try
            {
                retval = SetupCode();
            }
            catch (Exception e)
            {
                ex = e;
            }
            return new HomeGenie.Automation.MethodRunResult(){ Exception = ex, ReturnValue = retval };
        }

        public ScriptingHost hg { get { return (ScriptingHost)this; } }
    }
}";
            var usingNs = String.Join(" ", Includes.Select(x => String.Format("using {0};" + Environment.NewLine, x)));

            source = source
                     .Replace("{using}", usingNs)
                     .Replace("{source}", scriptSource)
                     .Replace("{setup}", scriptSetup);
#if NETCOREAPP
            var dotNetCoreDir = Path.GetDirectoryName(typeof(object).GetTypeInfo().Assembly.Location);
            var homeGenieDir  = Path.GetDirectoryName(typeof(HomeGenieService).GetTypeInfo().Assembly.Location);
            var compilation   = CSharpCompilation.Create("a")
                                .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
                                .AddReferences(

                MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enum).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Console).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Queryable).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Uri).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(HttpListener).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(DynamicObject).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Runtime.dll")),
                MetadataReference.CreateFromFile(Assembly.Load("netstandard").Location),
                MetadataReference.CreateFromFile(Assembly.Load("mscorlib").Location),
                MetadataReference.CreateFromFile(typeof(Thread).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Stopwatch).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Windows.dll")),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Threading.Thread.dll")),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Collections.dll")),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Net.dll")),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Net.Primitives.dll")),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Net.NameResolution.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "HomeGenie.dll")),

                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.dll")),
                MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Core.dll")),
                MetadataReference.CreateFromFile(typeof(CSharpArgumentInfo).GetTypeInfo().Assembly.Location),

                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "MIG.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir,
                                                              Path.Combine("lib", "mig", "CM19Lib.dll"))),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "LiteDB.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "NLog.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Newtonsoft.Json.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "SerialPortLib.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "NetClientLib.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "UPnP.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "MQTTnet.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Raspberry.IO.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Raspberry.IO.Components.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Raspberry.IO.GeneralPurpose.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir,
                                                              "Raspberry.IO.InterIntegratedCircuit.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir,
                                                              "Raspberry.IO.SerialPeripheralInterface.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Raspberry.System.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Innovative.Geometry.Angle.dll")),
                MetadataReference.CreateFromFile(Path.Combine(homeGenieDir, "Innovative.SolarCalculator.dll"))
                )
                                .AddSyntaxTrees(CSharpSyntaxTree.ParseText(source));

            var assemblyPdbFile = outputDllFile + ".pdb";
            using var assemblyStream = File.Open(outputDllFile, FileMode.Create, FileAccess.ReadWrite);
            using var pdbStream      = File.Open(assemblyPdbFile, FileMode.Create, FileAccess.ReadWrite);
            var opts = new EmitOptions()
                       .WithPdbFilePath(assemblyPdbFile);
            var pdbStreamHelper = pdbStream;

            if (Environment.OSVersion.Platform == PlatformID.Unix)
            {
                opts = opts.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
            }

            var result = compilation.Emit(assemblyStream, pdbStreamHelper, options: opts);

            if (result.Success)
            {
                // TODO:
            }
            else
            {
                // TODO:
            }
            return(result);
#else
            var providerOptions = new Dictionary <string, string>
            {
                //{ "CompilerVersion", "v4.0" }
            };
            var provider       = new CSharpCodeProvider(providerOptions);
            var compilerParams = new CompilerParameters
            {
                GenerateInMemory        = false,
                GenerateExecutable      = false,
                IncludeDebugInformation = true,
                TreatWarningsAsErrors   = false,
                OutputAssembly          = outputDllFile
                                          // *** Useful for debugging
                                          //,TempFiles = new TempFileCollection {KeepFiles = true}
            };

            // Mono runtime 2/3 compatibility fix
            // TODO: this may not be required anymore
            var relocateSystemAsm = false;
            var type = Type.GetType("Mono.Runtime");
            if (type != null)
            {
                MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
                if (displayName != null)
                {
                    int major;
                    if (Int32.TryParse(displayName.Invoke(null, null).ToString().Substring(0, 1), out major) && major > 2)
                    {
                        relocateSystemAsm = true;
                    }
                }
            }
            if (!relocateSystemAsm)
            {
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                foreach (var assembly in assemblies)
                {
                    var assemblyName = assembly.GetName();
                    switch (assemblyName.Name.ToLower())
                    {
                    case "system":
                        compilerParams.ReferencedAssemblies.Add(assembly.Location);
                        break;

                    case "system.core":
                        compilerParams.ReferencedAssemblies.Add(assembly.Location);
                        break;

                    case "microsoft.csharp":
                        compilerParams.ReferencedAssemblies.Add(assembly.Location);
                        break;
                    }
                }
            }
            else
            {
                compilerParams.ReferencedAssemblies.Add("System.dll");
                compilerParams.ReferencedAssemblies.Add("System.Core.dll");
                compilerParams.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
            }

            compilerParams.ReferencedAssemblies.Add("HomeGenie.exe");
            compilerParams.ReferencedAssemblies.Add("MIG.dll");
            compilerParams.ReferencedAssemblies.Add(Path.Combine("lib", "mig", "CM19Lib.dll"));
            compilerParams.ReferencedAssemblies.Add("LiteDB.dll");
            compilerParams.ReferencedAssemblies.Add("NLog.dll");
            compilerParams.ReferencedAssemblies.Add("Newtonsoft.Json.dll");

            compilerParams.ReferencedAssemblies.Add("SerialPortLib.dll");
            compilerParams.ReferencedAssemblies.Add("NetClientLib.dll");

            compilerParams.ReferencedAssemblies.Add("UPnP.dll");

            compilerParams.ReferencedAssemblies.Add("MQTTnet.dll");

            //if (Raspberry.Board.Current.IsRaspberryPi)
            {
                compilerParams.ReferencedAssemblies.Add("Raspberry.IO.dll");
                compilerParams.ReferencedAssemblies.Add("Raspberry.IO.Components.dll");
                compilerParams.ReferencedAssemblies.Add("Raspberry.IO.GeneralPurpose.dll");
                compilerParams.ReferencedAssemblies.Add("Raspberry.IO.InterIntegratedCircuit.dll");
                compilerParams.ReferencedAssemblies.Add("Raspberry.IO.SerialPeripheralInterface.dll");
                compilerParams.ReferencedAssemblies.Add("Raspberry.System.dll");
            }

            compilerParams.ReferencedAssemblies.Add(Path.Combine("Innovative.Geometry.Angle.dll"));
            compilerParams.ReferencedAssemblies.Add(Path.Combine("Innovative.SolarCalculator.dll"));

            // compile and generate script assembly
            return(provider.CompileAssemblyFromSource(compilerParams, source));
#endif
        }