From 3a0bc455603348e1754bf1f271866cbe0417072d Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 04:37:18 +0300 Subject: [PATCH 01/14] wip --- .../DependencyManager/DependencyProvider.fs | 68 +++++++++----- .../DependencyManager/DependencyProvider.fsi | 21 +++-- src/Compiler/Driver/CompilerConfig.fs | 8 +- src/Compiler/Driver/FxResolver.fs | 2 +- src/Compiler/Driver/ScriptClosure.fs | 2 + src/Compiler/Facilities/CompilerLocation.fs | 90 +++++++++++-------- src/Compiler/Facilities/CompilerLocation.fsi | 2 +- src/Compiler/Interactive/fsi.fs | 11 ++- .../FSharp.DependencyManager.ProjectFile.fs | 14 +-- .../FSharp.DependencyManager.Utilities.fs | 6 +- .../FSharp.DependencyManager.fs | 16 ++-- .../FSharp.DependencyManager.fsi | 4 + 12 files changed, 162 insertions(+), 82 deletions(-) diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs index a94e296d465..c6c2812898b 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fs +++ b/src/Compiler/DependencyManager/DependencyProvider.fs @@ -152,14 +152,25 @@ type ReflectionDependencyManagerProvider resolveDepsExWithScriptInfoAndTimeout: MethodInfo option, clearResultCache: MethodInfo option, outputDir: string option, - useResultsCache: bool + useResultsCache: bool, + sdkDirOverride: string option ) = let instance = - if not (isNull (theType.GetConstructor([| typeof; typeof |]))) then - Activator.CreateInstance(theType, [| outputDir :> objnull; useResultsCache :> objnull |]) - else - Activator.CreateInstance(theType, [| outputDir :> objnull |]) + let arguments: (Type * objnull) array = + [| + typeof, outputDir + typeof, useResultsCache + typeof, sdkDirOverride + |] + + let n = arguments.Length + + seq { for i in n - 1 .. -1 .. 0 -> arguments[0..i] } + |> Seq.map Array.unzip + |> Seq.tryFind (fun (types, _) -> isNotNull (theType.GetConstructor(types))) + |> Option.map (fun (_, values) -> Activator.CreateInstance(theType, values)) + |> Option.toObj let nameProperty (x: objnull) = x |> nameProperty.GetValue |> string let keyProperty (x: objnull) = x |> keyProperty.GetValue |> string @@ -171,7 +182,7 @@ type ReflectionDependencyManagerProvider | Some helpMessagesProperty -> x |> helpMessagesProperty.GetValue |> toStringArray | None -> [||] - static member InstanceMaker(theType: Type, outputDir: string option, useResultsCache: bool) = + static member InstanceMaker(theType: Type, outputDir: string option, useResultsCache: bool, sdkDirOverride: string option) = match getAttributeNamed theType dependencyManagerAttributeName, getInstanceProperty theType namePropertyName, @@ -246,7 +257,8 @@ type ReflectionDependencyManagerProvider resolveDepsExWithScriptInfoAndTimeout, clearResultsCacheMethod, outputDir, - useResultsCache + useResultsCache, + sdkDirOverride ) :> IDependencyManagerProvider) @@ -315,7 +327,8 @@ type ReflectionDependencyManagerProvider resolveDepsExWithScriptInfoAndTimeout, clearResultsCacheMethod, outputDir, - useResultsCache + useResultsCache, + sdkDirOverride ) :> IDependencyManagerProvider) @@ -510,7 +523,12 @@ type DependencyProvider let mutable registeredDependencyManagers: Map option = None - let RegisteredDependencyManagers (compilerTools: seq) (outputDir: string option) (reportError: ResolvingErrorReport) = + let RegisteredDependencyManagers + (compilerTools: seq) + (outputDir: string option) + (sdkDirOverride: string option) + (reportError: ResolvingErrorReport) + = match registeredDependencyManagers with | Some managers -> managers | None -> @@ -520,7 +538,8 @@ type DependencyProvider let loadedProviders = enumerateDependencyManagerAssemblies compilerTools reportError |> Seq.collect (fun a -> a.GetTypes()) - |> Seq.choose (fun t -> ReflectionDependencyManagerProvider.InstanceMaker(t, outputDir, useResultsCache)) + |> Seq.choose (fun t -> + ReflectionDependencyManagerProvider.InstanceMaker(t, outputDir, useResultsCache, sdkDirOverride)) |> Seq.map (fun maker -> maker ()) defaultProviders @@ -547,10 +566,10 @@ type DependencyProvider new() = new DependencyProvider(None, None, true) /// Returns a formatted help messages for registered dependencymanagers for the host to present - member _.GetRegisteredDependencyManagerHelpText(compilerTools, outputDir: string | null, errorReport) = + member _.GetRegisteredDependencyManagerHelpText(compilerTools, outputDir: string | null, sdkDirOverride: string option, errorReport) = [| let managers = - RegisteredDependencyManagers compilerTools (Option.ofString outputDir) errorReport + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) sdkDirOverride errorReport for kvp in managers do let dm = kvp.Value @@ -558,21 +577,26 @@ type DependencyProvider |] /// Clear the DependencyManager results caches - member _.ClearResultsCache(compilerTools, outputDir: string | null, errorReport) = + member _.ClearResultsCache(compilerTools, outputDir: string | null, sdkDirOverride: string option, errorReport) = let managers = - RegisteredDependencyManagers compilerTools (Option.ofString outputDir) errorReport + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) sdkDirOverride errorReport for kvp in managers do kvp.Value.ClearResultsCache() /// Returns a formatted error message for the host to present member _.CreatePackageManagerUnknownError - (compilerTools: seq, outputDir: string, packageManagerKey: string, reportError: ResolvingErrorReport) - = + ( + compilerTools: seq, + outputDir: string, + sdkDirOverride: string option, + packageManagerKey: string, + reportError: ResolvingErrorReport + ) = let registeredKeys = String.Join( ", ", - RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) sdkDirOverride reportError |> Seq.map (fun kv -> kv.Value.Key) ) @@ -581,17 +605,17 @@ type DependencyProvider /// Fetch a dependencymanager that supports a specific key member this.TryFindDependencyManagerInPath - (compilerTools: seq, outputDir: string, reportError: ResolvingErrorReport, path: string) + (compilerTools: seq, outputDir: string, sdkDirOverride: string option, reportError: ResolvingErrorReport, path: string) : string | null * IDependencyManagerProvider | null = try if path.Contains ":" && not (Path.IsPathRooted path) then let managers = - RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) sdkDirOverride reportError match managers |> Seq.tryFind (fun kv -> path.StartsWithOrdinal(kv.Value.Key + ":")) with | None -> let err, msg = - this.CreatePackageManagerUnknownError(compilerTools, outputDir, path.Split(':').[0], reportError) + this.CreatePackageManagerUnknownError(compilerTools, outputDir, sdkDirOverride, path.Split(':').[0], reportError) reportError.Invoke(ErrorReportType.Error, err, msg) null, null @@ -607,10 +631,10 @@ type DependencyProvider /// Fetch a dependencymanager that supports a specific key member _.TryFindDependencyManagerByKey - (compilerTools: seq, outputDir: string, reportError: ResolvingErrorReport, key: string) + (compilerTools: seq, outputDir: string, sdkDirOverride: string option, reportError: ResolvingErrorReport, key: string) : IDependencyManagerProvider | null = try - RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError + RegisteredDependencyManagers compilerTools (Option.ofString outputDir) sdkDirOverride reportError |> Map.tryFind key |> Option.toObj diff --git a/src/Compiler/DependencyManager/DependencyProvider.fsi b/src/Compiler/DependencyManager/DependencyProvider.fsi index 1fe1c400525..e05c6d0b9b3 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fsi +++ b/src/Compiler/DependencyManager/DependencyProvider.fsi @@ -105,13 +105,16 @@ type DependencyProvider = DependencyProvider /// Returns a formatted help messages for registered dependencymanagers for the host to present - member GetRegisteredDependencyManagerHelpText: string seq * string MaybeNull * ResolvingErrorReport -> string[] + member GetRegisteredDependencyManagerHelpText: + string seq * string MaybeNull * sdkDirOverride: string option * ResolvingErrorReport -> string[] /// Clear the DependencyManager results caches - member ClearResultsCache: string seq * string MaybeNull * ResolvingErrorReport -> unit + member ClearResultsCache: + string seq * string MaybeNull * sdkDirOverride: string option * ResolvingErrorReport -> unit /// Returns a formatted error message for the host to present - member CreatePackageManagerUnknownError: string seq * string * string * ResolvingErrorReport -> int * string + member CreatePackageManagerUnknownError: + string seq * string * sdkDirOverride: string option * string * ResolvingErrorReport -> int * string /// Resolve reference for a list of package manager lines member Resolve: @@ -129,10 +132,18 @@ type DependencyProvider = /// Fetch a dependencymanager that supports a specific key member TryFindDependencyManagerByKey: - compilerTools: string seq * outputDir: string * reportError: ResolvingErrorReport * key: string -> + compilerTools: string seq * + outputDir: string * + sdkDirOverride: string option * + reportError: ResolvingErrorReport * + key: string -> IDependencyManagerProvider | null /// TryFindDependencyManagerInPath - given a #r "key:sometext" go and find a DependencyManager that satisfies the key member TryFindDependencyManagerInPath: - compilerTools: string seq * outputDir: string * reportError: ResolvingErrorReport * path: string -> + compilerTools: string seq * + outputDir: string * + sdkDirOverride: string option * + reportError: ResolvingErrorReport * + path: string -> string | null * IDependencyManagerProvider | null diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index cccbcb15810..0db023fc327 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -1084,7 +1084,13 @@ type TcConfigBuilder = | ErrorReportType.Error -> errorR (Error(error, m))) let dm = - dependencyProvider.TryFindDependencyManagerInPath(tcConfigB.compilerToolPaths, output, reportError, path) + dependencyProvider.TryFindDependencyManagerInPath( + tcConfigB.compilerToolPaths, + output, + tcConfigB.sdkDirOverride, + reportError, + path + ) match dm with // #r "Assembly" diff --git a/src/Compiler/Driver/FxResolver.fs b/src/Compiler/Driver/FxResolver.fs index 0b3a5a2517e..906181cec99 100644 --- a/src/Compiler/Driver/FxResolver.fs +++ b/src/Compiler/Driver/FxResolver.fs @@ -112,7 +112,7 @@ type internal FxResolver desiredDotNetSdkVersionForDirectoryCache.GetOrAdd( projectDir, (fun _ -> - match getDotnetHostPath () with + match getDotnetHostPath None with | Some dotnetHostPath -> try let workingDir = diff --git a/src/Compiler/Driver/ScriptClosure.fs b/src/Compiler/Driver/ScriptClosure.fs index a9dd5442626..537e34551cf 100644 --- a/src/Compiler/Driver/ScriptClosure.fs +++ b/src/Compiler/Driver/ScriptClosure.fs @@ -347,6 +347,7 @@ module ScriptPreprocessClosure = dependencyProvider.TryFindDependencyManagerByKey( tcConfig.compilerToolPaths, outputDir, + tcConfig.sdkDirOverride, reportError m, packageManagerKey ) @@ -357,6 +358,7 @@ module ScriptPreprocessClosure = dependencyProvider.CreatePackageManagerUnknownError( tcConfig.compilerToolPaths, outputDir, + tcConfig.sdkDirOverride, packageManagerKey, reportError m ) diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index 03251f2109a..07ebe2d68e3 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -301,45 +301,61 @@ module internal FSharpEnvironment = // Can't find it --- give up None - let getDotnetHostPath () = - // How to find dotnet.exe --- woe is me; probing rules make me sad. - // Algorithm: - // 1. Look for DOTNET_HOST_PATH environment variable - // this is the main user programmable override .. provided by user to find a specific dotnet.exe - // 2. Probe for are we part of an .NetSDK install - // In an sdk install we are always installed in: sdk\3.0.100-rc2-014234\FSharp - // dotnet or dotnet.exe will be found in the directory that contains the sdk directory - // 3. We are loaded in-process to some other application ... Eg. try .net - // See if the host is dotnet.exe ... from net5.0 on this is fairly unlikely - // 4. If it's none of the above we are going to have to rely on the path containing the way to find dotnet.exe - // Use the path to search for dotnet.exe - let probePathForDotnetHost () = - let paths = - let p = Environment.GetEnvironmentVariable("PATH") - - match p with - | null -> [||] - | p -> p.Split(Path.PathSeparator) - - paths |> Array.tryFind (fun f -> fileExists (Path.Combine(f, dotnet))) + let getDotnetHostPath sdkDirOverride = + let dotnetHostPathOverride = + match sdkDirOverride with + | Some sdkDirOverride -> + let dotnetHostPath = + Path.GetFullPath(Path.Combine(sdkDirOverride, "..", "..", dotnet)) + + if fileExists dotnetHostPath then + Some dotnetHostPath + else + None + | None -> None + + match dotnetHostPathOverride with + | Some _ -> dotnetHostPathOverride + | None -> - match (Environment.GetEnvironmentVariable("DOTNET_HOST_PATH")) with - // Value set externally - | NonEmptyString value when fileExists value -> Some value - | _ -> - // Probe for netsdk install, dotnet. and dotnet.exe is a constant offset from the location of System.Int32 - let candidate = - let assemblyLocation = - Path.GetDirectoryName(typeof.GetTypeInfo().Assembly.Location) + // How to find dotnet.exe --- woe is me; probing rules make me sad. + // Algorithm: + // 1. Look for DOTNET_HOST_PATH environment variable + // this is the main user programmable override .. provided by user to find a specific dotnet.exe + // 2. Probe for are we part of an .NetSDK install + // In an sdk install we are always installed in: sdk\3.0.100-rc2-014234\FSharp + // dotnet or dotnet.exe will be found in the directory that contains the sdk directory + // 3. We are loaded in-process to some other application ... Eg. try .net + // See if the host is dotnet.exe ... from net5.0 on this is fairly unlikely + // 4. If it's none of the above we are going to have to rely on the path containing the way to find dotnet.exe + // Use the path to search for dotnet.exe + let probePathForDotnetHost () = + let paths = + let p = Environment.GetEnvironmentVariable("PATH") + + match p with + | null -> [||] + | p -> p.Split(Path.PathSeparator) + + paths |> Array.tryFind (fun f -> fileExists (Path.Combine(f, dotnet))) + + match (Environment.GetEnvironmentVariable("DOTNET_HOST_PATH")) with + // Value set externally + | NonEmptyString value when fileExists value -> Some value + | _ -> + // Probe for netsdk install, dotnet. and dotnet.exe is a constant offset from the location of System.Int32 + let candidate = + let assemblyLocation = + Path.GetDirectoryName(typeof.GetTypeInfo().Assembly.Location) - Path.GetFullPath(Path.Combine(!!assemblyLocation, "..", "..", "..", dotnet)) + Path.GetFullPath(Path.Combine(!!assemblyLocation, "..", "..", "..", dotnet)) - if fileExists candidate then - Some candidate - else - match probePathForDotnetHost () with - | Some f -> Some(Path.Combine(f, dotnet)) - | None -> getDotnetGlobalHostPath () + if fileExists candidate then + Some candidate + else + match probePathForDotnetHost () with + | Some f -> Some(Path.Combine(f, dotnet)) + | None -> getDotnetGlobalHostPath () let getDotnetHostDirectories () = let isDotnetMultilevelLookup = @@ -348,7 +364,7 @@ module internal FSharpEnvironment = <> 0 [| - match getDotnetHostPath (), getDotnetGlobalHostPath () with + match getDotnetHostPath None, getDotnetGlobalHostPath () with | Some hostPath, Some globalHostPath -> yield !!Path.GetDirectoryName(hostPath) diff --git a/src/Compiler/Facilities/CompilerLocation.fsi b/src/Compiler/Facilities/CompilerLocation.fsi index cbf397883ac..57549d3a32f 100644 --- a/src/Compiler/Facilities/CompilerLocation.fsi +++ b/src/Compiler/Facilities/CompilerLocation.fsi @@ -55,7 +55,7 @@ module internal FSharpEnvironment = val dotnet: string - val getDotnetHostPath: unit -> string option + val getDotnetHostPath: sdkDirOverride: string option -> string option val getDotnetHostDirectories: unit -> string[] diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index a4202ddbb62..fc1a55ca445 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -1200,7 +1200,12 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: s do if tcConfigB.clearResultsCache then - dependencyProvider.ClearResultsCache(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError rangeCmdArgs) + dependencyProvider.ClearResultsCache( + tcConfigB.compilerToolPaths, + getOutputDir tcConfigB, + tcConfigB.sdkDirOverride, + reportError rangeCmdArgs + ) do let firstArg = @@ -1245,6 +1250,7 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: s dependencyProvider.GetRegisteredDependencyManagerHelpText( tcConfigB.compilerToolPaths, getOutputDir tcConfigB, + tcConfigB.sdkDirOverride, reportError m ) do fsiConsoleOutput.uprintfn "%s" msg @@ -2704,6 +2710,7 @@ type internal FsiDynamicCompiler fsiOptions.DependencyProvider.TryFindDependencyManagerByKey( tcConfigB.compilerToolPaths, getOutputDir tcConfigB, + tcConfigB.sdkDirOverride, reportError m, packageManagerKey ) @@ -2713,6 +2720,7 @@ type internal FsiDynamicCompiler fsiOptions.DependencyProvider.CreatePackageManagerUnknownError( tcConfigB.compilerToolPaths, outputDir, + tcConfigB.sdkDirOverride, packageManagerKey, reportError m ) @@ -2792,6 +2800,7 @@ type internal FsiDynamicCompiler fsiOptions.DependencyProvider.TryFindDependencyManagerInPath( tcConfigB.compilerToolPaths, getOutputDir tcConfigB, + tcConfigB.sdkDirOverride, reportError m, path ) diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index f25d31a1ba7..8346fd3fd0e 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -3,6 +3,7 @@ namespace FSharp.DependencyManager.Nuget open System open System.IO +open Internal.Utilities.FSharpEnvironment // Package reference information type PackageReference = @@ -20,19 +21,22 @@ module internal ProjectFile = let csxExt = ".csx" - let makeScriptFromReferences (references: string seq) poundRprefix = + let makeScriptFromReferences (references: string seq) poundRprefix dotnetHostPath tfmMoniker = let expandReferences = references |> Seq.fold (fun acc r -> acc + poundRprefix + r + "\"" + Environment.NewLine) "" + let dotnetHostPath = Option.defaultValue "???" dotnetHostPath + let actualSdkPath = dotnetHostPath.Replace(dotnet, "") + "\\" + tfmMoniker + let projectTemplate = - """ + $""" // Generated from #r "nuget:Package References" // ============================================ // -// DOTNET_HOST_PATH:(C:\Program Files\dotnet\dotnet.exe) -// MSBuildSDKsPath:(C:\Program Files\dotnet\sdk\3.1.200-preview-014883\Sdks) -// MSBuildExtensionsPath:(C:\Program Files\dotnet\sdk\3.1.200-preview-014883\) +// DOTNET_HOST_PATH:({dotnetHostPath}) +// MSBuildSDKsPath:({actualSdkPath}\Sdks) +// MSBuildExtensionsPath:({actualSdkPath}\) // // References // diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs index ecfe86109aa..c28ede2cce0 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs @@ -219,7 +219,7 @@ module internal Utilities = | None -> false, Array.empty, Array.empty - let buildProject projectPath binLogPath timeout = + let buildProject dotnetHostPath projectPath binLogPath timeout = let binLoggingArguments = match binLogPath with | Some(path) -> @@ -240,7 +240,6 @@ module internal Utilities = sprintf "%s -restore %s %c%s%c /nologo /t:InteractivePackageManagement" prefix binLoggingArguments '\"' projectPath '\"' let workingDir = Path.GetDirectoryName projectPath - let dotnetHostPath = getDotnetHostPath () let args = arguments "msbuild -v:quiet" let success, stdOut, stdErr = executeTool dotnetHostPath args workingDir [] timeout @@ -286,8 +285,7 @@ module internal Utilities = includes = includes } - let generateSourcesFromNugetConfigs scriptDirectory workingDir timeout = - let dotnetHostPath = getDotnetHostPath () + let generateSourcesFromNugetConfigs dotnetHostPath scriptDirectory workingDir timeout = let args = "nuget list source --format detailed" let success, stdOut, stdErr = diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs index a1ff3c900bb..e45b3a9f057 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs @@ -11,6 +11,7 @@ open FSharp.DependencyManager.Nuget open FSharp.DependencyManager.Nuget.Utilities open FSharp.DependencyManager.Nuget.ProjectFile open FSDependencyManager +open Internal.Utilities.FSharpEnvironment module FSharpDependencyManager = @@ -302,7 +303,7 @@ type ResolveDependenciesResult member _.Roots = roots [] -type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bool) = +type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bool, sdkDirOverride: string option) = let key = "nuget" let name = "MsBuild Nuget DependencyManager" @@ -377,7 +378,8 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo directiveLines: (string * string) seq, targetFrameworkMoniker: string, runtimeIdentifier: string, - timeout: int + timeout: int, + dotnetHostPath: string option ) : PackageBuildResolutionResult = let scriptExt = match scriptExt with @@ -395,7 +397,7 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo |> Seq.concat let generatedNugetSources = - generateSourcesFromNugetConfigs scriptDirectory projectDirectory.Value timeout + generateSourcesFromNugetConfigs dotnetHostPath scriptDirectory projectDirectory.Value timeout let packageReferenceText = String.Join(Environment.NewLine, packageReferenceLines) @@ -424,7 +426,7 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo writeFile projectPath generateProjectFile writeFile nugetPath generateProjectNugetConfigFile - buildProject projectPath binLogPath timeout + buildProject dotnetHostPath projectPath binLogPath timeout generateAndBuildProjectArtifacts @@ -463,6 +465,7 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo do AppDomain.CurrentDomain.ProcessExit |> Event.add (fun _ -> deleteScripts ()) + new(outputDirectory: string option, useResultsCache: bool) = FSharpDependencyManager(outputDirectory, useResultsCache, None) new(outputDirectory: string option) = FSharpDependencyManager(outputDirectory, true) member _.Name = name @@ -502,6 +505,8 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo | ".csx" -> "#r \"" | _ -> "#r @\"" + let dotnetHostPath = getDotnetHostPath sdkDirOverride + let generateAndBuildProjectArtifacts = let resolutionHash = FSharpDependencyManager.computeHashForResolutionInputs ( @@ -522,7 +527,8 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo packageManagerTextLines, targetFrameworkMoniker, runtimeIdentifier, - timeout + timeout, + dotnetHostPath ) match resolutionResult.resolutionsFile with diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi index defe300d6ff..1bb6856dbf5 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi @@ -45,6 +45,10 @@ type ResolveDependenciesResult = [] type FSharpDependencyManager = + new: + outputDirectory: string option * useResultsCache: bool * sdkDirOverride: string option -> + FSharpDependencyManager + new: outputDirectory: string option * useResultsCache: bool -> FSharpDependencyManager new: outputDirectory: string option -> FSharpDependencyManager From 3cf35f7f283aa5659a719b894da6c53cbc5ba91e Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 04:41:27 +0300 Subject: [PATCH 02/14] fix --- .../FSharp.DependencyManager.ProjectFile.fs | 4 ++-- .../FSharp.DependencyManager.fs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index 8346fd3fd0e..0e5ff7fc89b 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -21,13 +21,13 @@ module internal ProjectFile = let csxExt = ".csx" - let makeScriptFromReferences (references: string seq) poundRprefix dotnetHostPath tfmMoniker = + let makeScriptFromReferences (references: string seq) poundRprefix dotnetHostPath tfm = let expandReferences = references |> Seq.fold (fun acc r -> acc + poundRprefix + r + "\"" + Environment.NewLine) "" let dotnetHostPath = Option.defaultValue "???" dotnetHostPath - let actualSdkPath = dotnetHostPath.Replace(dotnet, "") + "\\" + tfmMoniker + let actualSdkPath = dotnetHostPath.Replace(dotnet, "") + "\\" + tfm let projectTemplate = $""" diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs index e45b3a9f057..41dada15449 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs @@ -541,7 +541,7 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo // We have succeeded to gather information -- generate script and copy the results to the cache if not (fromCache) then let generatedScriptBody = - makeScriptFromReferences resolutionResult.references poundRprefix + makeScriptFromReferences resolutionResult.references poundRprefix dotnetHostPath targetFrameworkMoniker emitFile generatedScriptPath generatedScriptBody From a44921e970c0908540936d1cc0a414ffc83fd032 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 04:42:26 +0300 Subject: [PATCH 03/14] cleanup --- .../FSharp.DependencyManager.Utilities.fs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs index c28ede2cce0..d385201cdc1 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs @@ -4,11 +4,9 @@ namespace FSharp.DependencyManager.Nuget open System open System.Diagnostics open System.IO -open System.Reflection open System.Security.Cryptography open System.Text.RegularExpressions open FSDependencyManager -open Internal.Utilities.FSharpEnvironment [] type DependencyManagerAttribute() = From 956de473a771f0f80e9a7ac96f09b6e57c84b1cb Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 04:55:42 +0300 Subject: [PATCH 04/14] Fix tests --- .../DependencyManagerInteractiveTests.fs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 819fe92ec2c..83220dfa441 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -80,7 +80,7 @@ type DependencyManagerInteractiveTests() = | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net472") @@ -109,7 +109,7 @@ type DependencyManagerInteractiveTests() = | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, "net10.0") Assert.Equal(true, result.Success) @@ -132,7 +132,7 @@ type DependencyManagerInteractiveTests() = | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, "net472") @@ -160,7 +160,7 @@ type DependencyManagerInteractiveTests() = | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm1 = dp1.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm1 = dp1.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result1 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net472") Assert.Equal(true, result1.Success) @@ -181,7 +181,7 @@ type DependencyManagerInteractiveTests() = Assert.True((result2.Roots |> Seq.head).EndsWith("/fsharp.data/3.3.3/")) use dp2 = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm2 = dp2.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm2 = dp2.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result3 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, "net472") @@ -215,7 +215,7 @@ type DependencyManagerInteractiveTests() = | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm1 = dp1.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm1 = dp1.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result1 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, "net472") @@ -287,7 +287,7 @@ TorchSharp.Tensor.LongTensor.From([| 0L .. 100L |]).Device // Restore packages, Get Reference dll paths and package roots let result = use dp = new DependencyProvider(AssemblyResolutionProbe(assemblyProbingPaths), NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") Assert.True(result.Success, "resolve failed") @@ -385,7 +385,7 @@ printfn ""%A"" result // Restore packages, Get Reference dll paths and package roots let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") Assert.True(result.Success, "resolve failed") @@ -470,7 +470,7 @@ printfn ""%A"" result // Restore packages, Get Reference dll paths and package roots let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") Assert.True(result.Success, "resolve failed") @@ -524,7 +524,7 @@ x |> Seq.iter(fun r -> // Restore packages, Get Reference dll paths and package roots let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") // Expected: error FS3217: PackageManager cannot reference the System Package 'FSharp.Core' @@ -547,7 +547,7 @@ x |> Seq.iter(fun r -> // Restore packages, Get Reference dll paths and package roots let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") dp.Resolve(idm, ".csx", packagemanagerlines, reportError, "net10.0") Assert.True(result.Success, "resolve failed but should have succeeded") @@ -582,7 +582,7 @@ x |> Seq.iter(fun r -> Assert.False (found, "Invoke the nativeProbingRoots callback -- Error the ResolvingUnmanagedDll still fired ") use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots)) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net472") @@ -680,7 +680,7 @@ x |> Seq.iter(fun r -> do initialPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") let mutable currentPath:string = null if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, "netstandard2.0") @@ -697,7 +697,7 @@ x |> Seq.iter(fun r -> initialPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) let mutable currentPath:string = null use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, "net10.0") Assert.Equal(true, result.Success) currentPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) @@ -785,7 +785,7 @@ x |> Seq.iter(fun r -> | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0", timeout=0) // Fail in 0 milliseconds Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) @@ -808,7 +808,7 @@ x |> Seq.iter(fun r -> | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) @@ -831,7 +831,7 @@ x |> Seq.iter(fun r -> | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever Assert.Equal(true, result.Success) Assert.Equal(foundCorrectError, false) @@ -855,7 +855,7 @@ x |> Seq.iter(fun r -> | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") // Resolve and cache the results won't time out let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever @@ -865,7 +865,7 @@ x |> Seq.iter(fun r -> foundWrongError <- false // Now clear the cache --- this will ensure that resolving produces a timeout error. If we read from the cache the test will fail - dp.ClearResultsCache(Seq.empty, "", reportError) + dp.ClearResultsCache(Seq.empty, "", None, reportError) let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) From f06c11d93b1b3e5553d32f74083237973796b20c Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 05:31:26 +0300 Subject: [PATCH 05/14] + test --- .../DependencyManagerInteractiveTests.fs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 83220dfa441..a2d102b40a6 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -67,9 +67,17 @@ type DependencyManagerInteractiveTests() = let errors = script.Eval(code) |> getErrors Assert.Contains(message, errors |> Array.map(fun e -> e.Message)) *) - [] - member _.``Use Dependency Manager to resolve dependency FSharp.Data``() = + static member SdkDirOverrideTestData = [| + [| None |] + [| Path.Combine(__SOURCE_DIRECTORY__, "..", "..", ".dotnet", "sdk") + |> Directory.GetDirectories + |> Seq.head + |> Some |] + |] + [] + [] + member _.``Use Dependency Manager to resolve dependency FSharp.Data`` (sdkDirOverride: string option) = let nativeProbingRoots () = Seq.empty use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) @@ -80,7 +88,7 @@ type DependencyManagerInteractiveTests() = | ErrorReportType.Warning -> printfn "PackageManagementWarning %d : %s" code message ResolvingErrorReport (report) - let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") + let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", sdkDirOverride, reportError, "nuget") if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net472") From 54b76fced18912679e11ef4fd736461dec794ce4 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 05:35:43 +0300 Subject: [PATCH 06/14] fix --- .../FSharp.DependencyManager.ProjectFile.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index 0e5ff7fc89b..7bd0546f87b 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -27,7 +27,7 @@ module internal ProjectFile = |> Seq.fold (fun acc r -> acc + poundRprefix + r + "\"" + Environment.NewLine) "" let dotnetHostPath = Option.defaultValue "???" dotnetHostPath - let actualSdkPath = dotnetHostPath.Replace(dotnet, "") + "\\" + tfm + let actualSdkPath = dotnetHostPath.Replace(dotnet, "") + tfm let projectTemplate = $""" From da81d6c7716c334ffb2af288fcc5d5f58ccd1568 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 05:47:42 +0300 Subject: [PATCH 07/14] remove confusing restore info --- .../FSharp.DependencyManager.ProjectFile.fs | 5 +---- .../FSharp.DependencyManager.fs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index 7bd0546f87b..5386ea5a283 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -21,13 +21,12 @@ module internal ProjectFile = let csxExt = ".csx" - let makeScriptFromReferences (references: string seq) poundRprefix dotnetHostPath tfm = + let makeScriptFromReferences (references: string seq) poundRprefix dotnetHostPath = let expandReferences = references |> Seq.fold (fun acc r -> acc + poundRprefix + r + "\"" + Environment.NewLine) "" let dotnetHostPath = Option.defaultValue "???" dotnetHostPath - let actualSdkPath = dotnetHostPath.Replace(dotnet, "") + tfm let projectTemplate = $""" @@ -35,8 +34,6 @@ module internal ProjectFile = // ============================================ // // DOTNET_HOST_PATH:({dotnetHostPath}) -// MSBuildSDKsPath:({actualSdkPath}\Sdks) -// MSBuildExtensionsPath:({actualSdkPath}\) // // References // diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs index 41dada15449..f847ba8e8ab 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs @@ -541,7 +541,7 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo // We have succeeded to gather information -- generate script and copy the results to the cache if not (fromCache) then let generatedScriptBody = - makeScriptFromReferences resolutionResult.references poundRprefix dotnetHostPath targetFrameworkMoniker + makeScriptFromReferences resolutionResult.references poundRprefix dotnetHostPath emitFile generatedScriptPath generatedScriptBody From 3d4773bbd9c10954650b7ff9d7c1bfc3f97f7726 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 06:53:04 +0300 Subject: [PATCH 08/14] surface area --- ...harp.Compiler.Service.SurfaceArea.netstandard20.bsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index 9ac1302be02..b7994bed3ae 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -2673,17 +2673,17 @@ FSharp.Compiler.DependencyManager.AssemblyResolutionProbe: System.Collections.Ge FSharp.Compiler.DependencyManager.AssemblyResolutionProbe: System.IAsyncResult BeginInvoke(System.AsyncCallback, System.Object) FSharp.Compiler.DependencyManager.AssemblyResolutionProbe: Void .ctor(System.Object, IntPtr) FSharp.Compiler.DependencyManager.AssemblyResolveHandler: Void .ctor(FSharp.Compiler.DependencyManager.AssemblyResolutionProbe) -FSharp.Compiler.DependencyManager.DependencyProvider: FSharp.Compiler.DependencyManager.IDependencyManagerProvider TryFindDependencyManagerByKey(System.Collections.Generic.IEnumerable`1[System.String], System.String, FSharp.Compiler.DependencyManager.ResolvingErrorReport, System.String) +FSharp.Compiler.DependencyManager.DependencyProvider: FSharp.Compiler.DependencyManager.IDependencyManagerProvider TryFindDependencyManagerByKey(System.Collections.Generic.IEnumerable`1[System.String], System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], FSharp.Compiler.DependencyManager.ResolvingErrorReport, System.String) FSharp.Compiler.DependencyManager.DependencyProvider: FSharp.Compiler.DependencyManager.IResolveDependenciesResult Resolve(FSharp.Compiler.DependencyManager.IDependencyManagerProvider, System.String, System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.String,System.String]], FSharp.Compiler.DependencyManager.ResolvingErrorReport, System.String, System.String, System.String, System.String, System.String, Int32) -FSharp.Compiler.DependencyManager.DependencyProvider: System.String[] GetRegisteredDependencyManagerHelpText(System.Collections.Generic.IEnumerable`1[System.String], System.String, FSharp.Compiler.DependencyManager.ResolvingErrorReport) -FSharp.Compiler.DependencyManager.DependencyProvider: System.Tuple`2[System.Int32,System.String] CreatePackageManagerUnknownError(System.Collections.Generic.IEnumerable`1[System.String], System.String, System.String, FSharp.Compiler.DependencyManager.ResolvingErrorReport) -FSharp.Compiler.DependencyManager.DependencyProvider: System.Tuple`2[System.String,FSharp.Compiler.DependencyManager.IDependencyManagerProvider] TryFindDependencyManagerInPath(System.Collections.Generic.IEnumerable`1[System.String], System.String, FSharp.Compiler.DependencyManager.ResolvingErrorReport, System.String) +FSharp.Compiler.DependencyManager.DependencyProvider: System.String[] GetRegisteredDependencyManagerHelpText(System.Collections.Generic.IEnumerable`1[System.String], System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], FSharp.Compiler.DependencyManager.ResolvingErrorReport) +FSharp.Compiler.DependencyManager.DependencyProvider: System.Tuple`2[System.Int32,System.String] CreatePackageManagerUnknownError(System.Collections.Generic.IEnumerable`1[System.String], System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], System.String, FSharp.Compiler.DependencyManager.ResolvingErrorReport) +FSharp.Compiler.DependencyManager.DependencyProvider: System.Tuple`2[System.String,FSharp.Compiler.DependencyManager.IDependencyManagerProvider] TryFindDependencyManagerInPath(System.Collections.Generic.IEnumerable`1[System.String], System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], FSharp.Compiler.DependencyManager.ResolvingErrorReport, System.String) FSharp.Compiler.DependencyManager.DependencyProvider: Void .ctor() FSharp.Compiler.DependencyManager.DependencyProvider: Void .ctor(FSharp.Compiler.DependencyManager.AssemblyResolutionProbe, FSharp.Compiler.DependencyManager.NativeResolutionProbe) FSharp.Compiler.DependencyManager.DependencyProvider: Void .ctor(FSharp.Compiler.DependencyManager.AssemblyResolutionProbe, FSharp.Compiler.DependencyManager.NativeResolutionProbe, Boolean) FSharp.Compiler.DependencyManager.DependencyProvider: Void .ctor(FSharp.Compiler.DependencyManager.NativeResolutionProbe) FSharp.Compiler.DependencyManager.DependencyProvider: Void .ctor(FSharp.Compiler.DependencyManager.NativeResolutionProbe, Boolean) -FSharp.Compiler.DependencyManager.DependencyProvider: Void ClearResultsCache(System.Collections.Generic.IEnumerable`1[System.String], System.String, FSharp.Compiler.DependencyManager.ResolvingErrorReport) +FSharp.Compiler.DependencyManager.DependencyProvider: Void ClearResultsCache(System.Collections.Generic.IEnumerable`1[System.String], System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], FSharp.Compiler.DependencyManager.ResolvingErrorReport) FSharp.Compiler.DependencyManager.ErrorReportType+Tags: Int32 Error FSharp.Compiler.DependencyManager.ErrorReportType+Tags: Int32 Warning FSharp.Compiler.DependencyManager.ErrorReportType: Boolean Equals(FSharp.Compiler.DependencyManager.ErrorReportType) From aca3b158f0ff307c600f7b3d55ba174fb1464e57 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 16:43:39 +0300 Subject: [PATCH 09/14] release notes + ilverify --- docs/release-notes/.FSharp.Compiler.Service/11.0.0.md | 6 ++++++ ...lverify_FSharp.Compiler.Service_Debug_netstandard2.0.bsl | 2 +- ...erify_FSharp.Compiler.Service_Release_netstandard2.0.bsl | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 docs/release-notes/.FSharp.Compiler.Service/11.0.0.md diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md new file mode 100644 index 00000000000..37c74c8d93c --- /dev/null +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -0,0 +1,6 @@ +### Added + + +### Fixed + +* Scripts: Fix resolving the dotnet host path when an SDK directory is specified. ([PR #18960](https://github.com/dotnet/fsharp/pull/18960)) diff --git a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netstandard2.0.bsl b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netstandard2.0.bsl index 9a9e0b97a9f..61040597ad0 100644 --- a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netstandard2.0.bsl +++ b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netstandard2.0.bsl @@ -11,7 +11,7 @@ [IL]: Error [StackUnexpected]: : FSharp.Compiler.FxResolver::getTfmNumber(string)][offset 0x0000000B][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.FxResolver::tryGetRunningTfm()][offset 0x00000011][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.DependencyManager.AssemblyResolveHandler::.ctor([FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1)][offset 0x0000003E][found ref 'object'][expected ref '[S.P.CoreLib]System.IDisposable'] Unexpected type on the stack. -[IL]: Error [StackUnexpected]: : FSharp.Compiler.DependencyManager.DependencyProvider::TryFindDependencyManagerInPath([S.P.CoreLib]System.Collections.Generic.IEnumerable`1, string, [FSharp.Compiler.Service]FSharp.Compiler.DependencyManager.ResolvingErrorReport, string)][offset 0x00000061][found Char] Unexpected type on the stack. +[IL]: Error [StackUnexpected]: : FSharp.Compiler.DependencyManager.DependencyProvider::TryFindDependencyManagerInPath([S.P.CoreLib]System.Collections.Generic.IEnumerable`1, string, [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, [FSharp.Compiler.Service]FSharp.Compiler.DependencyManager.ResolvingErrorReport, string)][offset 0x00000064][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.Symbols.FSharpEntity::TryGetFullDisplayName()][offset 0x00000035][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.Symbols.FSharpEntity::TryGetFullCompiledName()][offset 0x00000035][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue::TryGetFullCompiledOperatorNameIdents()][offset 0x0000008A][found Char] Unexpected type on the stack. diff --git a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl index 0ffe02881a3..2d4250700df 100644 --- a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl +++ b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl @@ -11,7 +11,7 @@ [IL]: Error [StackUnexpected]: : FSharp.Compiler.FxResolver::getTfmNumber(string)][offset 0x0000000B][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.FxResolver::tryGetRunningTfm()][offset 0x00000011][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.DependencyManager.AssemblyResolveHandler::.ctor([FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1)][offset 0x0000002B][found ref 'object'][expected ref '[S.P.CoreLib]System.IDisposable'] Unexpected type on the stack. -[IL]: Error [StackUnexpected]: : FSharp.Compiler.DependencyManager.DependencyProvider::TryFindDependencyManagerInPath([S.P.CoreLib]System.Collections.Generic.IEnumerable`1, string, [FSharp.Compiler.Service]FSharp.Compiler.DependencyManager.ResolvingErrorReport, string)][offset 0x00000055][found Char] Unexpected type on the stack. +[IL]: Error [StackUnexpected]: : FSharp.Compiler.DependencyManager.DependencyProvider::TryFindDependencyManagerInPath([S.P.CoreLib]System.Collections.Generic.IEnumerable`1, string, [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, [FSharp.Compiler.Service]FSharp.Compiler.DependencyManager.ResolvingErrorReport, string)][offset 0x00000058][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.Symbols.FSharpEntity::TryGetFullDisplayName()][offset 0x00000024][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.Symbols.FSharpEntity::TryGetFullCompiledName()][offset 0x00000024][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue::TryGetFullCompiledOperatorNameIdents()][offset 0x00000060][found Char] Unexpected type on the stack. From 140feb18b19a4030c7921899bb13b6b77815f696 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 16:56:26 +0300 Subject: [PATCH 10/14] . --- src/Compiler/Facilities/CompilerLocation.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index 07ebe2d68e3..115c75ff217 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -7,6 +7,7 @@ open System.Diagnostics open System.IO open System.Reflection open System.Runtime.InteropServices +open FSharp.Compiler.IO open Microsoft.FSharp.Core open Internal.Utilities.Library @@ -303,16 +304,15 @@ module internal FSharpEnvironment = let getDotnetHostPath sdkDirOverride = let dotnetHostPathOverride = - match sdkDirOverride with - | Some sdkDirOverride -> + sdkDirOverride + |> Option.bind (fun sdkDirOverride -> let dotnetHostPath = - Path.GetFullPath(Path.Combine(sdkDirOverride, "..", "..", dotnet)) + FileSystem.GetFullPathShim(Path.Combine(sdkDirOverride, "..", "..", dotnet)) if fileExists dotnetHostPath then Some dotnetHostPath else - None - | None -> None + None) match dotnetHostPathOverride with | Some _ -> dotnetHostPathOverride From 9a3c7ebdf9ad28205e3547964d88e6392dff9c69 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Fri, 3 Oct 2025 17:03:39 +0300 Subject: [PATCH 11/14] fix build --- src/Compiler/Facilities/CompilerLocation.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index 115c75ff217..367a842a701 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -7,7 +7,6 @@ open System.Diagnostics open System.IO open System.Reflection open System.Runtime.InteropServices -open FSharp.Compiler.IO open Microsoft.FSharp.Core open Internal.Utilities.Library @@ -307,7 +306,7 @@ module internal FSharpEnvironment = sdkDirOverride |> Option.bind (fun sdkDirOverride -> let dotnetHostPath = - FileSystem.GetFullPathShim(Path.Combine(sdkDirOverride, "..", "..", dotnet)) + Path.GetFullPath(Path.Combine(sdkDirOverride, "..", "..", dotnet)) if fileExists dotnetHostPath then Some dotnetHostPath From 50dc8a4b1667d13226b17a2595d840999294a54d Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Tue, 7 Oct 2025 12:15:56 +0300 Subject: [PATCH 12/14] review fixes --- .../DependencyManager/DependencyProvider.fs | 5 ++++- .../FSharp.DependencyManager.fs | 15 +++++++++++++-- .../FSharp.DependencyManager.fsi | 4 +++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs index c6c2812898b..10b200ebb37 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fs +++ b/src/Compiler/DependencyManager/DependencyProvider.fs @@ -3,6 +3,7 @@ namespace FSharp.Compiler.DependencyManager open System +open System.Collections.Generic open System.IO open System.Reflection open System.Runtime.InteropServices @@ -161,11 +162,13 @@ type ReflectionDependencyManagerProvider [| typeof, outputDir typeof, useResultsCache - typeof, sdkDirOverride + typeof>, dict [ "sdkDirOverride", sdkDirOverride ] |] let n = arguments.Length + // Searches for the most suitable constructor, + // starting from the latest version (with more parameters) and falling back to earlier ones. seq { for i in n - 1 .. -1 .. 0 -> arguments[0..i] } |> Seq.map Array.unzip |> Seq.tryFind (fun (types, _) -> isNotNull (theType.GetConstructor(types))) diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs index f847ba8e8ab..e272248052c 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs @@ -4,6 +4,7 @@ namespace FSharp.DependencyManager.Nuget open System open System.Collections.Concurrent +open System.Collections.Generic open System.Diagnostics open System.IO open System.Text @@ -303,11 +304,21 @@ type ResolveDependenciesResult member _.Roots = roots [] -type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bool, sdkDirOverride: string option) = +type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bool, additionalParams: IDictionary) = let key = "nuget" let name = "MsBuild Nuget DependencyManager" + let sdkDirOverride = + if isNull additionalParams then + None + else + match additionalParams.TryGetValue("sdkDirOverride") with + | true, (:? (string option) as sdkDirOverride) -> sdkDirOverride + | _ -> + Debug.Assert(false, "FSharpDependencyManager: 'sdkDirOverride: string option' is required.") + None + let generatedScripts = ConcurrentDictionary() let projectDirectory, cacheDirectory = @@ -465,7 +476,7 @@ type FSharpDependencyManager(outputDirectory: string option, useResultsCache: bo do AppDomain.CurrentDomain.ProcessExit |> Event.add (fun _ -> deleteScripts ()) - new(outputDirectory: string option, useResultsCache: bool) = FSharpDependencyManager(outputDirectory, useResultsCache, None) + new(outputDirectory: string option, useResultsCache: bool) = FSharpDependencyManager(outputDirectory, useResultsCache, null) new(outputDirectory: string option) = FSharpDependencyManager(outputDirectory, true) member _.Name = name diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi index 1bb6856dbf5..627637e515c 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi @@ -2,6 +2,8 @@ namespace FSharp.DependencyManager.Nuget +open System.Collections.Generic + module internal FSharpDependencyManager = val formatPackageReference: PackageReference -> seq @@ -46,7 +48,7 @@ type ResolveDependenciesResult = [] type FSharpDependencyManager = new: - outputDirectory: string option * useResultsCache: bool * sdkDirOverride: string option -> + outputDirectory: string option * useResultsCache: bool * additionalParams: IDictionary -> FSharpDependencyManager new: outputDirectory: string option * useResultsCache: bool -> FSharpDependencyManager From 543b57c69354130a6ed90ba19217abee366d8b48 Mon Sep 17 00:00:00 2001 From: "Alexey.Berezhnykh" Date: Tue, 7 Oct 2025 13:16:02 +0300 Subject: [PATCH 13/14] fix --- src/Compiler/DependencyManager/DependencyProvider.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs index 10b200ebb37..31daa3a3c60 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fs +++ b/src/Compiler/DependencyManager/DependencyProvider.fs @@ -162,7 +162,7 @@ type ReflectionDependencyManagerProvider [| typeof, outputDir typeof, useResultsCache - typeof>, dict [ "sdkDirOverride", sdkDirOverride ] + typeof>, dict [ "sdkDirOverride", sdkDirOverride :> obj ] |] let n = arguments.Length From 3e248ddd604153635b872a09c5727e3758a91e24 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 9 Oct 2025 12:58:09 +0200 Subject: [PATCH 14/14] Apply suggestion from @T-Gro --- docs/release-notes/.FSharp.Compiler.Service/11.0.0.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md index adfab2f5e5d..2cde88c0d94 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -1,6 +1,3 @@ -### Added - - ### Fixed * Scripts: Fix resolving the dotnet host path when an SDK directory is specified. ([PR #18960](https://github.com/dotnet/fsharp/pull/18960))