Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Changes from all commits
Commits
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
65 changes: 49 additions & 16 deletions src/QuantumSdk/Tools/BuildConfiguration/Generate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,28 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;


namespace Microsoft.Quantum.Sdk.Tools
{
public static partial class BuildConfiguration
{
/// <summary>
/// Assembly names that are not compatible with the Q# compiler when loaded as a plugin.
/// </summary>
private static readonly IReadOnlyCollection<string> IncompatibleQscReferences = new[]
{
// TODO: This is to work around an assembly that is included with the C# generation package, but which
// can't be loaded as a compiler reference. If the SDK gains support for packages containing a combination
// of assemblies that can be loaded as rewrite steps and those that can't, this should be removed.
//
// See: https://github.com/microsoft/qsharp-compiler/issues/435
"Microsoft.Quantum.CsharpGeneration.EntryPointDriver.dll"
};

/// <summary>
/// Generates a suitable configuration file for the Q# compiler based on the given options.
/// Encountered exceptions are logged to the console, and indicated by the returned status.
Expand All @@ -24,21 +37,12 @@ public static ReturnCode Generate(Options options)
"diagnostic".Equals(options.Verbosity, StringComparison.InvariantCultureIgnoreCase) ||
"diag".Equals(options.Verbosity, StringComparison.InvariantCultureIgnoreCase);

static (string, int) ParseQscReference(string qscRef)
{
var pieces = qscRef.Trim().TrimStart('(').TrimEnd(')').Split(',');
var path = pieces.First().Trim();
return (path, Int32.TryParse(pieces.Skip(1).SingleOrDefault(), out var priority) ? priority : 0);
}

var qscReferences = options.QscReferences?.ToArray() ?? new string[0];
var orderedQscReferences = new string[0];
IEnumerable<string> compatibleQscReferences;
IEnumerable<string> incompatibleQscReferences;
try
{
orderedQscReferences = qscReferences
.Select(ParseQscReference)
.OrderByDescending(qscRef => qscRef.Item2)
.Select(qscRef => qscRef.Item1).ToArray();
(compatibleQscReferences, incompatibleQscReferences) =
ParseQscReferences(options.QscReferences ?? Array.Empty<string>());
}
catch (Exception ex)
{
Expand All @@ -49,16 +53,45 @@ public static ReturnCode Generate(Options options)
return ReturnCode.INVALID_ARGUMENTS;
}

return BuildConfiguration.WriteConfigFile(options.OutputFile, orderedQscReferences, verbose)
if (verbose)
{
foreach (var reference in incompatibleQscReferences)
{
Console.Error.WriteLine($"Skipped incompatible QSC reference: {reference}");
}
}
return WriteConfigFile(options.OutputFile, compatibleQscReferences, verbose)
? ReturnCode.SUCCESS
: ReturnCode.IO_EXCEPTION;
}

/// <summary>
/// Parses the QSC reference strings in the format "(path, priority)" and partitions them into compatible and
/// incompatible references.
/// </summary>
/// <param name="qscReferences">The QSC reference strings to parse.</param>
/// <returns>A tuple of compatible and incompatible QSC references.</returns>
private static (IEnumerable<string>, IEnumerable<string>) ParseQscReferences(IEnumerable<string> qscReferences)
{
static (string, int) ParseQscReference(string qscRef)
{
var pieces = qscRef.Trim().TrimStart('(').TrimEnd(')').Split(',');
var path = pieces.First().Trim();
return (path, int.TryParse(pieces.Skip(1).SingleOrDefault(), out var priority) ? priority : 0);
}
var compatible = qscReferences
.Select(ParseQscReference)
.OrderByDescending(qscRef => qscRef.Item2)
.Select(qscRef => qscRef.Item1)
.ToLookup(qscRef => !IncompatibleQscReferences.Contains(Path.GetFileName(qscRef)));
return (compatible[true], compatible[false]);
}

/// <summary>
/// Work in progress:
/// The signature and output of this method will change in the future.
/// </summary>
private static bool WriteConfigFile(string configFile, string[] qscReferences, bool verbose = false)
private static bool WriteConfigFile(string configFile, IEnumerable<string> qscReferences, bool verbose = false)
{
try
{
Expand Down