// 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)); }
/// <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); }
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)); }
/// <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); }
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); }
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); }