Beispiel #1
0
        // publicly accessible routines

        /// <summary>
        /// Builds the compilation for the Q# code or Q# snippet and referenced assemblies defined by the given options.
        /// Invokes all specified targets (dotnet core apps) with suitable TargetOptions,
        /// that in particular specify the path to the compiled binary as input and the same output folder, verbosity, and suppressed warnings as the given options.
        /// The output folder is set to the current directory if one or more targets have been specified but the output folder was left unspecified.
        /// Returns a suitable error code if one of the compilation or generation steps fails.
        /// </summary>
        /// <exception cref="System.ArgumentNullException">If any of the given arguments is null.</exception>
        /// </summary>
        public static int Run(BuildOptions options, ConsoleLogger logger)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            CompilationLoader.BuildTarget DefineTarget(string exeName) => (binary, onException) =>
            {
                var targetOpts = new TargetOptions
                {
                    Input        = new[] { binary },
                    OutputFolder = Path.GetFullPath(options.OutputFolder ?? "."), // GetFullPath is needed for the output folder to be relative to the current folder!
                    Verbose      = options.Verbose,
                    NoWarn       = options.NoWarn,
                };
                var pathToExe       = Path.GetFullPath(exeName);
                var commandLineArgs = $"{pathToExe} {Parser.Default.FormatCommandLine(targetOpts)}";
                var success         = ProcessRunner.Run("dotnet", commandLineArgs, out var output, out var error, out var exitCode, out var ex, timeout: 30000);

                if (ex != null)
                {
                    onException?.Invoke(ex);
                }
                if (exitCode != 0)
                {
                    logger.Log(WarningCode.TargetExitedAbnormally, new[] { exeName, exitCode.ToString() }, pathToExe);
                }
                var(outStr, errStr) = (output.ToString(), error.ToString());
                if (!String.IsNullOrWhiteSpace(outStr))
                {
                    logger.Log(InformationCode.BuildTargetOutput, Enumerable.Empty <string>(), pathToExe, messageParam: outStr);
                }
                if (!String.IsNullOrWhiteSpace(errStr))
                {
                    logger.Log(InformationCode.BuildTargetError, Enumerable.Empty <string>(), pathToExe, messageParam: errStr);
                }
                return(success);
            };

            var specifiesTargets = options.Targets != null && options.Targets.Any();
            var loadOptions      = new CompilationLoader.Configuration
            {
                ProjectFile               = options.ProjectName == null ? null : new Uri(Path.GetFullPath(options.ProjectName)),
                GenerateFunctorSupport    = true,
                SkipSyntaxTreeTrimming    = false,
                DocumentationOutputFolder = options.DocFolder,
                BuildOutputFolder         = options.OutputFolder ?? (specifiesTargets ? "." : null),
                Targets = options.Targets.ToImmutableDictionary(id => id, DefineTarget)
            };

            var loaded = new CompilationLoader(options.LoadSourcesOrSnippet(logger), options.References, loadOptions, logger);

            return(ReturnCode.Status(loaded));
        }
Beispiel #2
0
        /// <summary>
        /// Compiles the given Q# code and returns the list of elements found in it.
        /// Removes all currently tracked source files in the CompilationManager and replaces them with the given ones.
        /// The compiler does this on a best effort, so it will return the elements even if the compilation fails.
        /// If the given references are not null, reloads the references loaded in by the CompilationManager
        /// if the keys of the given references differ from the currently loaded ones.
        /// Returns an enumerable of all namespaces, including the content from both source files and references.
        /// </summary>
        private QsCompilation UpdateCompilation(ImmutableDictionary <Uri, string> sources, QsReferences references = null, QSharpLogger logger = null)
        {
            var loadOptions = new CompilationLoader.Configuration
            {
                GenerateFunctorSupport = true,
            };
            var loaded = new CompilationLoader(_ => sources, _ => references, loadOptions, logger);

            return(loaded.CompilationOutput);
        }
Beispiel #3
0
        private CompilationLoader CreateTemporaryLoader(string source)
        {
            var uri     = new Uri(Path.GetFullPath("__CODE_SNIPPET__.qs"));
            var sources = new Dictionary <Uri, string>()
            {
                { uri, $"namespace {Snippets.SNIPPETS_NAMESPACE} {{ {source} }}" }
            }.ToImmutableDictionary();
            var loadOptions = new CompilationLoader.Configuration();

            return(new CompilationLoader(_ => sources, _ => QsReferences.Empty, loadOptions));
        }
Beispiel #4
0
        /// <summary>
        /// Compiles the given Q# code and returns the list of elements found in it.
        /// The compiler does this on a best effort, so it will return the elements even if the compilation fails.
        /// </summary>
        public IEnumerable <QsNamespaceElement> IdentifyElements(string source)
        {
            var uri = new Uri(Path.GetFullPath("__CODE_SNIPPET__.qs"));
            var ns  = NonNullable <string> .New(Snippets.SNIPPETS_NAMESPACE);

            var sources = new Dictionary <Uri, string>()
            {
                { uri, $"namespace {ns.Value} {{ {source} }}" }
            }.ToImmutableDictionary();
            var loadOptions = new CompilationLoader.Configuration();
            var loaded      = new CompilationLoader(_ => sources, _ => QsReferences.Empty, loadOptions);

            return(loaded.VerifiedCompilation?.SyntaxTree[ns].Elements);
        }
Beispiel #5
0
        private QsCompilation UpdateCompilation(
            ImmutableDictionary <Uri, string> sources,
            QsReferences?references  = null,
            QSharpLogger?logger      = null,
            bool compileAsExecutable = false,
            string?executionTarget   = null,
            AssemblyConstants.RuntimeCapabilities runtimeCapabilities = AssemblyConstants.RuntimeCapabilities.Unknown)
        {
            var loadOptions = new CompilationLoader.Configuration
            {
                GenerateFunctorSupport = true,
                IsExecutable           = compileAsExecutable,
                AssemblyConstants      = new Dictionary <string, string> {
                    [AssemblyConstants.ProcessorArchitecture] = executionTarget ?? string.Empty
                },
                RuntimeCapabilities = runtimeCapabilities
            };
            var loaded = new CompilationLoader(_ => sources, _ => references, loadOptions, logger);

            return(loaded.CompilationOutput);
        }
Beispiel #6
0
        private QsCompilation?UpdateCompilation(
            ImmutableDictionary <Uri, string> sources,
            QsReferences references,
            QSharpLogger?logger                 = null,
            bool compileAsExecutable            = false,
            string?executionTarget              = null,
            RuntimeCapability?runtimeCapability = null)
        {
            var loadOptions = new CompilationLoader.Configuration
            {
                GenerateFunctorSupport = true,
                LoadReferencesBasedOnGeneratedCsharp = string.IsNullOrEmpty(executionTarget), // deserialization of resources in references is only needed if there is an execution target
                IsExecutable      = compileAsExecutable,
                AssemblyConstants = new Dictionary <string, string> {
                    [AssemblyConstants.ProcessorArchitecture] = executionTarget ?? string.Empty
                },
                RuntimeCapability = runtimeCapability ?? RuntimeCapability.FullComputation
            };
            var loaded = new CompilationLoader(_ => sources, _ => references, loadOptions, logger);

            return(loaded.CompilationOutput);
        }