Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
651c836
first draft for some handles for a package containing target specific…
Mar 3, 2020
390908c
That should properly merge options
Mar 3, 2020
2cf5a35
test
Mar 11, 2020
28d6d78
fixing typo
Mar 11, 2020
5a26e21
going with this test
Mar 11, 2020
26d923d
Merge branch 'master' into beheim/targetPackage
bettinaheim Mar 11, 2020
d4b6293
file structure
Mar 11, 2020
ef8f72c
Merge branch 'beheim/targetPackage' of https://github.com/microsoft/q…
Mar 11, 2020
e973d37
let's stick with that
Mar 11, 2020
ade77a8
basic outline for sdk - now we need to distinguish the partner package
Mar 15, 2020
6341cb3
splitting out options merging
Mar 15, 2020
0292bd7
whitespace
Mar 15, 2020
ad5efe1
take exclusive sets into account when merging options
Mar 15, 2020
3ccda80
propagating target package info
Mar 15, 2020
c4df957
Merge branch 'master' into beheim/targetPackage
bettinaheim Mar 15, 2020
d87d398
forgot to adapt a test
Mar 15, 2020
a09b489
Merge branch 'beheim/targetPackage' of https://github.com/microsoft/q…
Mar 15, 2020
fc61704
minor thing
Mar 15, 2020
c65a34a
updates from master
Mar 16, 2020
62da3c1
defining an assembly property with the resolved execution target
Mar 16, 2020
e8e2143
getting updates from master
Mar 18, 2020
06a5292
Merge branch 'master' into beheim/targetPackage
bettinaheim Mar 18, 2020
b6e52de
fixing typos
Mar 18, 2020
87a104a
Merge branch 'master' into beheim/targetPackage
bettinaheim Mar 18, 2020
30035cf
commenting out including partner packages
Mar 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions src/ProjectTemplates/Quantum.App1/Driver.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Threading.Tasks;

using Microsoft.Quantum.Simulation.Core;
using System.Threading.Tasks;
using Microsoft.Quantum.Simulation.Simulators;

namespace Quantum.App1
Expand All @@ -10,10 +7,8 @@ class Driver
{
static async Task Main(string[] args)
{
using (var qsim = new QuantumSimulator())
{
await HelloQ.Run(qsim);
}
using var qsim = new QuantumSimulator();
await HelloQ.Run(qsim);
}
}
}
48 changes: 33 additions & 15 deletions src/QsCompiler/CommandLineTool/Commands/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Microsoft.Quantum.QsCompiler.CommandLineCompiler
public static class BuildCompilation
{
[Verb("build", HelpText = "Builds a compilation unit to run on the Q# quantum simulation framework.")]
public class BuildOptions : Options
public class BuildOptions : CompilationOptions
{
[Usage(ApplicationAlias = "qsCompiler")]
public static IEnumerable<Example> UsageExamples
Expand All @@ -35,7 +35,7 @@ public static IEnumerable<Example> UsageExamples
}

[Option("response-files", Required = true, SetName = RESPONSE_FILES,
HelpText = "Response file(s) providing the command arguments. Required only if no other arguments are specified. This option replaces all other arguments.")]
HelpText = "Response file(s) providing command arguments. Required only if no other arguments are specified. Non-default values for options specified via command line take precedence.")]
public IEnumerable<string> ResponseFiles { get; set; }

[Option('o', "output", Required = false, SetName = CODE_MODE,
Expand All @@ -50,23 +50,37 @@ public static IEnumerable<Example> UsageExamples
HelpText = "Name of the project (needs to be usable as file name).")]
public string ProjectName { get; set; }

[Option("load", Required = false, SetName = CODE_MODE,
HelpText = "[Experimental feature] Path to the .NET Core dll(s) defining additional transformations to include in the compilation process.")]
public IEnumerable<string> Plugins { get; set; }

[Option("trim", Required = false, Default = 1,
HelpText = "[Experimental feature] Integer indicating how much to simplify the syntax tree by eliminating selective abstractions.")]
public int TrimLevel { get; set; }

[Option("emit-dll", Required = false, Default = false, SetName = CODE_MODE,
HelpText = "Specifies whether the compiler should emit a .NET Core dll containing the compiled Q# code.")]
public bool EmitDll { get; set; }

[Option('p', "perf", Required = false, SetName = CODE_MODE,
HelpText = "Destination folder where the output of the performance assessment will be generated.")]
public string PerfFolder { get; set; }


/// <summary>
/// Reads the content of all specified response files and processes it using FromResponseFiles.
/// Updates the settings accordingly, prioritizing already specified non-default values over the values from response-files.
/// Returns true and a new BuildOptions object as out parameter with all the settings from response files incorporated.
/// Returns false if the content of the specified response-files could not be processed.
/// </summary>
internal static bool IncorporateResponseFiles(BuildOptions options, out BuildOptions incorporated)
{
incorporated = null;
while (options.ResponseFiles != null && options.ResponseFiles.Any())
{
var fromResponseFiles = FromResponseFiles(options.ResponseFiles);
if (fromResponseFiles == null) return false;
fromResponseFiles.UpdateSetIndependentSettings(options);
options = fromResponseFiles;
}
incorporated = options;
return true;
}
}


/// <summary>
/// Given a string representing the command line arguments, splits them into a suitable string array.
/// </summary>
Expand Down Expand Up @@ -120,15 +134,19 @@ public static int Run(BuildOptions options, ConsoleLogger logger)
{
if (options == null) throw new ArgumentNullException(nameof(options));
if (logger == null) throw new ArgumentNullException(nameof(logger));

if (options?.ResponseFiles != null && options.ResponseFiles.Any())
{ options = FromResponseFiles(options.ResponseFiles); }
if (options == null) return ReturnCode.INVALID_ARGUMENTS;
if (!BuildOptions.IncorporateResponseFiles(options, out options)) return ReturnCode.INVALID_ARGUMENTS;

var usesPlugins = options.Plugins != null && options.Plugins.Any();
if (!options.ParseAssemblyProperties(out var assemblyConstants))
{
logger.Log(WarningCode.InvalidAssemblyProperties, new string[0]);
}

var loadOptions = new CompilationLoader.Configuration
{
ProjectName = options.ProjectName,
AssemblyConstants = assemblyConstants,
TargetPackageAssembly = options.GetTargetPackageAssemblyPath(logger),
GenerateFunctorSupport = true,
SkipSyntaxTreeTrimming = options.TrimLevel == 0,
ConvertClassicalControl = options.TrimLevel >= 2,
Expand All @@ -154,7 +172,7 @@ public static int Run(BuildOptions options, ConsoleLogger logger)
}
catch (Exception ex)
{
logger.Log(ErrorCode.PublishingPerfResultsFailed, new string[]{options.PerfFolder});
logger.Log(ErrorCode.PublishingPerfResultsFailed, new string[]{ options.PerfFolder });
logger.Log(ex);
}
}
Expand Down
21 changes: 10 additions & 11 deletions src/QsCompiler/CommandLineTool/Commands/Diagnose.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Microsoft.Quantum.QsCompiler.CommandLineCompiler
public static class DiagnoseCompilation
{
[Verb("diagnose", HelpText = "Generates intermediate representations of the code to help diagnose issues.")]
public class DiagnoseOptions : Options
public class DiagnoseOptions : CompilationOptions
{
[Usage(ApplicationAlias = "qsCompiler")]
public static IEnumerable<Example> UsageExamples
Expand Down Expand Up @@ -56,14 +56,6 @@ public static IEnumerable<Example> UsageExamples
[Option("code", Required = false, Default = false,
HelpText = "Specifies whether to print the Q# code generated based on the built syntax tree.")]
public bool PrintCompiledCode { get; set; }

[Option("trim", Required = false, Default = 1,
HelpText = "[Experimental feature] Integer indicating how much to simplify the syntax tree by eliminating selective abstractions.")]
public int TrimLevel { get; set; }

[Option("load", Required = false, SetName = CODE_MODE,
HelpText = "[Experimental feature] Path to the .NET Core dll(s) defining additional transformations to include in the compilation process.")]
public IEnumerable<string> Plugins { get; set; }
}

/// <summary>
Expand Down Expand Up @@ -136,7 +128,7 @@ private static void PrintContentTokenization(Compilation compilation, ILogger lo
private static void PrintSyntaxTree(IEnumerable<QsNamespace> evaluatedTree, Compilation compilation, ILogger logger)
{
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
evaluatedTree = evaluatedTree ?? compilation.SyntaxTree.Values;
evaluatedTree ??= compilation.SyntaxTree.Values;

foreach (var file in compilation.SourceFiles)
{
Expand Down Expand Up @@ -166,7 +158,7 @@ void PrintTree(string serialization) => logger.Log(
private static void PrintGeneratedQs(IEnumerable<QsNamespace> evaluatedTree, Compilation compilation, ILogger logger)
{
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
evaluatedTree = evaluatedTree ?? compilation.SyntaxTree.Values;
evaluatedTree ??= compilation.SyntaxTree.Values;

foreach (var file in compilation.SourceFiles)
{
Expand Down Expand Up @@ -217,8 +209,15 @@ public static int Run(DiagnoseOptions options, ConsoleLogger logger)
if (options == null) throw new ArgumentNullException(nameof(options));
if (logger == null) throw new ArgumentNullException(nameof(logger));

if (!options.ParseAssemblyProperties(out var assemblyConstants))
{
logger.Log(WarningCode.InvalidAssemblyProperties, new string[0]);
}

var loadOptions = new CompilationLoader.Configuration
{
AssemblyConstants = assemblyConstants,
TargetPackageAssembly = options.GetTargetPackageAssemblyPath(logger),
GenerateFunctorSupport = true,
SkipSyntaxTreeTrimming = options.TrimLevel == 0,
ConvertClassicalControl = options.TrimLevel >= 2,
Expand Down
115 changes: 101 additions & 14 deletions src/QsCompiler/CommandLineTool/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,81 @@

namespace Microsoft.Quantum.QsCompiler.CommandLineCompiler
{
/// <summary>
/// Default values for command line options if nothing is specified.
/// </summary>
internal static class DefaultOptions
{
public const string Verbosity = "normal";
public const Options.LogFormat OutputFormat = Options.LogFormat.Default;
public const int TrimLevel = 1;
}


public class CompilationOptions : Options
{
[Option("trim", Required = false, Default = DefaultOptions.TrimLevel, SetName = CODE_MODE,
HelpText = "[Experimental feature] Integer indicating how much to simplify the syntax tree by eliminating selective abstractions.")]
public int TrimLevel { get; set; }

[Option("load", Required = false, SetName = CODE_MODE,
HelpText = "[Experimental feature] Path to the .NET Core dll(s) defining additional transformations to include in the compilation process.")]
public IEnumerable<string> Plugins { get; set; }

[Option("target-package", Required = false, SetName = CODE_MODE,
HelpText = "Path to the NuGet package containing target specific information and implementations.")]
public string TargetPackage { get; set; }

[Option('p', "assembly-properties", Required = false, SetName = CODE_MODE,
HelpText = "Additional properties to populate the AssemblyConstants dictionary with. Each item is expected to be of the form \"key=value\".")]
public IEnumerable<string> AdditionalAssemblyProperties { get; set; }

/// <summary>
/// Returns a dictionary with the specified assembly properties as out parameter.
/// Returns a boolean indicating whether all specified properties were successfully added.
/// </summary>
internal bool ParseAssemblyProperties(out Dictionary<string, string> parsed)
{
var success = true;
parsed = new Dictionary<string, string>();
foreach (var keyValue in this.AdditionalAssemblyProperties ?? new string[0])
{
var pieces = keyValue?.Split("=");
var valid = pieces != null && pieces.Length == 2;
success = valid && parsed.TryAdd(pieces[0].Trim().Trim('"'), pieces[1].Trim().Trim('"')) && success;
}
return success;
}

/// <summary>
/// Returns null if TargetPackage is null or empty, and
/// returns the path to the assembly containing target specific implementations otherwise.
/// If a logger is specified, logs suitable diagnostics if a TargetPackages is not null or empty,
/// but no path to the target package assembly could be determined.
/// This may be the case if no directory at the TargetPackage location exists, or if its files can't be accessed,
/// or more than one dll matches the pattern by which the target package assembly is identified.
/// </summary>
public string GetTargetPackageAssemblyPath(ILogger logger = null)
{
if (String.IsNullOrEmpty(this.TargetPackage)) return null;
try
{
// Disclaimer: we may revise that in the future.
var targetPackageAssembly = Directory.GetFiles(this.TargetPackage, "*Intrinsics.dll", SearchOption.AllDirectories).SingleOrDefault();
if (targetPackageAssembly != null) return targetPackageAssembly;
}
catch (Exception ex)
{
if (Directory.Exists(this.TargetPackage)) logger?.Log(ex);
else logger?.Log(ErrorCode.CouldNotFindTargetPackage, new[] { this.TargetPackage });
}

logger?.Log(ErrorCode.CouldNotFindTargetPackageAssembly, new[] { this.TargetPackage });
return null;
}
}


public class Options
{
public enum LogFormat
Expand All @@ -30,10 +105,14 @@ public enum LogFormat
protected const string SNIPPET_MODE = "snippetMode";
protected const string RESPONSE_FILES = "responseFiles";

[Option('v', "verbosity", Required = false, Default = "normal",
[Option('v', "verbosity", Required = false, Default = DefaultOptions.Verbosity,
HelpText = "Specifies the verbosity of the logged output. Valid values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].")]
public string Verbosity { get; set; }

[Option("format", Required = false, Default = DefaultOptions.OutputFormat,
HelpText = "Specifies the output format of the command line compiler.")]
public LogFormat OutputFormat { get; set; }

[Option('i', "input", Required = true, SetName = CODE_MODE,
HelpText = "Q# code or name of the Q# file to compile.")]
public IEnumerable<string> Input { get; set; }
Expand All @@ -54,15 +133,25 @@ public enum LogFormat
HelpText = "Warnings with the given code(s) will be ignored.")]
public IEnumerable<int> NoWarn { get; set; }

[Option("format", Required = false, Default = LogFormat.Default,
HelpText = "Specifies the output format of the command line compiler.")]
public LogFormat OutputFormat { get; set; }

[Option("package-load-fallback-folders", Required = false, SetName = CODE_MODE,
HelpText = "Specifies the directories the compiler will search when a rewrite step dependency could not be found.")]
HelpText = "Specifies the directories the compiler will search when a compiler dependency could not be found.")]
public IEnumerable<string> PackageLoadFallbackFolders { get; set; }


/// <summary>
/// Updates the settings that can be used independent on the other arguments according to the setting in the given options.
/// Already specified non-default values are prioritized over the values in the given options,
/// unless overwriteNonDefaultValues is set to true. Sequences are merged.
/// </summary>
internal void UpdateSetIndependentSettings(Options updates, bool overwriteNonDefaultValues = false)
{
this.Verbosity = overwriteNonDefaultValues || this.Verbosity == DefaultOptions.Verbosity ? updates.Verbosity : this.Verbosity;
this.OutputFormat = overwriteNonDefaultValues || this.OutputFormat == DefaultOptions.OutputFormat ? updates.OutputFormat : this.OutputFormat;
this.NoWarn = (this.NoWarn ?? new int[0]).Concat(updates.NoWarn ?? new int[0]);
this.References = (this.References ?? new string[0]).Concat(updates.References ?? new string[0]);
}


// routines related to logging

/// <summary>
Expand All @@ -87,15 +176,13 @@ string value(PropertyInfo p)
/// <summary>
/// Given a LogFormat, returns a suitable routing for formatting diagnostics.
/// </summary>
internal static Func<Diagnostic, string> LoggingFormat(LogFormat format)
{
switch (format)
internal static Func<Diagnostic, string> LoggingFormat(LogFormat format) =>
format switch
{
case LogFormat.MsBuild: return Formatting.MsBuildFormat;
case LogFormat.Default: return Formatting.HumanReadableFormat;
default: throw new NotImplementedException("unknown output format for logger");
}
}
LogFormat.MsBuild => Formatting.MsBuildFormat,
LogFormat.Default => Formatting.HumanReadableFormat,
_ => throw new NotImplementedException("unknown output format for logger"),
};

/// <summary>
/// Creates a suitable logger for the given command line options,
Expand Down
Loading