diff --git a/examples/QIR/Development/Development.csproj b/examples/QIR/Development/Development.csproj index 5c01930244..9b6deba038 100644 --- a/examples/QIR/Development/Development.csproj +++ b/examples/QIR/Development/Development.csproj @@ -5,13 +5,30 @@ netcoreapp3.1 + + + + + + + + false dotnet $(MSBuildThisFileDirectory)../../../src/QsCompiler/CommandLineTool/bin/$(Configuration)/netcoreapp3.1/qsc.dll - + + @@ -28,18 +45,28 @@ and files with the generated QIR are deleted when the project is cleaned despite that we added them in a way that displays them as part of the project. --> - - + + - <_FilesToClean Include="$(GeneratedFilesOutputPath)**" /> - <_FilesToClean Include="$(QirOutputPath)**/*.ll" /> - + <_QirFilesToClean Include="$(QirOutputPath)**" /> + - + + - + + + + $(PkglibLLVM_runtime_osx-x64) + $(PkglibLLVM_runtime_win-x64) + $(PkglibLLVM_runtime_ubuntu_18_04-x64) + $(PkglibLLVM_runtime_ubuntu_20_04-x64) + + + --llvm-libs $(LlvmLibsPath)/ + diff --git a/src/QsCompiler/CommandLineTool/CommandLineTool.csproj b/src/QsCompiler/CommandLineTool/CommandLineTool.csproj index e60219af2b..c2c1875239 100644 --- a/src/QsCompiler/CommandLineTool/CommandLineTool.csproj +++ b/src/QsCompiler/CommandLineTool/CommandLineTool.csproj @@ -27,10 +27,6 @@ - - - - diff --git a/src/QsCompiler/CommandLineTool/Commands/Build.cs b/src/QsCompiler/CommandLineTool/Commands/Build.cs index 8899e89476..6badefd290 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Build.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Build.cs @@ -91,6 +91,7 @@ internal static bool IncorporateResponseFiles( BuildOptions options, [NotNullWhen(true)] out BuildOptions? incorporated, ILogger? logger = null) { incorporated = null; + var responseFiles = options.ResponseFiles; while (options.ResponseFiles != null && options.ResponseFiles.Any()) { try @@ -110,6 +111,7 @@ internal static bool IncorporateResponseFiles( } } incorporated = options; + incorporated.ResponseFiles = responseFiles; return true; } } @@ -203,11 +205,15 @@ public static int Run(BuildOptions options, ConsoleLogger logger) { if (!BuildOptions.IncorporateResponseFiles(options, out var incorporated)) { + options.Print(logger); logger.Log(ErrorCode.InvalidCommandLineArgsInResponseFiles, Array.Empty()); return ReturnCode.InvalidArguments; } options = incorporated; + options.Print(logger); + options.SetupLoadingContext(); + var usesPlugins = options.Plugins != null && options.Plugins.Any(); if (!options.ParseAssemblyProperties(out var assemblyConstants)) { diff --git a/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs b/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs index 80b21ff9fc..409e679cc7 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs @@ -229,6 +229,8 @@ public static IEnumerable StripSnippetWrapping(IEnumerable public static int Run(DiagnoseOptions options, ConsoleLogger logger) { + options.Print(logger); + options.SetupLoadingContext(); if (!options.ParseAssemblyProperties(out var assemblyConstants)) { logger.Log(WarningCode.InvalidAssemblyProperties, Array.Empty()); diff --git a/src/QsCompiler/CommandLineTool/Commands/Format.cs b/src/QsCompiler/CommandLineTool/Commands/Format.cs index 62559f580e..596865b346 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Format.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Format.cs @@ -157,8 +157,9 @@ ImmutableDictionary LoadSources(SourceFileLoader loadFromDisk) => .ToImmutableDictionary(entry => entry.Key, entry => UpdateArrayLiterals(entry.Value)); // manually replace array literals // no rewrite steps, no generation - var loaded = - new CompilationLoader(LoadSources, options.References ?? Enumerable.Empty(), logger: logger); + options.Print(logger); + var loaded = new CompilationLoader(LoadSources, options.References ?? Enumerable.Empty(), logger: logger); + if (ReturnCode.Status(loaded) == ReturnCode.UnresolvedFiles) { return ReturnCode.UnresolvedFiles; // ignore compilation errors diff --git a/src/QsCompiler/CommandLineTool/LoadContext.cs b/src/QsCompiler/CommandLineTool/LoadContext.cs index 745fe47eaf..469e707e96 100644 --- a/src/QsCompiler/CommandLineTool/LoadContext.cs +++ b/src/QsCompiler/CommandLineTool/LoadContext.cs @@ -22,6 +22,9 @@ namespace Microsoft.Quantum.QsCompiler /// public class LoadContext : AssemblyLoadContext { + internal static HashSet ManagedDllPaths = new HashSet(); + internal static HashSet UnmanagedDllPaths = new HashSet(); + public readonly string PathToParentAssembly; private readonly AssemblyDependencyResolver resolver; private readonly HashSet fallbackPaths; @@ -50,7 +53,7 @@ private LoadContext(string parentAssembly) protected override IntPtr LoadUnmanagedDll(string name) { var path = this.resolver.ResolveUnmanagedDllToPath(name); - path ??= this.ResolveFromFallbackPaths(name); + path ??= ResolveFromPaths(name, this.fallbackPaths); return path == null ? IntPtr.Zero : this.LoadUnmanagedDllFromPath(path); } @@ -58,14 +61,14 @@ protected override IntPtr LoadUnmanagedDll(string name) /// Search all fallback paths for a suitable .dll, .dylib, or .so file, ignoring all exceptions. /// Returns the full path to the file if such a file was found. /// - private string? ResolveFromFallbackPaths(string name) + internal static string? ResolveFromPaths(string name, IEnumerable paths) { bool MatchByName(string file) => Path.GetFileNameWithoutExtension(file) .Equals(name, StringComparison.InvariantCultureIgnoreCase); var found = new List(); - foreach (var dir in this.fallbackPaths) + foreach (var dir in paths) { try { @@ -108,14 +111,14 @@ bool MatchByName(string file) => /// Search all fallback paths for a suitable .dll ignoring all exceptions. /// Returns the full path to the dll if a suitable assembly was found. /// - private string? ResolveFromFallbackPaths(AssemblyName name) + internal static string? ResolveFromPaths(AssemblyName name, string pathToParentAssembly, IEnumerable paths) { bool MatchByName(string file) => Path.GetFileNameWithoutExtension(file) .Equals(name.Name, StringComparison.InvariantCultureIgnoreCase); var found = new List(); - foreach (var dir in this.fallbackPaths) + foreach (var dir in paths) { try { @@ -132,7 +135,7 @@ bool MatchByName(string file) => return found.FirstOrDefault(); } - var tempContext = new LoadContext(this.PathToParentAssembly); + var tempContext = new LoadContext(pathToParentAssembly); var versions = new List<(string, Version?)>(); foreach (var file in found) { @@ -172,7 +175,7 @@ bool MatchByName(string file) => /// private Assembly? OnResolving(AssemblyLoadContext context, AssemblyName name) { - var path = this.ResolveFromFallbackPaths(name); + var path = ResolveFromPaths(name, this.PathToParentAssembly, this.fallbackPaths); return path == null ? null : this.LoadFromAssemblyPath(path); } @@ -210,6 +213,15 @@ public static Assembly LoadAssembly(string path, string[]? fallbackPaths = null) { context.AddToPath(fallbackPaths); } + foreach (var preload in UnmanagedDllPaths) + { + context.LoadUnmanagedDllFromPath(preload); + } + foreach (var preload in ManagedDllPaths) + { + context.LoadFromAssemblyPath(preload); + } + Loaded.Add(context); var assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(path)); return context.LoadFromAssemblyName(assemblyName); diff --git a/src/QsCompiler/CommandLineTool/Options.cs b/src/QsCompiler/CommandLineTool/Options.cs index 5d6582ec8b..f3903a1367 100644 --- a/src/QsCompiler/CommandLineTool/Options.cs +++ b/src/QsCompiler/CommandLineTool/Options.cs @@ -99,6 +99,20 @@ public class CompilationOptions : Options HelpText = "Specifies whether to build a Q# command line application.")] public bool MakeExecutable { get; set; } + [Option( + "package-load-fallback-folders", + Required = false, + SetName = CodeMode, + HelpText = "Specifies the directories the compiler will search when a compiler dependency could not be found.")] + public IEnumerable? PackageLoadFallbackFolders { get; set; } + + [Option( + "llvm-libs", + Required = false, + SetName = CodeMode, + HelpText = "Specifies the folder where the llvm libraries can be found.")] + public string? LlvmLibs { get; set; } + /// /// Returns a dictionary with the specified assembly properties as out parameter. /// Returns a boolean indicating whether all specified properties were successfully added. @@ -117,6 +131,25 @@ internal bool ParseAssemblyProperties(out Dictionary parsed) } return success; } + + /// + /// Configures the LoadingContext for this assembly depending on the defined options. + /// + internal void SetupLoadingContext() + { + var current = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; + var fallbackFolders = this.PackageLoadFallbackFolders.Prepend(current); + CompilationLoader.LoadAssembly = path => + LoadContext.LoadAssembly(path, fallbackFolders.ToArray()); + + var llvmLibs = this.LlvmLibs != null + ? LoadContext.ResolveFromPaths("libLLVM", new[] { this.LlvmLibs }) + : null; + if (llvmLibs != null) + { + LoadContext.UnmanagedDllPaths.Add(llvmLibs); + } + } } public class Options @@ -188,13 +221,6 @@ public enum LogFormat HelpText = "Warnings with the given code(s) will be ignored.")] public IEnumerable? NoWarn { get; set; } - [Option( - "package-load-fallback-folders", - Required = false, - SetName = CodeMode, - HelpText = "Specifies the directories the compiler will search when a compiler dependency could not be found.")] - public IEnumerable? PackageLoadFallbackFolders { get; set; } - /// /// 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, @@ -241,8 +267,7 @@ internal static Func LoggingFormat(LogFormat format) => }; /// - /// Creates a suitable logger for the given command line options, - /// logging the given arguments if the verbosity is high enough. + /// Creates a suitable logger for the given command line options. /// public ConsoleLogger GetLogger(DiagnosticSeverity defaultVerbosity = DiagnosticSeverity.Warning) { @@ -261,7 +286,6 @@ public ConsoleLogger GetLogger(DiagnosticSeverity defaultVerbosity = DiagnosticS verbosity, this.NoWarn, this.CodeSnippet != null ? -2 : 0); - this.Print(logger); return logger; } diff --git a/src/QsCompiler/CommandLineTool/Program.cs b/src/QsCompiler/CommandLineTool/Program.cs index 681134d15b..c225d79876 100644 --- a/src/QsCompiler/CommandLineTool/Program.cs +++ b/src/QsCompiler/CommandLineTool/Program.cs @@ -107,11 +107,6 @@ private static int Run(Func compile, T options) var logger = options.GetLogger(); try { - var current = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; - var fallbackFolders = options.PackageLoadFallbackFolders.Prepend(current); - CompilationLoader.LoadAssembly = path => - LoadContext.LoadAssembly(path, fallbackFolders.ToArray()); - var result = compile(options, logger); logger.ReportSummary(result); return result; diff --git a/src/QsCompiler/LlvmBindings/LlvmBindings.csproj b/src/QsCompiler/LlvmBindings/LlvmBindings.csproj index 5263a8a14c..168b3c8ffd 100644 --- a/src/QsCompiler/LlvmBindings/LlvmBindings.csproj +++ b/src/QsCompiler/LlvmBindings/LlvmBindings.csproj @@ -9,11 +9,7 @@ - - - - - + diff --git a/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj b/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj index 471f4c2351..8078435a47 100644 --- a/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj +++ b/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj @@ -370,9 +370,9 @@ Always - - Always - + + Always + Always @@ -536,6 +536,10 @@ + + + + diff --git a/src/QuantumSdk/DefaultItems/DefaultItems.targets b/src/QuantumSdk/DefaultItems/DefaultItems.targets index 29a9013e53..7fb55fdd62 100644 --- a/src/QuantumSdk/DefaultItems/DefaultItems.targets +++ b/src/QuantumSdk/DefaultItems/DefaultItems.targets @@ -39,11 +39,11 @@ The execution target for a Q# library needs to be 'Any'. - + - OpenQASM - ExtendedQASM - OpenQASM + Type1 + Type2 + Type3 Default diff --git a/src/QuantumSdk/Sdk/Sdk.props b/src/QuantumSdk/Sdk/Sdk.props index de15b074ec..1f278cd0b9 100644 --- a/src/QuantumSdk/Sdk/Sdk.props +++ b/src/QuantumSdk/Sdk/Sdk.props @@ -29,10 +29,12 @@ - - - + + @@ -44,6 +46,22 @@ Include="Microsoft.Quantum.QirGeneration" Version="0.15.2101126940" IsImplicitlyDefined="true" IsQscReference="true" ExecutionTarget="Any" Priority="-1" PrivateAssets="All" /> + + + + diff --git a/src/QuantumSdk/Sdk/Sdk.targets b/src/QuantumSdk/Sdk/Sdk.targets index cb3af539de..53dc7a4e9c 100644 --- a/src/QuantumSdk/Sdk/Sdk.targets +++ b/src/QuantumSdk/Sdk/Sdk.targets @@ -32,7 +32,7 @@ - + <_FilesToClean Include="$(GeneratedFilesOutputPath)**" /> @@ -43,7 +43,7 @@ @@ -69,7 +69,14 @@ - + + + $(PkglibLLVM_runtime_osx-x64) + $(PkglibLLVM_runtime_win-x64) + $(PkglibLLVM_runtime_ubuntu_18_04-x64) + $(PkglibLLVM_runtime_ubuntu_20_04-x64) + +