From ff20f70d4d973f69b2661318918332aafab50a79 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 5 Feb 2020 09:44:55 -0600 Subject: [PATCH] cross-platform wrapper around memory-backed memorymappedfile creation (#8403) * cross-platform wrapper around memory-backed memorymappedfile creation * reenable FCS tests on non-windows platforms * publish test results on non-windows platforms * ensure correct .net sdk versions are installed regardless of VM image preloads * simple workaround for missing mscorlib versions to TFMs * publish per-framework xml results and report them in AZDO * rework mono fixes to use ByteArrayMemory directly * move runningOnMono call to bytes.fs and patch up callsites * revert to build-only on mono-containing platforms another MR will be required to fix the underlying logic before those can be changed to run tests again * trigger ci --- azure-pipelines.yml | 58 +++++++-- eng/Versions.props | 2 +- .../FSharp.Compiler.Service.Tests.fsproj | 10 +- fcs/build.fsx | 6 +- fcs/samples/FscExe/FscMain.fs | 2 +- src/absil/bytes.fs | 122 +++++++++++------- src/absil/bytes.fsi | 3 +- src/absil/il.fs | 18 --- src/absil/il.fsi | 2 - src/absil/ilread.fs | 7 +- src/absil/ilreflect.fs | 1 + src/absil/ilsupp.fs | 8 +- src/absil/ilwrite.fs | 13 +- src/absil/ilwritepdb.fs | 3 +- src/fsharp/CompileOps.fs | 1 + src/fsharp/CompileOptions.fs | 3 +- src/fsharp/DotNetFrameworkDependencies.fs | 25 ++-- src/fsharp/LegacyMSBuildReferenceResolver.fs | 2 +- src/fsharp/fsc.fs | 3 +- src/fsharp/fsi/fsi.fs | 1 + src/fsharp/service/service.fs | 3 +- tests/service/ScriptOptionsTests.fs | 36 ++++++ 22 files changed, 214 insertions(+), 115 deletions(-) create mode 100644 tests/service/ScriptOptionsTests.fs diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 566be9e28d..966baf9ee2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -342,6 +342,11 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + useGlobalJson: true + workingDirectory: fcs - script: fcs\build.cmd TestAndNuget displayName: Build / Test - task: PublishTestResults@2 @@ -350,6 +355,7 @@ stages: testResultsFormat: 'NUnit' testResultsFiles: '*.xml' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' + publishRunAttachments: true continueOnError: true condition: always() @@ -362,20 +368,48 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + useGlobalJson: true + workingDirectory: fcs - script: ./fcs/build.sh - displayName: Build + displayName: Build / Test + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' + publishRunAttachments: true + continueOnError: true + condition: always() - # - job: MacOS_FCS - # pool: - # vmImage: macOS-latest - # variables: - # - name: _SignType - # value: Test - # steps: - # - checkout: self - # clean: true - # - script: ./fcs/build.sh - # displayName: Build + - job: MacOS_FCS + pool: + vmImage: macOS-latest + variables: + - name: _SignType + value: Test + steps: + - checkout: self + clean: true + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + useGlobalJson: true + workingDirectory: fcs + - script: ./fcs/build.sh + displayName: Build / Test + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/Release' + publishRunAttachments: true + continueOnError: true + condition: always() #---------------------------------------------------------------------------------------------------------------------# # Post Build # diff --git a/eng/Versions.props b/eng/Versions.props index 1ee1522072..5b0f95663e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -183,7 +183,7 @@ 3.11.0 3.11.2 3.11.0 - 2.1.36 + 2.1.41 1.0.0-beta2-dev3 5.28.0.1 2.0.187 diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 072e2e0a58..2c80e36b01 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -1,5 +1,6 @@ + $(FcsTargetNetFxFramework);netcoreapp3.0 true @@ -60,6 +61,9 @@ TreeVisitorTests.fs + + ScriptOptionsTests.fs + Program.fs @@ -71,10 +75,10 @@ - - - + + + diff --git a/fcs/build.fsx b/fcs/build.fsx index 00dc80cf6f..c599d58135 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -73,9 +73,9 @@ Target.create "Test" (fun _ -> // This project file is used for the netcoreapp2.0 tests to work out reference sets runDotnet __SOURCE_DIRECTORY__ "build" "../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -nodereuse:false -v n /restore /p:DisableCompilerRedirection=true" - // Now run the tests - let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml") - runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -nodereuse:false -v n -c Release --test-adapter-path . --logger \"nunit;LogFilePath=%s\"" logFilePath) + // Now run the tests (different output files per TFM) + let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.{framework}.xml") + runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -nodereuse:false -v n -c Release --logger \"nunit;LogFilePath=%s\"" logFilePath) ) Target.create "NuGet" (fun _ -> diff --git a/fcs/samples/FscExe/FscMain.fs b/fcs/samples/FscExe/FscMain.fs index b2d5d6a899..36b980cbbb 100644 --- a/fcs/samples/FscExe/FscMain.fs +++ b/fcs/samples/FscExe/FscMain.fs @@ -8,7 +8,7 @@ open System.IO open System.Reflection open System.Runtime.CompilerServices open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.AbstractIL.IL // runningOnMono +open FSharp.Compiler.AbstractIL.Internal.Utils // runningOnMono open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.ErrorLogger diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 7e2f0ab2c9..52d041c367 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -12,6 +12,25 @@ open FSharp.NativeInterop #nowarn "9" +module Utils = + let runningOnMono = + #if ENABLE_MONO_SUPPORT + // Officially supported way to detect if we are running on Mono. + // See http://www.mono-project.com/FAQ:_Technical + // "How can I detect if am running in Mono?" section + try + System.Type.GetType ("Mono.Runtime") <> null + with _ -> + // Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent + // that is not reliable. + // This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is + // called by OnTypeResolveEvent. The function throws a NullReferenceException. I'm working with that team to get + // their issue fixed but we need to be robust here anyway. + false + #else + false + #endif + module internal Bytes = let b0 n = (n &&& 0xFF) let b1 n = ((n >>> 8) &&& 0xFF) @@ -296,65 +315,72 @@ type ByteMemory with member x.AsReadOnly() = ReadOnlyByteMemory x static member CreateMemoryMappedFile(bytes: ReadOnlyByteMemory) = - let length = int64 bytes.Length - let mmf = + if Utils.runningOnMono + then + // mono's MemoryMappedFile implementation throws with null `mapName`, so we use byte arrays instead: https://github.com/mono/mono/issues/10245 + ByteArrayMemory.FromArray (bytes.ToArray()) :> ByteMemory + else + let length = int64 bytes.Length let mmf = - MemoryMappedFile.CreateNew( - null, - length, - MemoryMappedFileAccess.ReadWrite, - MemoryMappedFileOptions.None, - HandleInheritability.None) - use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) - bytes.CopyTo stream - mmf + let mmf = MemoryMappedFile.CreateNew(null, length, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, HandleInheritability.None) + use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) + bytes.CopyTo stream + mmf - let accessor = mmf.CreateViewAccessor(0L, length, MemoryMappedFileAccess.ReadWrite) - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) + let accessor = mmf.CreateViewAccessor(0L, length, MemoryMappedFileAccess.ReadWrite) + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) static member FromFile(path, access, ?canShadowCopy: bool) = let canShadowCopy = defaultArg canShadowCopy false - let memoryMappedFileAccess = - match access with - | FileAccess.Read -> MemoryMappedFileAccess.Read - | FileAccess.Write -> MemoryMappedFileAccess.Write - | _ -> MemoryMappedFileAccess.ReadWrite + if Utils.runningOnMono + then + // mono's MemoryMappedFile implementation throws with null `mapName`, so we use byte arrays instead: https://github.com/mono/mono/issues/10245 + let bytes = File.ReadAllBytes path + ByteArrayMemory.FromArray bytes + else + let memoryMappedFileAccess = + match access with + | FileAccess.Read -> MemoryMappedFileAccess.Read + | FileAccess.Write -> MemoryMappedFileAccess.Write + | _ -> MemoryMappedFileAccess.ReadWrite - let mmf, accessor, length = let fileStream = File.Open(path, FileMode.Open, access, FileShare.Read) + let length = fileStream.Length - let mmf = - if canShadowCopy then - let mmf = - MemoryMappedFile.CreateNew( - null, - length, - MemoryMappedFileAccess.ReadWrite, - MemoryMappedFileOptions.None, - HandleInheritability.None) - use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) - fileStream.CopyTo(stream) - fileStream.Dispose() - mmf - else - MemoryMappedFile.CreateFromFile( - fileStream, - null, - length, - memoryMappedFileAccess, - HandleInheritability.None, - leaveOpen=false) - mmf, mmf.CreateViewAccessor(0L, length, memoryMappedFileAccess), length - // Validate MMF with the access that was intended. - match access with - | FileAccess.Read when not accessor.CanRead -> invalidOp "Cannot read file" - | FileAccess.Write when not accessor.CanWrite -> invalidOp "Cannot write file" - | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" - | _ -> () + let mmf, accessor, length = + let mmf = + if canShadowCopy then + let mmf = + MemoryMappedFile.CreateNew( + null, + length, + MemoryMappedFileAccess.ReadWrite, + MemoryMappedFileOptions.None, + HandleInheritability.None) + use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite) + fileStream.CopyTo(stream) + fileStream.Dispose() + mmf + else + MemoryMappedFile.CreateFromFile( + fileStream, + null, + length, + memoryMappedFileAccess, + HandleInheritability.None, + leaveOpen=false) + mmf, mmf.CreateViewAccessor(0L, length, memoryMappedFileAccess), length - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) + // Validate MMF with the access that was intended. + match access with + | FileAccess.Read when not accessor.CanRead -> invalidOp "Cannot read file" + | FileAccess.Write when not accessor.CanWrite -> invalidOp "Cannot write file" + | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" + | _ -> () + + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) static member FromUnsafePointer(addr, length, holder: obj) = RawByteMemory(NativePtr.ofNativeInt addr, length, holder) :> ByteMemory diff --git a/src/absil/bytes.fsi b/src/absil/bytes.fsi index 46b30b6c5a..55a48e3e46 100644 --- a/src/absil/bytes.fsi +++ b/src/absil/bytes.fsi @@ -5,10 +5,11 @@ namespace FSharp.Compiler.AbstractIL.Internal open System.IO open Internal.Utilities - open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.Internal +module Utils = + val runningOnMono: bool module internal Bytes = /// returned int will be 0 <= x <= 255 diff --git a/src/absil/il.fs b/src/absil/il.fs index 7e27e71da2..09cdbd5d32 100644 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -25,24 +25,6 @@ open Internal.Utilities let logging = false -let runningOnMono = -#if ENABLE_MONO_SUPPORT -// Officially supported way to detect if we are running on Mono. -// See http://www.mono-project.com/FAQ:_Technical -// "How can I detect if am running in Mono?" section - try - System.Type.GetType ("Mono.Runtime") <> null - with e-> - // Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent - // that is not reliable. - // This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is - // called by OnTypeResolveEvent. The function throws a NullReferenceException. I'm working with that team to get - // their issue fixed but we need to be robust here anyway. - false -#else - false -#endif - let _ = if logging then dprintn "* warning: Il.logging is on" let int_order = LanguagePrimitives.FastGenericComparer diff --git a/src/absil/il.fsi b/src/absil/il.fsi index 506878e1d6..7bbfad1eb2 100644 --- a/src/absil/il.fsi +++ b/src/absil/il.fsi @@ -2012,8 +2012,6 @@ type ILPropertyRef = member Name: string interface System.IComparable -val runningOnMono: bool - type ILReferences = { AssemblyReferences: ILAssemblyRef list ModuleReferences: ILModuleRef list } diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index b9994f6418..f399c05684 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -20,12 +20,13 @@ open System.Text open Internal.Utilities open Internal.Utilities.Collections open FSharp.NativeInterop -open FSharp.Compiler.AbstractIL.Internal -open FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL.Diagnostics +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.BinaryConstants -open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Support +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range open System.Reflection diff --git a/src/absil/ilreflect.fs b/src/absil/ilreflect.fs index 9657cf1794..7f048dd5b9 100644 --- a/src/absil/ilreflect.fs +++ b/src/absil/ilreflect.fs @@ -17,6 +17,7 @@ open System.Collections.Generic open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.ErrorLogger diff --git a/src/absil/ilsupp.fs b/src/absil/ilsupp.fs index a5dbe768b8..5773486388 100644 --- a/src/absil/ilsupp.fs +++ b/src/absil/ilsupp.fs @@ -3,9 +3,9 @@ module internal FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL -open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.AbstractIL.Internal.NativeRes +open FSharp.Compiler.AbstractIL.Internal.Utils #if FX_NO_CORHOST_SIGNER open FSharp.Compiler.AbstractIL.Internal.StrongNameSign #endif @@ -1287,7 +1287,7 @@ let getICLRStrongName () = | Some sn -> sn let signerGetPublicKeyForKeyPair kp = - if IL.runningOnMono then + if runningOnMono then let snt = System.Type.GetType("Mono.Security.StrongName") let sn = System.Activator.CreateInstance(snt, [| box kp |]) snt.InvokeMember("PublicKey", (BindingFlags.GetProperty ||| BindingFlags.Instance ||| BindingFlags.Public), null, sn, [| |], Globalization.CultureInfo.InvariantCulture) :?> byte[] @@ -1319,7 +1319,7 @@ let signerCloseKeyContainer kc = iclrSN.StrongNameKeyDelete kc |> ignore let signerSignatureSize (pk: byte[]) = - if IL.runningOnMono then + if runningOnMono then if pk.Length > 32 then pk.Length - 32 else 128 else let mutable pSize = 0u @@ -1328,7 +1328,7 @@ let signerSignatureSize (pk: byte[]) = int pSize let signerSignFileWithKeyPair fileName kp = - if IL.runningOnMono then + if runningOnMono then let snt = System.Type.GetType("Mono.Security.StrongName") let sn = System.Activator.CreateInstance(snt, [| box kp |]) let conv (x: obj) = if (unbox x: bool) then 0 else -1 diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 1464e29923..d86a2a710c 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -6,12 +6,13 @@ open System.Collections.Generic open System.IO open Internal.Utilities -open FSharp.Compiler.AbstractIL.IL -open FSharp.Compiler.AbstractIL.Diagnostics -open FSharp.Compiler.AbstractIL.Internal -open FSharp.Compiler.AbstractIL.Internal.BinaryConstants -open FSharp.Compiler.AbstractIL.Internal.Support -open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.Diagnostics +open FSharp.Compiler.AbstractIL.Internal +open FSharp.Compiler.AbstractIL.Internal.BinaryConstants +open FSharp.Compiler.AbstractIL.Internal.Support +open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 682b20a688..564cd99083 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -15,6 +15,7 @@ open Internal.Utilities open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range @@ -244,7 +245,7 @@ let pdbGetDebugInfo (contentId: byte[]) (timestamp: int32) (filepath: string) // This function takes output file name and returns debug file name. let getDebugFileName outfile (portablePDB: bool) = #if ENABLE_MONO_SUPPORT - if IL.runningOnMono && not portablePDB then + if runningOnMono && not portablePDB then outfile + ".mdb" else #else diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 23bd2ebc3e..dba6a0bd7d 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -20,6 +20,7 @@ open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Extensions.ILX open FSharp.Compiler.AbstractIL.Diagnostics diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 6510790668..911f913f2f 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -8,10 +8,11 @@ open Internal.Utilities open System open System.IO open FSharp.Compiler -open FSharp.Compiler.AbstractIL +open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Extensions.ILX open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.CompileOps diff --git a/src/fsharp/DotNetFrameworkDependencies.fs b/src/fsharp/DotNetFrameworkDependencies.fs index a454ec8059..2d27290586 100644 --- a/src/fsharp/DotNetFrameworkDependencies.fs +++ b/src/fsharp/DotNetFrameworkDependencies.fs @@ -115,13 +115,19 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies let desktopProductVersionMonikers = [| // major, minor, build, revision, moniker 4, 8, 3815, 0, "net48" + 4, 8, 3761, 0, "net48" 4, 7, 3190, 0, "net472" + 4, 7, 3062, 0, "net472" 4, 7, 2600, 0, "net471" + 4, 7, 2558, 0, "net471" 4, 7, 2053, 0, "net47" + 4, 7, 2046, 0, "net47" 4, 6, 1590, 0, "net462" + 4, 6, 57, 0, "net462" 4, 6, 1055, 0, "net461" 4, 6, 81, 0, "net46" 4, 0, 30319, 34209, "net452" + 4, 0, 30319, 17020, "net452" 4, 0, 30319, 18408, "net451" 4, 0, 30319, 17929, "net45" 4, 0, 30319, 1, "net4" @@ -138,14 +144,17 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies with _ -> defaultMscorlibVersion // Get the ProductVersion of this framework compare with table yield compatible monikers - let _, _, _, _, moniker = - desktopProductVersionMonikers - |> Array.find (fun (major, minor, build, revision, _) -> - (majorPart >= major) && - (minorPart >= minor) && - (buildPart >= build) && - (privatePart >= revision)) - moniker + match desktopProductVersionMonikers + |> Array.tryFind (fun (major, minor, build, revision, _) -> + (majorPart >= major) && + (minorPart >= minor) && + (buildPart >= build) && + (privatePart >= revision)) with + | Some (_,_,_,_,moniker) -> + moniker + | None -> + // no TFM could be found, assume latest stable? + "net48" /// Gets the tfm E.g netcore3.0, net472 let executionTfm = diff --git a/src/fsharp/LegacyMSBuildReferenceResolver.fs b/src/fsharp/LegacyMSBuildReferenceResolver.fs index a07941509f..c0f2596c39 100644 --- a/src/fsharp/LegacyMSBuildReferenceResolver.fs +++ b/src/fsharp/LegacyMSBuildReferenceResolver.fs @@ -344,7 +344,7 @@ module LegacyMSBuildReferenceResolver #if ENABLE_MONO_SUPPORT // The properties TargetedRuntimeVersion and CopyLocalDependenciesWhenParentReferenceInGac // are not available on Mono. So we only set them if available (to avoid a compile-time dependency). - if not FSharp.Compiler.AbstractIL.IL.runningOnMono then + if not FSharp.Compiler.AbstractIL.Internal.Utils.runningOnMono then typeof.InvokeMember("TargetedRuntimeVersion",(BindingFlags.Instance ||| BindingFlags.SetProperty ||| BindingFlags.Public),null,rar,[| box targetedRuntimeVersionValue |]) |> ignore typeof.InvokeMember("CopyLocalDependenciesWhenParentReferenceInGac",(BindingFlags.Instance ||| BindingFlags.SetProperty ||| BindingFlags.Public),null,rar,[| box true |]) |> ignore #else diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index c717d9b6e3..7bb4306668 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -29,8 +29,9 @@ open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader -open FSharp.Compiler.AbstractIL.Internal +open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.IlxGen diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index aece6638ff..cf634a6103 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -29,6 +29,7 @@ open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.AbstractIL.ILRuntimeWriter open FSharp.Compiler.Lib open FSharp.Compiler.AccessibilityLogic diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index a5db4e09b4..d0852143ee 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -12,7 +12,8 @@ open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader -open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.AbstractIL.Internal.Utils open FSharp.Compiler.Ast open FSharp.Compiler.CompileOps diff --git a/tests/service/ScriptOptionsTests.fs b/tests/service/ScriptOptionsTests.fs new file mode 100644 index 0000000000..be38f9ff72 --- /dev/null +++ b/tests/service/ScriptOptionsTests.fs @@ -0,0 +1,36 @@ +#if INTERACTIVE +#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive +#r "../../artifacts/bin/fcs/net461/nunit.framework.dll" +#load "FsUnit.fs" +#load "Common.fs" +#else +module Tests.Service.ScriptOptions +#endif + +open NUnit.Framework +open FsUnit +open System +open FSharp.Compiler +open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.Service.Tests.Common + +// Add additional imports/constructs into this script text to verify that common scenarios +// for FCS script typechecking can be supported +let scriptSource = """ +open System +let pi = Math.PI +""" + +[] +[] +[] +let ``can generate options for different frameworks regardless of execution environment``(assumeNetFx, useSdk, flags) = + let path = IO.Path.GetTempPath() + let file = IO.Path.GetTempFileName() + let tempFile = IO.Path.Combine(path, file) + let (options, errors) = + checker.GetProjectOptionsFromScript(tempFile, Text.SourceText.ofString scriptSource, assumeDotNetFramework = assumeNetFx, useSdkRefs = useSdk, otherFlags = flags) + |> Async.RunSynchronously + match errors with + | [] -> () + | errors -> failwithf "Error while parsing script with assumeDotNetFramework:%b, useSdkRefs:%b, and otherFlags:%A:\n%A" assumeNetFx useSdk flags errors \ No newline at end of file