diff --git a/.gitignore b/.gitignore
index e1cb5a9ea3f..96ada8e2b36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -336,10 +336,16 @@ ASALocalRun/
# MFractors (Xamarin productivity tool) working folder
.mfractor/
+
/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/built
+/src/Simulation/Simulators.Tests/TestProjects/QirExe/qir
/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/built
+
dbw_test
+# out folders
+out/
+
# Jupyter caches
.ipynb_checkpoints
diff --git a/Simulation.sln b/Simulation.sln
index a540b7cb492..5d4f6e60d76 100644
--- a/Simulation.sln
+++ b/Simulation.sln
@@ -103,11 +103,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandaloneInputReference",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-standalone-input-reference", "src\Qir\Samples\StandaloneInputReference\qsharp\qir-standalone-input-reference.csproj", "{D7D34736-A719-4B45-A33F-2723F59EC29D}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Quantum.AutoSubstitution", "src\Simulation\AutoSubstitution\Microsoft.Quantum.AutoSubstitution.csproj", "{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Execution", "Execution", "{442E66C8-F69F-44E9-9CD9-1F52C37EA41B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools\Microsoft.Quantum.Qir.Tools.csproj", "{C60226E3-98DE-4E92-AED4-B4A93D4CA063}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools.Tests\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirExe", "src\Simulation\Simulators.Tests\TestProjects\QirExe\QirExe.csproj", "{A0B98D0E-FC28-4FD8-8806-4825B9F5489D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.CommandLineTool", "src\Qir\Execution\CommandLineTool\Microsoft.Quantum.Qir.CommandLineTool.csproj", "{EAABB911-02EE-4A05-B566-0084013FC5CD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.AutoSubstitution", "src\Simulation\AutoSubstitution\Microsoft.Quantum.AutoSubstitution.csproj", "{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.AutoSubstitution", "src\Simulation\AutoSubstitution.Tests\Tests.Microsoft.Quantum.AutoSubstitution.csproj", "{4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Microsoft.Quantum.AutoSubstitution.Integration", "src\Simulation\AutoSubstitution.Integration.Tests\Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj", "{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.AutoSubstitution.Integration", "src\Simulation\AutoSubstitution.Integration.Tests\Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj", "{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -681,6 +691,70 @@ Global
{D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
{D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|x64.Build.0 = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|x64.ActiveCfg = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|x64.Build.0 = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|x64.Build.0 = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|x64.ActiveCfg = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|x64.Build.0 = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|x64.Build.0 = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|x64.ActiveCfg = Release|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|x64.Build.0 = Release|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|x64.Build.0 = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|x64.ActiveCfg = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|x64.Build.0 = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
+ {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -777,6 +851,11 @@ Global
{AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567}
{A7DB7367-9FD6-4164-8263-A05077BE54AB} = {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A}
{D7D34736-A719-4B45-A33F-2723F59EC29D} = {A7DB7367-9FD6-4164-8263-A05077BE54AB}
+ {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567}
+ {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B}
+ {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B}
+ {A0B98D0E-FC28-4FD8-8806-4825B9F5489D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820}
+ {EAABB911-02EE-4A05-B566-0084013FC5CD} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B}
{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4}
{4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4}
{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4}
diff --git a/build/manifest.ps1 b/build/manifest.ps1
index 5de30d17b65..6b45da5bc5f 100644
--- a/build/manifest.ps1
+++ b/build/manifest.ps1
@@ -26,6 +26,7 @@ $artifacts = @{
"Microsoft.Quantum.Type1.Core",
"Microsoft.Quantum.Type2.Core",
"Microsoft.Quantum.Type3.Core",
+ "Microsoft.Quantum.Qir.Tools",
"Microsoft.Quantum.QSharp.Foundation"
"Microsoft.Quantum.Runtime.Core",
"Microsoft.Quantum.Simulators",
@@ -35,6 +36,7 @@ $artifacts = @{
Assemblies = @(
".\src\Azure\Azure.Quantum.Client\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Azure.Quantum.Client.dll",
".\src\Simulation\AutoSubstitution\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.AutoSubstitution.dll",
+ ".\src\Qir\Execution\Tools\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Qir.Tools.dll",
".\src\Simulation\Core\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Runtime.Core.dll",
".\src\Simulation\EntryPointDriver\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.EntryPointDriver.dll",
".\src\Simulation\QSharpCore\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QSharp.Core.dll",
diff --git a/build/pack.ps1 b/build/pack.ps1
index fab179be420..9b17a17a264 100644
--- a/build/pack.ps1
+++ b/build/pack.ps1
@@ -163,12 +163,16 @@ Pack-Dotnet '../src/Simulation/QSharpCore/Microsoft.Quantum.QSharp.Core.csproj'
Pack-Dotnet '../src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj'
Pack-Dotnet '../src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj'
Pack-Dotnet '../src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj'
+Pack-Dotnet '../src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj' -ForcePrerelease
+Pack-Dotnet '../src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj' -ForcePrerelease
Pack-One '../src/Simulation/Simulators/Microsoft.Quantum.Simulators.nuspec'
Pack-One '../src/Xunit/Microsoft.Quantum.Xunit.csproj'
Pack-Crate -PackageDirectory "../src/Simulation/qdk_sim_rs" -OutPath $Env:CRATE_OUTDIR;
Pack-Wheel -PackageDirectory "../src/Simulation/qdk_sim_rs" -OutPath $Env:WHEEL_OUTDIR;
Pack-One '../src/Qir/Runtime/Microsoft.Quantum.Qir.Runtime.nuspec' -ForcePrerelease
+Move-Item -Path (Join-Path $Env:NUGET_OUTDIR Microsoft.Quantum.Qir.CommandLineTool.*) -Destination $Env:INTERNAL_TOOLS_OUTDIR
+
if (-not $all_ok) {
throw "At least one project failed to pack. Check the logs."
}
diff --git a/build/set-env.ps1 b/build/set-env.ps1
index 1173a7a0a07..69808d051e6 100644
--- a/build/set-env.ps1
+++ b/build/set-env.ps1
@@ -25,6 +25,8 @@ if ($Env:DROP_NATIVE -eq $null) {
$Env:DROP_NATIVE = (Join-Path $PSScriptRoot "..")
}
+If ($Env:INTERNAL_TOOLS_OUTDIR -eq $null) { $Env:INTERNAL_TOOLS_OUTDIR = (Join-Path $Env:DROPS_DIR "internal_tools") }
+If (-not (Test-Path -Path $Env:INTERNAL_TOOLS_OUTDIR)) { [IO.Directory]::CreateDirectory($Env:INTERNAL_TOOLS_OUTDIR) }
If ($Env:NUGET_OUTDIR -eq $null) { $Env:NUGET_OUTDIR = (Join-Path $Env:DROPS_DIR "nugets") }
If (-not (Test-Path -Path $Env:NUGET_OUTDIR)) { [IO.Directory]::CreateDirectory($Env:NUGET_OUTDIR) }
diff --git a/build/test.ps1 b/build/test.ps1
index 76d614af61c..211c5931bd6 100644
--- a/build/test.ps1
+++ b/build/test.ps1
@@ -43,11 +43,13 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false") {
if ($LastExitCode -ne 0) {
$script:all_ok = $False
}
+
$qirTests = (Join-Path $PSScriptRoot "../src/Qir/Tests")
& "$qirTests/test-qir-tests.ps1"
if ($LastExitCode -ne 0) {
$script:all_ok = $False
}
+
$qirSamples = (Join-Path $PSScriptRoot "../src/Qir/Samples")
& "$qirSamples/test-qir-samples.ps1"
if ($LastExitCode -ne 0) {
diff --git a/global.json b/global.json
index 62bca5f3c81..b1cbde009e2 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,5 @@
{
"msbuild-sdks": {
- "Microsoft.Quantum.Sdk": "0.18.2106149090-alpha"
+ "Microsoft.Quantum.Sdk": "0.18.2107150698-alpha"
}
}
diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
index cd61dd5ce49..98dfab392f9 100644
--- a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
+++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
@@ -17,6 +17,7 @@ public static class QuantumMachineFactory
/// The execution target for job submission.
/// The connection string for the Azure storage account.
/// A quantum machine for job submission targeting targetName.
+ [Obsolete("Use SubmitterFactory.QSharpSubmitter.")]
public static IQuantumMachine? CreateMachine(
IWorkspace workspace, string targetName, string? storageConnectionString = null)
{
diff --git a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj
index 28a0ded1164..5585bc6f1b4 100644
--- a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj
+++ b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj
@@ -6,6 +6,7 @@
netstandard2.1
x64
Client library for Azure Quantum.
+ Microsoft.Azure.Quantum
diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs
new file mode 100644
index 00000000000..d4e303cf707
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#nullable enable
+
+namespace Microsoft.Azure.Quantum
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.Immutable;
+ using System.Linq;
+ using System.Reflection;
+ using System.Text.RegularExpressions;
+ using Microsoft.Quantum.Runtime.Submitters;
+
+ ///
+ /// Creates Azure Quantum submitters for specific targets.
+ ///
+ public static class SubmitterFactory
+ {
+ ///
+ /// Information about each supported QIR submitter.
+ ///
+ private static readonly ImmutableList QirSubmitters = ImmutableList.Create(
+ new SubmitterInfo(
+ new Regex(@"\Amicrosoft\.simulator\.([\w]+\.)*[\w]+\z"),
+ "Microsoft.Quantum.Providers.Targets.MicrosoftSimulatorSubmitter, Microsoft.Quantum.Providers.Core",
+ "QirSubmitter"));
+
+ ///
+ /// Information about each supported Q# submitter.
+ ///
+ private static readonly ImmutableList QSharpSubmitters = ImmutableList.Empty;
+
+ ///
+ /// Returns a QIR submitter.
+ ///
+ /// The name of the execution target.
+ /// The workspace used to manage jobs.
+ /// The connection string for the storage account.
+ /// A QIR submitter.
+ public static IQirSubmitter? QirSubmitter(string target, IWorkspace workspace, string? storageConnection) =>
+ Submitter(QirSubmitters, target, workspace, storageConnection);
+
+ ///
+ /// Returns a Q# submitter.
+ ///
+ /// The name of the execution target.
+ /// The workspace used to manage jobs.
+ /// The connection string for the storage account.
+ /// A Q# submitter.
+ public static IQSharpSubmitter? QSharpSubmitter(
+ string target, IWorkspace workspace, string? storageConnection) =>
+ Submitter(QSharpSubmitters, target, workspace, storageConnection);
+
+ ///
+ /// Returns an instance of a submitter from the given list that matches the target.
+ ///
+ /// Information about each submitter.
+ /// The name of the execution target.
+ /// The workspace used to manage jobs.
+ /// The connection string for the storage account.
+ /// The type of the submitter interface.
+ /// The submitter instance.
+ private static T? Submitter(
+ IEnumerable submitters, string target, IWorkspace workspace, string? storageConnection)
+ where T : class
+ {
+ var submitter = submitters.FirstOrDefault(s => s.TargetPattern.IsMatch(target));
+ if (submitter is null)
+ {
+ return null;
+ }
+
+ var type = QdkType(submitter.TypeName);
+ var args = new object?[] { target, workspace, storageConnection };
+ return (T)type.InvokeMember(
+ submitter.MethodName, BindingFlags.InvokeMethod, Type.DefaultBinder, null, args);
+ }
+
+ ///
+ /// Returns a type from a QDK assembly given its type name.
+ ///
+ /// The fully-qualified or assembly-qualified type name.
+ /// The type.
+ private static Type QdkType(string name)
+ {
+ var version = Assembly.GetExecutingAssembly().GetName().Version;
+ var strongName = $"{name}, Version={version}, Culture=neutral, PublicKeyToken=40866b40fd95c7f5";
+ return Type.GetType(strongName, true);
+ }
+
+ ///
+ /// Information about a submitter.
+ ///
+ private class SubmitterInfo
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The pattern for targets supported by the submitter.
+ /// The fully-qualified or assembly-qualified name of the submitter type.
+ /// The name of the static factory method.
+ public SubmitterInfo(Regex targetPattern, string typeName, string methodName) =>
+ (TargetPattern, TypeName, MethodName) = (targetPattern, typeName, methodName);
+
+ ///
+ /// The pattern for targets supported by the submitter.
+ ///
+ public Regex TargetPattern { get; }
+
+ ///
+ /// The fully-qualified or assembly-qualified name of the submitter type.
+ ///
+ public string TypeName { get; }
+
+ ///
+ /// The name of the static factory method.
+ ///
+ public string MethodName { get; }
+ }
+ }
+}
diff --git a/src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj b/src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj
new file mode 100644
index 00000000000..95fd980a0ec
--- /dev/null
+++ b/src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+ qir-cli
+ Command-line tool for interacting with QIR.
+ Quantum QIR
+
+
+
+
+
+
+
+
diff --git a/src/Qir/Execution/CommandLineTool/Program.cs b/src/Qir/Execution/CommandLineTool/Program.cs
new file mode 100644
index 00000000000..9ffd39908bb
--- /dev/null
+++ b/src/Qir/Execution/CommandLineTool/Program.cs
@@ -0,0 +1,150 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.CommandLine;
+using System.CommandLine.Builder;
+using System.CommandLine.Help;
+using System.CommandLine.Invocation;
+using System.CommandLine.Parsing;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Quantum.Qir.Tools;
+
+namespace Microsoft.Quantum.Qir.CommandLineTool
+{
+ class Program
+ {
+ private static async Task Main(string[] args)
+ {
+ var buildCommand = CreateBuildCommand();
+
+ var root = new RootCommand() { buildCommand };
+ SetSubCommandAsDefault(root, buildCommand);
+ root.Description = "Command-line tool for processing QIR DLL files.";
+ root.TreatUnmatchedTokensAsErrors = true;
+
+ Console.OutputEncoding = Encoding.UTF8;
+ return await new CommandLineBuilder(root)
+ .UseDefaults()
+ .UseHelpBuilder(context => new QsHelpBuilder(context.Console))
+ .Build()
+ .InvokeAsync(args);
+ }
+
+ ///
+ /// Creates the Build command for the command line compiler, which is used to
+ /// compile the executables from a given QIR DLL.
+ ///
+ /// The Build command.
+ private static Command CreateBuildCommand()
+ {
+ var buildCommand = new Command("build", "(default) Build the executables from a QIR DLL.")
+ {
+ Handler = CommandHandler.Create((BuildOptions settings) =>
+ QirTools.BuildFromQSharpDll(settings.QSharpDll, settings.LibraryDirectories, settings.IncludeDirectories, settings.ExecutablesDirectory))
+ };
+ buildCommand.TreatUnmatchedTokensAsErrors = true;
+
+ buildCommand.AddOption(new Option(
+ aliases: new string[] { "--qsharp-dll", "--dll" },
+ description: "The path to the .NET DLL file generated by the Q# compiler.")
+ {
+ Required = true
+ });
+
+ buildCommand.AddOption(new Option(
+ aliases: new string[] { "--library-directories", "--lib" },
+ description: "One or more paths to the directories containing the libraries to be linked.")
+ {
+ Required = false,
+ Argument = new Argument(() => new DirectoryInfo[] { })
+ {
+ Arity = ArgumentArity.OneOrMore
+ }
+ });
+
+ buildCommand.AddOption(new Option(
+ aliases: new string[] { "--include-directories", "--include" },
+ description: "One or more paths to the directories containing the headers required for compilation.")
+ {
+ Required = false,
+ Argument = new Argument(() => new DirectoryInfo[] { })
+ {
+ Arity = ArgumentArity.OneOrMore
+ }
+ });
+
+ buildCommand.AddOption(new Option(
+ aliases: new string[] { "--executables-directory", "--exe" },
+ description: "The path to the output directory where the created executables will be placed.")
+ {
+ Required = true
+ });
+
+ return buildCommand;
+ }
+
+ ///
+ /// Copies the handle and options from the given sub command to the given command.
+ ///
+ /// The command whose handle and options will be set.
+ /// The sub command that will be copied from.
+ private static void SetSubCommandAsDefault(Command root, Command subCommand)
+ {
+ root.Handler = subCommand.Handler;
+ foreach (var option in subCommand.Options)
+ {
+ root.AddOption(option);
+ }
+ }
+
+ ///
+ /// A modification of the command-line class.
+ ///
+ private sealed class QsHelpBuilder : HelpBuilder
+ {
+ ///
+ /// Creates a new help builder using the given console.
+ ///
+ /// The console to use.
+ internal QsHelpBuilder(IConsole console) : base(console)
+ {
+ }
+
+ protected override string ArgumentDescriptor(IArgument argument)
+ {
+ // Hide long argument descriptors.
+ var descriptor = base.ArgumentDescriptor(argument);
+ return descriptor.Length > 30 ? argument.Name : descriptor;
+ }
+ }
+
+ ///
+ /// A class for encapsulating the different options for the build command.
+ ///
+ public sealed class BuildOptions
+ {
+ ///
+ /// The path to the .NET DLL file generated by the Q# compiler.
+ ///
+ public FileInfo QSharpDll { get; set; }
+
+ ///
+ /// One or more paths to the directories containing the libraries to be linked.
+ ///
+ public DirectoryInfo[] LibraryDirectories { get; set; }
+
+ ///
+ /// One or more paths to the directories containing the headers required for compilation.
+ ///
+ public DirectoryInfo[] IncludeDirectories { get; set; }
+
+ ///
+ /// The path to the output directory where the created executables will be placed.
+ ///
+ public DirectoryInfo ExecutablesDirectory { get; set; }
+ }
+ }
+}
diff --git a/src/Qir/Execution/Tools.Tests/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tools.Tests/QirDriverGeneratorTests.cs
new file mode 100644
index 00000000000..ece6d0e22fd
--- /dev/null
+++ b/src/Qir/Execution/Tools.Tests/QirDriverGeneratorTests.cs
@@ -0,0 +1,180 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+using Xunit;
+
+using Microsoft.Quantum.Qir.Tools.Driver;
+using Microsoft.Quantum.Qir.Serialization;
+
+namespace Tests.Microsoft.Quantum.Qir.Tools
+{
+ public class QirDriverGeneratorTests
+ {
+ private static string TestArtifactsDirectory = Path.Combine("TestArtifacts", "FullStateDriverGenerator");
+ private static string TestCasesDirectory = Path.Combine("TestCases", "FullStateDriverGenerator");
+ private static IDictionary TestCases =
+ new Dictionary
+ {
+ {
+ "UseNoArgs",
+ new EntryPointOperation{Name = "UseNoArgs"}
+ },
+ {
+ "UseBoolArg",
+ new EntryPointOperation
+ {
+ Name = "UseBoolArg",
+ Parameters = new List{new Parameter{ Name = "BoolArg", Type = DataType.BoolType}}
+ }
+ },
+ {
+ "UseBoolArrayArg",
+ new EntryPointOperation
+ {
+ Name = "UseBoolArrayArg",
+ Parameters = new List{new Parameter{ Name = "BoolArrayArg", Type = DataType.ArrayType, ArrayType = DataType.BoolType}}
+ }
+ },
+ {
+ "UseDoubleArg",
+ new EntryPointOperation
+ {
+ Name = "UseDoublArg",
+ Parameters = new List{new Parameter{ Name = "DoubleArg", Type = DataType.DoubleType}}
+ }
+ },
+ {
+ "UseDoubleArrayArg",
+ new EntryPointOperation
+ {
+ Name = "UseDoubleArrayArg",
+ Parameters = new List{new Parameter{ Name = "DoubleArrayArg", Type = DataType.ArrayType, ArrayType = DataType.DoubleType}}
+ }
+ },
+ {
+ "UseIntegerArg",
+ new EntryPointOperation
+ {
+ Name = "UseIntegerArg",
+ Parameters = new List{new Parameter{ Name = "IntegerArg", Type = DataType.IntegerType}}
+ }
+ },
+ {
+ "UseIntegerArrayArg",
+ new EntryPointOperation
+ {
+ Name = "UseIntegerArrayArg",
+ Parameters = new List{new Parameter{ Name = "IntegerArrayArg", Type = DataType.ArrayType, ArrayType = DataType.IntegerType}}
+ }
+ },
+ {
+ "UsePauliArg",
+ new EntryPointOperation
+ {
+ Name = "UsePauliArg",
+ Parameters = new List{new Parameter{ Name = "PauliArg", Type = DataType.PauliType}}
+ }
+ },
+ {
+ "UsePauliArrayArg",
+ new EntryPointOperation
+ {
+ Name = "UsePauliArrayArg",
+ Parameters = new List{new Parameter{ Name = "PauliArrayArg", Type = DataType.ArrayType, ArrayType = DataType.PauliType}}
+ }
+ },
+ {
+ "UseRangeArg",
+ new EntryPointOperation
+ {
+ Name = "UseRangeArg",
+ Parameters = new List{new Parameter{ Name = "RangeArg", Type = DataType.RangeType}}
+ }
+ },
+ {
+ "UseRangeArrayArg",
+ new EntryPointOperation
+ {
+ Name = "UseRangeArrayArg",
+ Parameters = new List{new Parameter{ Name = "RangeArrayArg", Type = DataType.ArrayType, ArrayType = DataType.RangeType}}
+ }
+ },
+ {
+ "UseResultArg",
+ new EntryPointOperation
+ {
+ Name = "UseResultArg",
+ Parameters = new List{new Parameter{ Name = "ResultArg", Type = DataType.ResultType}}
+ }
+ },
+ {
+ "UseResultArrayArg",
+ new EntryPointOperation
+ {
+ Name = "UseResultArrayArg",
+ Parameters = new List{new Parameter{ Name = "ResultArrayArg", Type = DataType.ArrayType, ArrayType = DataType.ResultType}}
+ }
+ },
+ {
+ "UseStringArg",
+ new EntryPointOperation
+ {
+ Name = "UseStringArg",
+ Parameters = new List{new Parameter{ Name = "StringArg", Type = DataType.StringType}}
+ }
+ },
+ {
+ "UseMiscArgs",
+ new EntryPointOperation
+ {
+ Name = "UseMiscArgs",
+ Parameters = new List{
+ new Parameter{ Name = "BoolArg", Type = DataType.BoolType},
+ new Parameter{ Name = "IntegerArrayArg", Position = 1, Type = DataType.ArrayType, ArrayType = DataType.IntegerType},
+ new Parameter{ Name = "RangeArg", Position = 2, Type = DataType.RangeType},
+ new Parameter{ Name = "StringArg", Position = 3, Type = DataType.StringType}
+ }
+ }
+ }
+ };
+
+ private static string RemoveLineEndings(string str) =>
+ str.Replace("\n", string.Empty).Replace("\r", string.Empty);
+
+ [Theory]
+ [InlineData("UseNoArgs")]
+ [InlineData("UseBoolArg")]
+ [InlineData("UseBoolArrayArg")]
+ [InlineData("UseDoubleArg")]
+ [InlineData("UseDoubleArrayArg")]
+ [InlineData("UseIntegerArg")]
+ [InlineData("UseIntegerArrayArg")]
+ [InlineData("UsePauliArg")]
+ [InlineData("UsePauliArrayArg")]
+ [InlineData("UseRangeArg")]
+ [InlineData("UseRangeArrayArg")]
+ [InlineData("UseResultArg")]
+ [InlineData("UseResultArrayArg")]
+ [InlineData("UseStringArg")]
+ [InlineData("UseMiscArgs")]
+ public void GenerateFullStateSimulatorDriver(string testCase)
+ {
+ var entryPointOperation = TestCases[testCase];
+ var driverGenerator = new QirFullStateDriverGenerator();
+ var driverFileName = $"{testCase}.cpp";
+ var verificationCppSourceCode = RemoveLineEndings(File.ReadAllText(Path.Combine(TestCasesDirectory, driverFileName)));
+ Directory.CreateDirectory(TestArtifactsDirectory);
+ var generatedStream = File.Create(Path.Combine(TestArtifactsDirectory, driverFileName));
+ driverGenerator.GenerateAsync(entryPointOperation, generatedStream).Wait();
+ var generatedStreamReader = new StreamReader(generatedStream, Encoding.UTF8);
+ var generatedCppSourceCode = RemoveLineEndings(generatedStreamReader.ReadToEnd());
+ Assert.Equal(verificationCppSourceCode, generatedCppSourceCode);
+ generatedStream.Close();
+
+ }
+ }
+}
diff --git a/src/Qir/Execution/Tools.Tests/QirExecutableGeneratorTests.cs b/src/Qir/Execution/Tools.Tests/QirExecutableGeneratorTests.cs
new file mode 100644
index 00000000000..61af04407e8
--- /dev/null
+++ b/src/Qir/Execution/Tools.Tests/QirExecutableGeneratorTests.cs
@@ -0,0 +1,105 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Quantum.Qir.Tools.Executable;
+using Moq;
+using Xunit;
+
+namespace Tests.Microsoft.Quantum.Qir.Tools
+{
+ public class QirExecutableGeneratorTests : IDisposable
+ {
+ private readonly Mock clangClientMock;
+ private readonly QirExecutableGenerator executableGenerator;
+ private readonly DirectoryInfo sourceDirectory;
+ private readonly DirectoryInfo includeDirectory;
+ private readonly DirectoryInfo libraryDirectory;
+ private readonly DirectoryInfo binDirectory;
+ private readonly IList libraryFiles;
+ private readonly IList sourceFiles;
+ private IList linkLibraries;
+
+ public QirExecutableGeneratorTests()
+ {
+ clangClientMock = new Mock();
+ executableGenerator = new QirExecutableGenerator(clangClientMock.Object, null);
+
+ // Set up files.
+ var prefix = Guid.NewGuid().ToString();
+ binDirectory = new DirectoryInfo($"{prefix}-bin");
+ binDirectory.Create();
+ libraryDirectory = new DirectoryInfo($"{prefix}-library");
+ libraryDirectory.Create();
+ libraryFiles = new List()
+ {
+ Util.CreateBinaryFile(libraryDirectory, "lib1", new byte[]{0x01, 0x23, 0x45, 0x67}),
+ Util.CreateBinaryFile(libraryDirectory, "lib2", new byte[]{0x89, 0xAB, 0xCD, 0xEF}),
+ };
+ includeDirectory = new DirectoryInfo($"{prefix}-include");
+ includeDirectory.Create();
+ sourceDirectory = new DirectoryInfo($"{prefix}-source");
+ sourceDirectory.Create();
+ sourceFiles = new List()
+ {
+ Util.CreateTextFile(sourceDirectory, "src1.cpp", "src1 contents"),
+ Util.CreateBinaryFile(sourceDirectory, "src2.bc", new byte[]{0xFE, 0xDC, 0xBA, 0x98}),
+ };
+ linkLibraries = new List { "lib1", "lib2" };
+ }
+
+ public void Dispose()
+ {
+ sourceDirectory.Delete(true);
+ includeDirectory.Delete(true);
+ libraryDirectory.Delete(true);
+ binDirectory.Delete(true);
+ }
+
+ [Fact]
+ public async Task TestGenerateExecutable()
+ {
+ var executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executableFile"));
+ await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, new[] { libraryDirectory }, new[] { includeDirectory }, linkLibraries);
+
+ // Verify invocation of clang.
+ clangClientMock.Verify(obj => obj.CreateExecutableAsync(
+ It.Is(s => s.OrderBy(val => val).SequenceEqual(sourceFiles.OrderBy(val => val.FullName).Select(fileInfo => fileInfo.FullName))),
+ It.Is(s => s.OrderBy(val => val).SequenceEqual(linkLibraries.OrderBy(val => val))),
+ new[] { libraryDirectory.FullName },
+ new[] { includeDirectory.FullName },
+ executableFile.FullName));
+
+ // Verify files were copied.
+ Assert.True(FilesWereCopied(libraryFiles.ToArray(), binDirectory));
+ }
+
+ private static bool FilesWereCopied(FileInfo[] files, DirectoryInfo destinationDirectory)
+ {
+ var destinationDirectoryFiles = destinationDirectory.GetFiles();
+
+ // N.B. Runtime is (number of FileInfo objects passed in) * (number of files in destination directory).
+ foreach (var file in files)
+ {
+ // Make sure that the file was copied and that the contents is the same.
+ var copiedFile = destinationDirectoryFiles.FirstOrDefault(fileInfo => fileInfo.Name == file.Name);
+ if (copiedFile == null)
+ {
+ return false;
+ }
+
+ if (!Util.CompareFiles(file, copiedFile))
+ {
+ return false;
+ }
+
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/Qir/Execution/Tools.Tests/QirExecutableTests.cs b/src/Qir/Execution/Tools.Tests/QirExecutableTests.cs
new file mode 100644
index 00000000000..6ab9b829604
--- /dev/null
+++ b/src/Qir/Execution/Tools.Tests/QirExecutableTests.cs
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Quantum.Qir.Serialization;
+using Microsoft.Quantum.Qir.Tools.Driver;
+using Microsoft.Quantum.Qir.Tools.Executable;
+using Moq;
+using Xunit;
+
+namespace Tests.Microsoft.Quantum.Qir.Tools
+{
+ public class QirExecutableTests : IDisposable
+ {
+ private readonly DirectoryInfo sourceDirectory;
+ private readonly DirectoryInfo includeDirectory;
+ private readonly DirectoryInfo libraryDirectory;
+ private readonly DirectoryInfo binDirectory;
+ private readonly Mock driverGeneratorMock;
+ private readonly Mock executableGeneratorMock;
+ private readonly Mock runnerMock;
+ private readonly Mock qirExecutable;
+ private readonly FileInfo executableFile;
+ private readonly byte[] qirBytecode = { 1, 2, 3, 4, 5 };
+ private readonly IList linkLibraries;
+ private readonly IList headerDirectories;
+ private readonly IList libraryDirectories;
+
+ public QirExecutableTests()
+ {
+ // Set up files.
+ var prefix = Guid.NewGuid().ToString();
+ binDirectory = new DirectoryInfo($"{prefix}-bin");
+ binDirectory.Create();
+ libraryDirectory = new DirectoryInfo($"{prefix}-library");
+ libraryDirectory.Create();
+ includeDirectory = new DirectoryInfo($"{prefix}-include");
+ includeDirectory.Create();
+ sourceDirectory = new DirectoryInfo($"{prefix}-source");
+ sourceDirectory.Create();
+ executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executable"));
+ driverGeneratorMock = new Mock();
+ executableGeneratorMock = new Mock();
+ runnerMock = new Mock();
+ qirExecutable = new Mock(executableFile, qirBytecode, driverGeneratorMock.Object, executableGeneratorMock.Object, runnerMock.Object, null) { CallBase = true };
+ linkLibraries = new List { "lib1", "lib2" };
+ headerDirectories = new List();
+ libraryDirectories = new List();
+ qirExecutable.SetupGet(obj => obj.LinkLibraries).Returns(linkLibraries);
+ qirExecutable.SetupGet(obj => obj.SourceDirectoryPath).Returns(sourceDirectory.FullName);
+ qirExecutable.SetupGet(obj => obj.DriverFileExtension).Returns(".cpp");
+ qirExecutable.SetupGet(obj => obj.HeaderDirectories).Returns(headerDirectories);
+ qirExecutable.SetupGet(obj => obj.LibraryDirectories).Returns(libraryDirectories);
+ }
+
+ public void Dispose()
+ {
+ sourceDirectory.Delete(true);
+ includeDirectory.Delete(true);
+ libraryDirectory.Delete(true);
+ binDirectory.Delete(true);
+ }
+
+ [Fact]
+ public async Task TestBuild()
+ {
+ // Set up.
+ var entryPoint = new EntryPointOperation();
+ var driverFileContents = "driver file contents";
+ driverGeneratorMock.Setup(obj => obj.GenerateAsync(entryPoint, It.IsAny())).Callback((entryPoint, stream) =>
+ {
+ using var streamWriter = new StreamWriter(stream);
+ streamWriter.Write(driverFileContents);
+ });
+
+ // Build the executable.
+ await qirExecutable.Object.BuildAsync(entryPoint, new[] { libraryDirectory }, new[] { includeDirectory });
+
+ // Verify that the "bytecode" file was created correctly.
+ var bytecodeFilePath = new FileInfo(Path.Combine(sourceDirectory.FullName, "qir.bc"));
+ using var bytecodeFileStream = bytecodeFilePath.OpenRead();
+ Assert.True(Util.CompareStreams(new MemoryStream(qirBytecode), bytecodeFileStream));
+
+ // Verify that the driver was written to the correct file.
+ var driver = new FileInfo(Path.Combine(sourceDirectory.FullName, "driver.cpp"));
+ using var driverStreamReader = driver.OpenText();
+ var actualDriverContents = driverStreamReader.ReadToEnd();
+ Assert.Equal(driverFileContents, actualDriverContents);
+
+ // Verify that the executable was generated.
+ executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync(executableFile, It.Is(arg => arg.FullName == sourceDirectory.FullName), new[] { libraryDirectory }, new[] { includeDirectory }, linkLibraries));
+ }
+
+ [Fact]
+ public async Task TestRun()
+ {
+ // Set up.
+ using var outputStream = new MemoryStream();
+ var execInfo = new ExecutionInformation();
+ var arguments = "arguments";
+ driverGeneratorMock.Setup(obj => obj.GetCommandLineArguments(execInfo)).Returns(arguments);
+
+ // Run executable.
+ await qirExecutable.Object.RunAsync(execInfo, outputStream);
+
+ // Verify runner was invoked properly.
+ runnerMock.Verify(obj => obj.RunExecutableAsync(executableFile, outputStream, arguments));
+ }
+ }
+}
diff --git a/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArg.cpp
new file mode 100644
index 00000000000..c7d4e5c5806
--- /dev/null
+++ b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArg.cpp
@@ -0,0 +1,89 @@
+//----------------------------------------------------------------------------------------------------------------------
+//
+// This code was generated by the Microsoft.Quantum.Qir.Tools package.
+// The purpose of this source code file is to provide an entry-point for executing a QIR program.
+// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program.
+//----------------------------------------------------------------------------------------------------------------------
+
+#include
+#include
+#include