diff --git a/.fantomasignore b/.fantomasignore index ee73dc2845d157cfc49adbf5d1dca16297c2644d..c22a6a6b7b17ef50ed58d2686975328b63d59f38 100644 --- a/.fantomasignore +++ b/.fantomasignore @@ -16,6 +16,7 @@ artifacts/ src/Compiler/Checking/**/*.fs src/Compiler/CodeGen/**/*.fs src/Compiler/DependencyManager/**/*.fs +src/Compiler/Facilities/**/*.fs src/Compiler/Interactive/**/*.fs src/Compiler/Legacy/**/*.fs src/Compiler/Optimize/**/*.fs diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 424cbe6c578376b8de37a47b7daee32607374321..ce23ae7da0fbd27da1681aef33f3ef28c8b580df 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -61,6 +61,7 @@ param ( [string]$officialSkipTests = "false", [switch]$noVisualStudio, [switch]$sourceBuild, + [switch]$skipBuild, [parameter(ValueFromRemainingArguments = $true)][string[]]$properties) @@ -114,6 +115,7 @@ function Print-Usage() { Write-Host " -useGlobalNuGetCache Use global NuGet cache." Write-Host " -noVisualStudio Only build fsc and fsi as .NET Core applications. No Visual Studio required. '-configuration', '-verbosity', '-norestore', '-rebuild' are supported." Write-Host " -sourceBuild Simulate building for source-build." + Write-Host " -skipbuild Skip building product" Write-Host "" Write-Host "Command line arguments starting with '/p:' are passed through to MSBuild." } @@ -458,7 +460,7 @@ try { } $script:BuildMessage = "Failure building product" - if ($restore -or $build -or $rebuild -or $pack -or $sign -or $publish) { + if ($restore -or $build -or $rebuild -or $pack -or $sign -or $publish -and -not $skipBuild) { if ($noVisualStudio) { BuildSolution "FSharp.sln" } diff --git a/src/Compiler/DependencyManager/AssemblyResolveHandler.fs b/src/Compiler/DependencyManager/AssemblyResolveHandler.fs index 5f17c53a41a663784178aa767f982f2d8bb806d4..6efe32e4bc02c1274c1752ad0ce9c6f4c2995f8c 100644 --- a/src/Compiler/DependencyManager/AssemblyResolveHandler.fs +++ b/src/Compiler/DependencyManager/AssemblyResolveHandler.fs @@ -12,78 +12,96 @@ open Internal.Utilities.FSharpEnvironment type AssemblyResolutionProbe = delegate of Unit -> seq /// Type that encapsulates AssemblyResolveHandler for managed packages -type AssemblyResolveHandlerCoreclr (assemblyProbingPaths: AssemblyResolutionProbe option) as this = - let assemblyLoadContextType: Type = Type.GetType("System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader", false) +type AssemblyResolveHandlerCoreclr(assemblyProbingPaths: AssemblyResolutionProbe option) as this = + let loadContextType = + Type.GetType("System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader", false) let loadFromAssemblyPathMethod = - assemblyLoadContextType.GetMethod("LoadFromAssemblyPath", [| typeof |]) + loadContextType.GetMethod("LoadFromAssemblyPath", [| typeof |]) - let eventInfo, handler, defaultAssemblyLoadContext = - let eventInfo = assemblyLoadContextType.GetEvent("Resolving") - let mi = - let gmi = this.GetType().GetMethod("ResolveAssemblyNetStandard", BindingFlags.Instance ||| BindingFlags.NonPublic) - gmi.MakeGenericMethod(assemblyLoadContextType) + let eventInfo = loadContextType.GetEvent("Resolving") - eventInfo, - Delegate.CreateDelegate(eventInfo.EventHandlerType, this, mi), - assemblyLoadContextType.GetProperty("Default", BindingFlags.Static ||| BindingFlags.Public).GetValue(null, null) + let handler, defaultAssemblyLoadContext = + let ti = typeof + + let gmi = + ti.GetMethod("ResolveAssemblyNetStandard", BindingFlags.Instance ||| BindingFlags.NonPublic) + + let mi = gmi.MakeGenericMethod(loadContextType) + let del = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, mi) + + let prop = + loadContextType + .GetProperty("Default", BindingFlags.Static ||| BindingFlags.Public) + .GetValue(null, null) + + del, prop do eventInfo.AddEventHandler(defaultAssemblyLoadContext, handler) - member _.ResolveAssemblyNetStandard (ctxt: 'T) (assemblyName: AssemblyName): Assembly = + member _.ResolveAssemblyNetStandard (ctxt: 'T) (assemblyName: AssemblyName) : Assembly = let loadAssembly path = loadFromAssemblyPathMethod.Invoke(ctxt, [| path |]) :?> Assembly let assemblyPaths = match assemblyProbingPaths with | None -> Seq.empty - | Some assemblyProbingPaths -> assemblyProbingPaths.Invoke() + | Some assemblyProbingPaths -> assemblyProbingPaths.Invoke() try // args.Name is a displayname formatted assembly version. // E.g: "System.IO.FileSystem, Version=4.1.1.0, Culture=en-US, PublicKeyToken=b03f5f7f11d50a3a" let simpleName = assemblyName.Name - let assemblyPathOpt = assemblyPaths |> Seq.tryFind(fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + + let assemblyPathOpt = + assemblyPaths + |> Seq.tryFind (fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + match assemblyPathOpt with | Some path -> loadAssembly path | None -> Unchecked.defaultof - with | _ -> Unchecked.defaultof + with _ -> + Unchecked.defaultof interface IDisposable with member _x.Dispose() = eventInfo.RemoveEventHandler(defaultAssemblyLoadContext, handler) /// Type that encapsulates AssemblyResolveHandler for managed packages -type AssemblyResolveHandlerDeskTop (assemblyProbingPaths: AssemblyResolutionProbe option) = +type AssemblyResolveHandlerDeskTop(assemblyProbingPaths: AssemblyResolutionProbe option) = - let resolveAssemblyNET (assemblyName: AssemblyName): Assembly = - - let loadAssembly assemblyPath = - Assembly.LoadFrom(assemblyPath) + let resolveAssemblyNET (assemblyName: AssemblyName) : Assembly = let assemblyPaths = match assemblyProbingPaths with | None -> Seq.empty - | Some assemblyProbingPaths -> assemblyProbingPaths.Invoke() + | Some assemblyProbingPaths -> assemblyProbingPaths.Invoke() try // args.Name is a displayname formatted assembly version. // E.g: "System.IO.FileSystem, Version=4.1.1.0, Culture=en-US, PublicKeyToken=b03f5f7f11d50a3a" let simpleName = assemblyName.Name - let assemblyPathOpt = assemblyPaths |> Seq.tryFind(fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + + let assemblyPathOpt = + assemblyPaths + |> Seq.tryFind (fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + match assemblyPathOpt with - | Some path -> loadAssembly path + | Some path -> Assembly.LoadFrom path | None -> Unchecked.defaultof - with | _ -> Unchecked.defaultof + with _ -> + Unchecked.defaultof + + let handler = + ResolveEventHandler(fun _ (args: ResolveEventArgs) -> resolveAssemblyNET (AssemblyName(args.Name))) - let handler = ResolveEventHandler(fun _ (args: ResolveEventArgs) -> resolveAssemblyNET (AssemblyName(args.Name))) - do AppDomain.CurrentDomain.add_AssemblyResolve(handler) + do AppDomain.CurrentDomain.add_AssemblyResolve (handler) interface IDisposable with member _x.Dispose() = - AppDomain.CurrentDomain.remove_AssemblyResolve(handler) + AppDomain.CurrentDomain.remove_AssemblyResolve (handler) type AssemblyResolveHandler internal (assemblyProbingPaths: AssemblyResolutionProbe option) = @@ -93,7 +111,7 @@ type AssemblyResolveHandler internal (assemblyProbingPaths: AssemblyResolutionPr else new AssemblyResolveHandlerDeskTop(assemblyProbingPaths) :> IDisposable - new (assemblyProbingPaths: AssemblyResolutionProbe) = new AssemblyResolveHandler(Option.ofObj assemblyProbingPaths) + new(assemblyProbingPaths: AssemblyResolutionProbe) = new AssemblyResolveHandler(Option.ofObj assemblyProbingPaths) interface IDisposable with member _.Dispose() = handler.Dispose() diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs index aeb5f43f3e8be8ae751d6d0082e884e38af2f4af..419053605a7b3743292227b510530b3c4b129302 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fs +++ b/src/Compiler/DependencyManager/DependencyProvider.fs @@ -16,14 +16,13 @@ module Option = /// Convert string into Option string where null and String.Empty result in None let ofString s = - if String.IsNullOrEmpty(s) then None - else Some(s) + if String.IsNullOrEmpty(s) then None else Some(s) [] module ReflectionHelper = let dependencyManagerPattern = "*DependencyManager*.dll" - let dependencyManagerAttributeName= "DependencyManagerAttribute" + let dependencyManagerAttributeName = "DependencyManagerAttribute" let resolveDependenciesMethodName = "ResolveDependencies" @@ -33,7 +32,7 @@ module ReflectionHelper = let helpMessagesPropertyName = "HelpMessages" - let arrEmpty = Array.empty + let arrEmpty = [||] let seqEmpty = Seq.empty @@ -41,40 +40,46 @@ module ReflectionHelper = try CustomAttributeExtensions.GetCustomAttributes(theAssembly) |> Seq.exists (fun a -> a.GetType().Name = attributeName) - with | _ -> false + with _ -> + false let getAttributeNamed (theType: Type) attributeName = try theType.GetTypeInfo().GetCustomAttributes false |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) - with | _ -> None + with _ -> + None - let getInstanceProperty<'treturn> (theType: Type) propertyName = + let getInstanceProperty<'T> (theType: Type) propertyName = try - let property = theType.GetProperty(propertyName, BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance, Unchecked.defaultof, typeof<'treturn>, Array.empty, Array.empty) + let instanceFlags = + BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance + + let property = + theType.GetProperty(propertyName, instanceFlags, null, typeof<'T>, [||], [||]) + if isNull property then None else let getMethod = property.GetGetMethod() + if not (isNull getMethod) && not getMethod.IsStatic then Some property else None - with | _ -> None + with _ -> + None - let getInstanceMethod<'treturn> (theType: Type) (parameterTypes: Type array) methodName = + let getInstanceMethod<'T> (theType: Type) (parameterTypes: Type[]) methodName = try let theMethod = theType.GetMethod(methodName, parameterTypes) - if isNull theMethod then - None - else - Some theMethod - with | _ -> None + if isNull theMethod then None else Some theMethod + with _ -> + None - let stripTieWrapper (e:Exception) = + let stripTieWrapper (e: Exception) = match e with - | :? TargetInvocationException as e-> - e.InnerException + | :? TargetInvocationException as e -> e.InnerException | _ -> e /// Indicate the type of error to report @@ -117,15 +122,26 @@ type IResolveDependenciesResult = /// #I @"c:\somepath\to\packages\1.1.1\ResolvedPackage" abstract Roots: seq - [] type IDependencyManagerProvider = abstract Name: string abstract Key: string abstract HelpMessages: string[] - abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * scriptExt: string * packageManagerTextLines: (string * string) seq * tfm: string * rid: string * timeout: int-> IResolveDependenciesResult -type ReflectionDependencyManagerProvider(theType: Type, + abstract ResolveDependencies: + scriptDir: string * + mainScriptName: string * + scriptName: string * + scriptExt: string * + packageManagerTextLines: (string * string) seq * + tfm: string * + rid: string * + timeout: int -> + IResolveDependenciesResult + +type ReflectionDependencyManagerProvider + ( + theType: Type, nameProperty: PropertyInfo, keyProperty: PropertyInfo, helpMessagesProperty: PropertyInfo option, @@ -133,40 +149,160 @@ type ReflectionDependencyManagerProvider(theType: Type, resolveDepsEx: MethodInfo option, resolveDepsExWithTimeout: MethodInfo option, resolveDepsExWithScriptInfoAndTimeout: MethodInfo option, - outputDir: string option) = + outputDir: string option + ) = + let instance = Activator.CreateInstance(theType, [| outputDir :> obj |]) let nameProperty = nameProperty.GetValue >> string let keyProperty = keyProperty.GetValue >> string + let helpMessagesProperty = - let toStringArray(o:obj) = o :?> string[] + let toStringArray (o: obj) = o :?> string[] + match helpMessagesProperty with | Some helpMessagesProperty -> helpMessagesProperty.GetValue >> toStringArray - | None -> fun _ -> Array.empty + | None -> fun _ -> [||] - static member InstanceMaker (theType: Type, outputDir: string option) = + static member InstanceMaker(theType: Type, outputDir: string option) = match getAttributeNamed theType dependencyManagerAttributeName, getInstanceProperty theType namePropertyName, getInstanceProperty theType keyPropertyName, getInstanceProperty theType helpMessagesPropertyName - with + with | None, _, _, _ | _, None, _, _ | _, _, None, _ -> None + | Some _, Some nameProperty, Some keyProperty, None -> - let resolveMethod = getInstanceMethod theType [| typeof; typeof; typeof; typeof; typeof |] resolveDependenciesMethodName - let resolveMethodEx = getInstanceMethod theType [| typeof; typeof<(string * string) seq>; typeof; typeof |] resolveDependenciesMethodName - let resolveMethodExWithTimeout = getInstanceMethod theType [| typeof; typeof<(string * string) seq>; typeof; typeof; typeof |] resolveDependenciesMethodName - let resolveDepsExWithScriptInfoAndTimeout = getInstanceMethod theType [| typeof; typeof; typeof; typeof<(string * string) seq>; typeof; typeof; typeof |] resolveDependenciesMethodName - Some (fun () -> ReflectionDependencyManagerProvider(theType, nameProperty, keyProperty, None, resolveMethod, resolveMethodEx, resolveMethodExWithTimeout, resolveDepsExWithScriptInfoAndTimeout,outputDir) :> IDependencyManagerProvider) + let resolveMethod = + getInstanceMethod + theType + [| + typeof + typeof + typeof + typeof> + typeof + |] + resolveDependenciesMethodName + + let resolveMethodEx = + getInstanceMethod + theType + [| + typeof + typeof<(string * string) seq> + typeof + typeof + |] + resolveDependenciesMethodName + + let resolveMethodExWithTimeout = + getInstanceMethod + theType + [| + typeof + typeof<(string * string) seq> + typeof + typeof + typeof + |] + resolveDependenciesMethodName + + let resolveDepsExWithScriptInfoAndTimeout = + getInstanceMethod + theType + [| + typeof + typeof + typeof + typeof<(string * string) seq> + typeof + typeof + typeof + |] + resolveDependenciesMethodName + + Some(fun () -> + ReflectionDependencyManagerProvider( + theType, + nameProperty, + keyProperty, + None, + resolveMethod, + resolveMethodEx, + resolveMethodExWithTimeout, + resolveDepsExWithScriptInfoAndTimeout, + outputDir + ) + :> IDependencyManagerProvider) + | Some _, Some nameProperty, Some keyProperty, Some helpMessagesProperty -> - let resolveMethod = getInstanceMethod theType [| typeof; typeof; typeof; typeof; typeof |] resolveDependenciesMethodName - let resolveMethodEx = getInstanceMethod theType [| typeof; typeof<(string * string) seq>; typeof; typeof |] resolveDependenciesMethodName - let resolveMethodExWithTimeout = getInstanceMethod theType [| typeof; typeof<(string * string) seq>; typeof; typeof; typeof; |] resolveDependenciesMethodName - let resolveDepsExWithScriptInfoAndTimeout = getInstanceMethod theType [| typeof; typeof; typeof; typeof<(string * string) seq>; typeof; typeof; typeof |] resolveDependenciesMethodName - Some (fun () -> ReflectionDependencyManagerProvider(theType, nameProperty, keyProperty, Some helpMessagesProperty, resolveMethod, resolveMethodEx, resolveMethodExWithTimeout, resolveDepsExWithScriptInfoAndTimeout, outputDir) :> IDependencyManagerProvider) - - static member MakeResultFromObject(result: obj) = { - new IResolveDependenciesResult with + let resolveMethod = + getInstanceMethod + theType + [| + typeof + typeof + typeof + typeof> + typeof + |] + resolveDependenciesMethodName + + let resolveMethodEx = + getInstanceMethod + theType + [| + typeof + typeof<(string * string) seq> + typeof + typeof + |] + resolveDependenciesMethodName + + let resolveMethodExWithTimeout = + getInstanceMethod + theType + [| + typeof + typeof<(string * string) seq> + typeof + typeof + typeof + |] + resolveDependenciesMethodName + + let resolveDepsExWithScriptInfoAndTimeout = + getInstanceMethod + theType + [| + typeof + typeof + typeof + typeof<(string * string) seq> + typeof + typeof + typeof + |] + resolveDependenciesMethodName + + Some(fun () -> + ReflectionDependencyManagerProvider( + theType, + nameProperty, + keyProperty, + Some helpMessagesProperty, + resolveMethod, + resolveMethodEx, + resolveMethodExWithTimeout, + resolveDepsExWithScriptInfoAndTimeout, + outputDir + ) + :> IDependencyManagerProvider) + + static member MakeResultFromObject(result: obj) = + { new IResolveDependenciesResult with /// Succeded? member _.Success = match getInstanceProperty (result.GetType()) "Success" with @@ -175,37 +311,45 @@ type ReflectionDependencyManagerProvider(theType: Type, /// The resolution output log member _.StdOut = - match getInstanceProperty (result.GetType()) "StdOut" with - | None -> Array.empty - | Some p -> p.GetValue(result) :?> string array + match getInstanceProperty (result.GetType()) "StdOut" with + | None -> [||] + | Some p -> p.GetValue(result) :?> string[] /// The resolution error log (* process stderror *) member _.StdError = - match getInstanceProperty (result.GetType()) "StdError" with - | None -> Array.empty - | Some p -> p.GetValue(result) :?> string array + match getInstanceProperty (result.GetType()) "StdError" with + | None -> [||] + | Some p -> p.GetValue(result) :?> string[] /// The resolution paths member _.Resolutions = - match getInstanceProperty (result.GetType()) "Resolutions" with + match getInstanceProperty> (result.GetType()) "Resolutions" with | None -> Seq.empty - | Some p -> p.GetValue(result) :?> string seq + | Some p -> p.GetValue(result) :?> seq /// The source code file paths member _.SourceFiles = - match getInstanceProperty (result.GetType()) "SourceFiles" with + match getInstanceProperty> (result.GetType()) "SourceFiles" with | None -> Seq.empty - | Some p -> p.GetValue(result) :?> string seq + | Some p -> p.GetValue(result) :?> seq /// The roots to package directories member _.Roots = - match getInstanceProperty (result.GetType()) "Roots" with + match getInstanceProperty> (result.GetType()) "Roots" with | None -> Seq.empty - | Some p -> p.GetValue(result) :?> string seq + | Some p -> p.GetValue(result) :?> seq } - static member MakeResultFromFields(success: bool, stdOut: string array, stdError: string array, resolutions: string seq, sourceFiles: string seq, roots: string seq) = { - new IResolveDependenciesResult with + static member MakeResultFromFields + ( + success: bool, + stdOut: string[], + stdError: string[], + resolutions: seq, + sourceFiles: seq, + roots: seq + ) = + { new IResolveDependenciesResult with /// Succeded? member _.Success = success @@ -225,7 +369,6 @@ type ReflectionDependencyManagerProvider(theType: Type, member _.Roots = roots } - interface IDependencyManagerProvider with /// Name of dependency Manager @@ -238,7 +381,17 @@ type ReflectionDependencyManagerProvider(theType: Type, member _.HelpMessages = instance |> helpMessagesProperty /// Resolve the dependencies for the given arguments - member _.ResolveDependencies(scriptDir, mainScriptName, scriptName, scriptExt, packageManagerTextLines, tfm, rid, timeout): IResolveDependenciesResult = + member _.ResolveDependencies + ( + scriptDir, + mainScriptName, + scriptName, + scriptExt, + packageManagerTextLines, + tfm, + rid, + timeout + ) : IResolveDependenciesResult = // The ResolveDependencies method, has two signatures, the original signaature in the variable resolveDeps and the updated signature resolveDepsEx // the resolve method can return values in two different tuples: // (bool * string list * string list * string list) @@ -246,19 +399,29 @@ type ReflectionDependencyManagerProvider(theType: Type, // We use reflection to get the correct method and to determine what we got back. let method, arguments = if resolveDepsExWithScriptInfoAndTimeout.IsSome then - resolveDepsExWithScriptInfoAndTimeout, [| box scriptDir; box scriptName; box scriptExt; box packageManagerTextLines; box tfm; box rid; box timeout |] + resolveDepsExWithScriptInfoAndTimeout, + [| + box scriptDir + box scriptName + box scriptExt + box packageManagerTextLines + box tfm + box rid + box timeout + |] elif resolveDepsExWithTimeout.IsSome then resolveDepsExWithTimeout, [| box scriptExt; box packageManagerTextLines; box tfm; box rid; box timeout |] elif resolveDepsEx.IsSome then resolveDepsEx, [| box scriptExt; box packageManagerTextLines; box tfm; box rid |] elif resolveDeps.IsSome then - resolveDeps, [| box scriptDir - box mainScriptName - box scriptName - box (packageManagerTextLines - |> Seq.filter(fun (dv, _) -> dv = "r") - |> Seq.map snd) - box tfm |] + resolveDeps, + [| + box scriptDir + box mainScriptName + box scriptName + box (packageManagerTextLines |> Seq.filter (fun (dv, _) -> dv = "r") |> Seq.map snd) + box tfm + |] else None, [||] @@ -269,22 +432,25 @@ type ReflectionDependencyManagerProvider(theType: Type, // Verify the number of arguments returned in the tuple returned by resolvedependencies, it can be: // 1 - object with properties // 3 - (bool * string list * string list) - // Support legacy api return shape (bool, string seq, string seq) --- original paket packagemanager - if FSharpType.IsTuple (result.GetType()) then + // Support legacy api return shape (bool, seq, seq) --- original paket packagemanager + if FSharpType.IsTuple(result.GetType()) then // Verify the number of arguments returned in the tuple returned by resolvedependencies, it can be: // 3 - (bool * string list * string list) let success, sourceFiles, packageRoots = let tupleFields = result |> FSharpValue.GetTupleFields + match tupleFields |> Array.length with - | 3 -> tupleFields[0] :?> bool, tupleFields[1] :?> string list |> List.toSeq, tupleFields[2] :?> string list |> List.distinct |> List.toSeq + | 3 -> + tupleFields[0] :?> bool, + tupleFields[1] :?> string list |> List.toSeq, + tupleFields[2] :?> string list |> List.distinct |> List.toSeq | _ -> false, seqEmpty, seqEmpty - ReflectionDependencyManagerProvider.MakeResultFromFields(success, Array.empty, Array.empty, Seq.empty, sourceFiles, packageRoots) + + ReflectionDependencyManagerProvider.MakeResultFromFields(success, [||], [||], Seq.empty, sourceFiles, packageRoots) else ReflectionDependencyManagerProvider.MakeResultFromObject(result) - | None -> - ReflectionDependencyManagerProvider.MakeResultFromFields(false, Array.empty, Array.empty, Seq.empty, Seq.empty, Seq.empty) - + | None -> ReflectionDependencyManagerProvider.MakeResultFromFields(false, [||], [||], Seq.empty, Seq.empty, Seq.empty) /// Provides DependencyManagement functions. /// Class is IDisposable @@ -294,41 +460,47 @@ type DependencyProvider internal (assemblyProbingPaths: AssemblyResolutionProbe let dllResolveHandler = new NativeDllResolveHandler(nativeProbingRoots) // Note: creating a AssemblyResolveHandler currently installs process-wide handlers - let assemblyResolveHandler = new AssemblyResolveHandler(assemblyProbingPaths) :> IDisposable + let assemblyResolveHandler = + new AssemblyResolveHandler(assemblyProbingPaths) :> IDisposable // Resolution Path = Location of FSharp.Compiler.Service.dll - let assemblySearchPaths = lazy ( - [ - let assemblyLocation = typeof.GetTypeInfo().Assembly.Location - yield Path.GetDirectoryName assemblyLocation - yield AppDomain.CurrentDomain.BaseDirectory - ]) + let assemblySearchPaths = + lazy + ([ + let assemblyLocation = + typeof.GetTypeInfo().Assembly.Location + + yield Path.GetDirectoryName assemblyLocation + yield AppDomain.CurrentDomain.BaseDirectory + ]) let enumerateDependencyManagerAssemblies compilerTools (reportError: ResolvingErrorReport) = getCompilerToolsDesignTimeAssemblyPaths compilerTools |> Seq.append (assemblySearchPaths.Force()) |> Seq.collect (fun path -> try - if Directory.Exists(path) then Directory.EnumerateFiles(path, dependencyManagerPattern) - else Seq.empty - with _ -> Seq.empty) - |> Seq.choose (fun path -> + if Directory.Exists(path) then + Directory.EnumerateFiles(path, dependencyManagerPattern) + else + Seq.empty + with _ -> + Seq.empty) + |> Seq.choose (fun path -> try Some(Assembly.LoadFrom path) - with - | e -> + with e -> let e = stripTieWrapper e - let n, m = FSComp.SR.couldNotLoadDependencyManagerExtension(path,e.Message) + let n, m = FSComp.SR.couldNotLoadDependencyManagerExtension (path, e.Message) reportError.Invoke(ErrorReportType.Warning, n, m) None) |> Seq.filter (fun a -> assemblyHasAttribute a dependencyManagerAttributeName) - let mutable registeredDependencyManagers: Map option= None + let mutable registeredDependencyManagers: Map option = + None - let RegisteredDependencyManagers (compilerTools: string seq) (outputDir: string option) (reportError: ResolvingErrorReport) = + let RegisteredDependencyManagers (compilerTools: seq) (outputDir: string option) (reportError: ResolvingErrorReport) = match registeredDependencyManagers with - | Some managers -> - managers + | Some managers -> managers | None -> let managers = let defaultProviders = [] @@ -344,98 +516,150 @@ type DependencyProvider internal (assemblyProbingPaths: AssemblyResolutionProbe |> Seq.map (fun pm -> pm.Key, pm) |> Map.ofSeq - registeredDependencyManagers <- - if managers.Count > 0 then - Some managers - else - None + registeredDependencyManagers <- if managers.Count > 0 then Some managers else None managers - let cache = ConcurrentDictionary<_,Result>(HashIdentity.Structural) + let cache = + ConcurrentDictionary<_, Result>(HashIdentity.Structural) - new (assemblyProbingPaths: AssemblyResolutionProbe, nativeProbingRoots: NativeResolutionProbe) = new DependencyProvider(Some assemblyProbingPaths, Some nativeProbingRoots) + new(assemblyProbingPaths: AssemblyResolutionProbe, nativeProbingRoots: NativeResolutionProbe) = + new DependencyProvider(Some assemblyProbingPaths, Some nativeProbingRoots) - new (nativeProbingRoots: NativeResolutionProbe) = new DependencyProvider(None, Some nativeProbingRoots) + new(nativeProbingRoots: NativeResolutionProbe) = new DependencyProvider(None, Some nativeProbingRoots) - new () = new DependencyProvider(None, None) + new() = new DependencyProvider(None, None) /// Returns a formatted help messages for registered dependencymanagers for the host to present - member _.GetRegisteredDependencyManagerHelpText (compilerTools, outputDir, errorReport) = [| - let managers = RegisteredDependencyManagers compilerTools (Option.ofString outputDir) errorReport + member _.GetRegisteredDependencyManagerHelpText(compilerTools, outputDir, errorReport) = + [| + let managers = + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) errorReport + for kvp in managers do let dm = kvp.Value yield! dm.HelpMessages |] + /// Returns a formatted error message for the host to present - member _.CreatePackageManagerUnknownError (compilerTools: string seq, outputDir: string, packageManagerKey: string, reportError: ResolvingErrorReport) = - let registeredKeys = String.Join(", ", RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError |> Seq.map (fun kv -> kv.Value.Key)) + member _.CreatePackageManagerUnknownError + ( + compilerTools: seq, + outputDir: string, + packageManagerKey: string, + reportError: ResolvingErrorReport + ) = + let registeredKeys = + String.Join( + ", ", + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError + |> Seq.map (fun kv -> kv.Value.Key) + ) + let searchPaths = assemblySearchPaths.Force() - FSComp.SR.packageManagerUnknown(packageManagerKey, String.Join(", ", searchPaths, compilerTools), registeredKeys) + FSComp.SR.packageManagerUnknown (packageManagerKey, String.Join(", ", searchPaths, compilerTools), registeredKeys) /// Fetch a dependencymanager that supports a specific key - member this.TryFindDependencyManagerInPath (compilerTools: string seq, outputDir: string, reportError: ResolvingErrorReport, path: string): string MaybeNull * IDependencyManagerProvider MaybeNull = + member this.TryFindDependencyManagerInPath + ( + compilerTools: seq, + outputDir: string, + reportError: ResolvingErrorReport, + path: string + ) : string MaybeNull * IDependencyManagerProvider MaybeNull = try if path.Contains ":" && not (Path.IsPathRooted path) then - let managers = RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError + let managers = + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError - match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with + match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":")) with | None -> - let err, msg = this.CreatePackageManagerUnknownError(compilerTools, outputDir, path.Split(':').[0], reportError) + let err, msg = + this.CreatePackageManagerUnknownError(compilerTools, outputDir, path.Split(':').[0], reportError) + reportError.Invoke(ErrorReportType.Error, err, msg) null, null - | Some kv -> - path, kv.Value + | Some kv -> path, kv.Value else path, null - with - | e -> + with e -> let e = stripTieWrapper e - let err, msg = FSComp.SR.packageManagerError(e.Message) + let err, msg = FSComp.SR.packageManagerError (e.Message) reportError.Invoke(ErrorReportType.Error, err, msg) null, null /// Fetch a dependencymanager that supports a specific key - member _.TryFindDependencyManagerByKey (compilerTools: string seq, outputDir: string, reportError: ResolvingErrorReport, key: string): IDependencyManagerProvider MaybeNull = + member _.TryFindDependencyManagerByKey + ( + compilerTools: seq, + outputDir: string, + reportError: ResolvingErrorReport, + key: string + ) : IDependencyManagerProvider MaybeNull = try RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError |> Map.tryFind key |> Option.toObj - with - | e -> + with e -> let e = stripTieWrapper e - let err, msg = FSComp.SR.packageManagerError(e.Message) + let err, msg = FSComp.SR.packageManagerError (e.Message) reportError.Invoke(ErrorReportType.Error, err, msg) null /// Resolve reference for a list of package manager lines - member _.Resolve (packageManager:IDependencyManagerProvider, - scriptExt: string, - packageManagerTextLines: (string * string) seq, - reportError: ResolvingErrorReport, - executionTfm: string, - []executionRid: string MaybeNull, - []implicitIncludeDir: string, - []mainScriptName: string, - []fileName: string, - []timeout: int): IResolveDependenciesResult = - - let key = (packageManager.Key, scriptExt, Seq.toArray packageManagerTextLines, executionTfm, executionRid, implicitIncludeDir, mainScriptName, fileName) - - let result = - cache.GetOrAdd(key, System.Func<_,_>(fun _ -> - try - let executionRid = - match executionRid with - | Null -> RidHelpers.platformRid - | NonNull executionRid -> executionRid - Ok (packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, scriptExt, packageManagerTextLines, executionTfm, executionRid, timeout)) - - with e -> - let e = stripTieWrapper e - Error (FSComp.SR.packageManagerError(e.Message)) - )) + member _.Resolve + ( + packageManager: IDependencyManagerProvider, + scriptExt: string, + packageManagerTextLines: (string * string) seq, + reportError: ResolvingErrorReport, + executionTfm: string, + [] executionRid: string MaybeNull, + [] implicitIncludeDir: string, + [] mainScriptName: string, + [] fileName: string, + [] timeout: int + ) : IResolveDependenciesResult = + + let key = + (packageManager.Key, + scriptExt, + Seq.toArray packageManagerTextLines, + executionTfm, + executionRid, + implicitIncludeDir, + mainScriptName, + fileName) + + let result = + cache.GetOrAdd( + key, + System.Func<_, _>(fun _ -> + try + let executionRid = + match executionRid with + | Null -> RidHelpers.platformRid + | NonNull executionRid -> executionRid + + Ok( + packageManager.ResolveDependencies( + implicitIncludeDir, + mainScriptName, + fileName, + scriptExt, + packageManagerTextLines, + executionTfm, + executionRid, + timeout + ) + ) + + with e -> + let e = stripTieWrapper e + Error(FSComp.SR.packageManagerError (e.Message))) + ) + match result with | Ok res -> dllResolveHandler.RefreshPathsInEnvironment(res.Roots) diff --git a/src/Compiler/DependencyManager/NativeDllResolveHandler.fs b/src/Compiler/DependencyManager/NativeDllResolveHandler.fs index 7ed85eb403535c7ec09a64ce5a502baa1a516b25..a35382f9485cc27a815fddebd50c09d972b3f8b8 100644 --- a/src/Compiler/DependencyManager/NativeDllResolveHandler.fs +++ b/src/Compiler/DependencyManager/NativeDllResolveHandler.fs @@ -16,14 +16,17 @@ open FSharp.Compiler.IO type NativeResolutionProbe = delegate of Unit -> seq /// Type that encapsulates Native library probing for managed packages -type NativeDllResolveHandlerCoreClr (nativeProbingRoots: NativeResolutionProbe option) = +type NativeDllResolveHandlerCoreClr(nativeProbingRoots: NativeResolutionProbe option) = let nativeLibraryTryLoad = - let nativeLibraryType: Type = Type.GetType("System.Runtime.InteropServices.NativeLibrary, System.Runtime.InteropServices", false) - nativeLibraryType.GetMethod("TryLoad", [| typeof; typeof.MakeByRefType() |]) + let nativeLibraryType: Type = + Type.GetType("System.Runtime.InteropServices.NativeLibrary, System.Runtime.InteropServices", false) + + nativeLibraryType.GetMethod("TryLoad", [| typeof; typeof.MakeByRefType () |]) let loadNativeLibrary path = - let arguments = [| path:>obj; IntPtr.Zero:>obj |] + let arguments = [| path :> obj; IntPtr.Zero :> obj |] + if nativeLibraryTryLoad.Invoke(null, arguments) :?> bool then arguments[1] :?> IntPtr else @@ -32,13 +35,20 @@ type NativeDllResolveHandlerCoreClr (nativeProbingRoots: NativeResolutionProbe o let probingFileNames (name: string) = // coreclr native library probing algorithm: https://github.com/dotnet/coreclr/blob/9773db1e7b1acb3ec75c9cc0e36bd62dcbacd6d5/src/System.Private.CoreLib/shared/System/Runtime/Loader/LibraryNameVariation.Unix.cs let isRooted = Path.IsPathRooted name - let useSuffix s = not (name.Contains(s + ".") || name.EndsWith(s)) // linux devs often append version # to libraries I.e mydll.so.5.3.2 - let usePrefix = name.IndexOf(Path.DirectorySeparatorChar) = -1 // If name has directory information no add no prefix - && name.IndexOf(Path.AltDirectorySeparatorChar) = -1 - && name.IndexOf(Path.PathSeparator) = -1 - && name.IndexOf(Path.VolumeSeparatorChar) = -1 + + let useSuffix s = + not (name.Contains(s + ".") || name.EndsWith(s)) // linux devs often append version # to libraries I.e mydll.so.5.3.2 + + let usePrefix = + name.IndexOf(Path.DirectorySeparatorChar) = -1 // If name has directory information no add no prefix + && name.IndexOf(Path.AltDirectorySeparatorChar) = -1 + && name.IndexOf(Path.PathSeparator) = -1 + && name.IndexOf(Path.VolumeSeparatorChar) = -1 + let prefix = [| "lib" |] - let suffix = [| + + let suffix = + [| if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then ".dll" ".exe" @@ -49,72 +59,79 @@ type NativeDllResolveHandlerCoreClr (nativeProbingRoots: NativeResolutionProbe o |] [| - yield name // Bare name + yield name // Bare name if not isRooted then for s in suffix do - if useSuffix s then // Suffix without prefix + if useSuffix s then // Suffix without prefix yield (sprintf "%s%s" name s) + if usePrefix then - for p in prefix do // Suffix with prefix + for p in prefix do // Suffix with prefix yield (sprintf "%s%s%s" p name s) elif usePrefix then - for p in prefix do // Prefix + for p in prefix do // Prefix yield (sprintf "%s%s" p name) |] - let resolveUnmanagedDll (_: Assembly) (name: string): IntPtr = + let resolveUnmanagedDll (_: Assembly) (name: string) : IntPtr = // Enumerate probing roots looking for a dll that matches the probing name in the probed locations let probeForNativeLibrary root rid name = // Look for name in root - probingFileNames name |> Array.tryPick(fun name -> + probingFileNames name + |> Array.tryPick (fun name -> let path = Path.Combine(root, "runtimes", rid, "native", name) - if FileSystem.FileExistsShim(path) then - Some path - else - None) + if FileSystem.FileExistsShim(path) then Some path else None) let probe = match nativeProbingRoots with | None -> None - | Some nativeProbingRoots -> + | Some nativeProbingRoots -> nativeProbingRoots.Invoke() - |> Seq.tryPick(fun root -> - probingFileNames name |> Seq.tryPick(fun name -> + |> Seq.tryPick (fun root -> + probingFileNames name + |> Seq.tryPick (fun name -> let path = Path.Combine(root, name) + if FileSystem.FileExistsShim(path) then Some path else - RidHelpers.probingRids |> Seq.tryPick(fun rid -> probeForNativeLibrary root rid name))) + RidHelpers.probingRids + |> Seq.tryPick (fun rid -> probeForNativeLibrary root rid name))) match probe with - | Some path -> loadNativeLibrary(path) + | Some path -> loadNativeLibrary (path) | None -> IntPtr.Zero // netstandard 2.1 has this property, unfortunately we don't build with that yet //public event Func ResolvingUnmanagedDll - let assemblyLoadContextType: Type = Type.GetType("System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader", false) + let assemblyLoadContextType: Type = + Type.GetType("System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader", false) + let eventInfo, handler, defaultAssemblyLoadContext = assemblyLoadContextType.GetEvent("ResolvingUnmanagedDll"), Func resolveUnmanagedDll, - assemblyLoadContextType.GetProperty("Default", BindingFlags.Static ||| BindingFlags.Public).GetValue(null, null) + assemblyLoadContextType + .GetProperty("Default", BindingFlags.Static ||| BindingFlags.Public) + .GetValue(null, null) do eventInfo.AddEventHandler(defaultAssemblyLoadContext, handler) interface IDisposable with - member _x.Dispose() = eventInfo.RemoveEventHandler(defaultAssemblyLoadContext, handler) + member _x.Dispose() = + eventInfo.RemoveEventHandler(defaultAssemblyLoadContext, handler) - -type NativeDllResolveHandler (nativeProbingRoots: NativeResolutionProbe option) = +type NativeDllResolveHandler(nativeProbingRoots: NativeResolutionProbe option) = let handler: IDisposable option = if isRunningOnCoreClr then - Some (new NativeDllResolveHandlerCoreClr(nativeProbingRoots) :> IDisposable) + Some(new NativeDllResolveHandlerCoreClr(nativeProbingRoots) :> IDisposable) else None let appendPathSeparator (p: string) = let separator = string Path.PathSeparator - if not(p.EndsWith(separator, StringComparison.OrdinalIgnoreCase)) then + + if not (p.EndsWith(separator, StringComparison.OrdinalIgnoreCase)) then p + separator else p @@ -124,17 +141,20 @@ type NativeDllResolveHandler (nativeProbingRoots: NativeResolutionProbe option) let addProbeToProcessPath probePath = let probe = appendPathSeparator probePath let path = appendPathSeparator (Environment.GetEnvironmentVariable("PATH")) + if not (path.Contains(probe)) then Environment.SetEnvironmentVariable("PATH", path + probe) addedPaths.Add probe let removeProbeFromProcessPath probePath = - if not(String.IsNullOrWhiteSpace(probePath)) then + if not (String.IsNullOrWhiteSpace(probePath)) then let probe = appendPathSeparator probePath let path = appendPathSeparator (Environment.GetEnvironmentVariable("PATH")) - if path.Contains(probe) then Environment.SetEnvironmentVariable("PATH", path.Replace(probe, "")) - new (nativeProbingRoots: NativeResolutionProbe) = new NativeDllResolveHandler(Option.ofObj nativeProbingRoots) + if path.Contains(probe) then + Environment.SetEnvironmentVariable("PATH", path.Replace(probe, "")) + + new(nativeProbingRoots: NativeResolutionProbe) = new NativeDllResolveHandler(Option.ofObj nativeProbingRoots) member internal _.RefreshPathsInEnvironment(roots: string seq) = for probePath in roots do @@ -146,6 +166,7 @@ type NativeDllResolveHandler (nativeProbingRoots: NativeResolutionProbe option) | None -> () | Some handler -> handler.Dispose() - let mutable probe:string = Unchecked.defaultof + let mutable probe: string = Unchecked.defaultof + while (addedPaths.TryTake(&probe)) do removeProbeFromProcessPath probe diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 55cd348782dd3bfc917451afc31451f5a32a2a47..9362c9618daf6d33691a0d8dd5833db0ee320178 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -754,7 +754,6 @@ - diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ba0693c81e579cb6172817db1960c0e19c05125f..5950a28ad0f05fc1bbb6421a30a1b547c28675c8 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,6 +15,7 @@ true false $(ArtifactsPackagesDir)\$(Configuration) + false diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj index ce010764b623f382a1ccd9bb9550e291bb0ae9e5..6dd94cfd92e46513abb9650f39d628600c0c17c7 100644 --- a/src/FSharp.Build/FSharp.Build.fsproj +++ b/src/FSharp.Build/FSharp.Build.fsproj @@ -4,8 +4,7 @@ Library - netstandard2.0 - netstandard2.0 + netstandard2.0 FSharp.Build $(NoWarn);75 true diff --git a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.csproj b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.csproj index eaeac80f3628169462b15e3439dc24ae580b95de..a16bc1310ee099be0ba287642bc5cdbbe40bfcbf 100644 --- a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.csproj +++ b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.csproj @@ -11,6 +11,13 @@ true + + $(NuGetPackageRoot)microsoft.dotnet.arcade.sdk\$(ArcadeSdkVersion)\ + <_BuildReleasePackagesTargets>$(ArcadeSdkDir)tools\BuildReleasePackages.targets + + + + @@ -19,6 +26,36 @@ - + + + + + + + + TargetFrameworks=netstandard2.1;netstandard2.0 + + + TargetFrameworks=netstandard2.0 + + + TargetFrameworks=netstandard2.0 + + + TargetFrameworks=netstandard2.0 + + + TargetFrameworks=netstandard2.0 + + + + + + + + + diff --git a/src/Microsoft.FSharp.Compiler/Program.cs b/src/Microsoft.FSharp.Compiler/Program.cs index c52f1037882bfc4da93f39407972314da0c98ac4..0be8ed50b0eb0a7d4277347196bc71eee906527f 100644 --- a/src/Microsoft.FSharp.Compiler/Program.cs +++ b/src/Microsoft.FSharp.Compiler/Program.cs @@ -1,2 +1,2 @@ -// See https://aka.ms/new-console-template for more information +// See https://aka.ms/new-console-template for more information return 0; \ No newline at end of file diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets b/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets index 966cffad5ff2fda1229e0f19b48fdc1a5701b4a3..9b932e87ec3913bac32ea34940d54204937adb40 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets @@ -33,7 +33,7 @@ All 2 True - TargetFramework=$(DependencyTargetFramework) + TargetFramework=netstandard2.0