diff --git a/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj b/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj index 42febe9c5a5..0bbcd502150 100644 --- a/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj +++ b/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj @@ -21,12 +21,11 @@ - + - Microsoft.FSharp.Targets diff --git a/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj b/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj index a6505441b5b..e7ccc386e61 100644 --- a/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj +++ b/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj @@ -22,16 +22,13 @@ CompilerLocationUtils.fs - - CreateFSharpManifestResourceName.fsi - CreateFSharpManifestResourceName.fs - - Fsc.fsi - - + + FSharpCommandLineBuilder.fs + + Fsc.fs diff --git a/src/fsharp/FSharp.Build/CreateFSharpManifestResourceName.fsi b/src/fsharp/FSharp.Build/CreateFSharpManifestResourceName.fsi deleted file mode 100644 index 549f1ab8366..00000000000 --- a/src/fsharp/FSharp.Build/CreateFSharpManifestResourceName.fsi +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.FSharp.Build - -[] -type CreateFSharpManifestResourceName = - inherit Microsoft.Build.Tasks.CreateCSharpManifestResourceName - public new : unit -> CreateFSharpManifestResourceName - member UseStandardResourceNames : bool with get,set \ No newline at end of file diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 5c8982e34c4..5bc7c9f75bc 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -20,23 +20,16 @@ false false - - - - - - - + - Microsoft.FSharp.Targets diff --git a/src/fsharp/FSharp.Build/FSharpCommandLineBuilder.fs b/src/fsharp/FSharp.Build/FSharpCommandLineBuilder.fs new file mode 100644 index 00000000000..8ea25e12d61 --- /dev/null +++ b/src/fsharp/FSharp.Build/FSharpCommandLineBuilder.fs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Build + +open System +open System.Text +open Microsoft.Build.Framework +open Microsoft.Build.Utilities +open Internal.Utilities + +[] +[] +do() + +type FSharpCommandLineBuilder () = + + // In addition to generating a command-line that will be handed to cmd.exe, we also generate + // an array of individual arguments. The former needs to be quoted (and cmd.exe will strip the + // quotes while parsing), whereas the latter is not. See bug 4357 for background; this helper + // class gets us out of the business of unparsing-then-reparsing arguments. + + let builder = new CommandLineBuilder() + let mutable args = [] // in reverse order + let mutable srcs = [] // in reverse order + + /// Return a list of the arguments (with no quoting for the cmd.exe shell) + member x.CapturedArguments() = List.rev args + + /// Return a list of the sources (with no quoting for the cmd.exe shell) + member x.CapturedFilenames() = List.rev srcs + + /// Return a full command line (with quoting for the cmd.exe shell) + override x.ToString() = builder.ToString() + + member x.AppendFileNamesIfNotNull(filenames:ITaskItem array, sep:string) = + builder.AppendFileNamesIfNotNull(filenames, sep) + // do not update "args", not used + for item in filenames do + let tmp = new CommandLineBuilder() + tmp.AppendSwitchUnquotedIfNotNull("", item.ItemSpec) // we don't want to quote the filename, this is a way to get that + let s = tmp.ToString() + if s <> String.Empty then + srcs <- tmp.ToString() :: srcs + + member x.AppendSwitchIfNotNull(switch:string, values:string array, sep:string) = + builder.AppendSwitchIfNotNull(switch, values, sep) + let tmp = new CommandLineBuilder() + tmp.AppendSwitchUnquotedIfNotNull(switch, values, sep) + let s = tmp.ToString() + if s <> String.Empty then + args <- s :: args + + member x.AppendSwitchIfNotNull(switch:string, value:string, ?metadataNames:string array) = + let metadataNames = defaultArg metadataNames [||] + builder.AppendSwitchIfNotNull(switch, value) + let tmp = new CommandLineBuilder() + tmp.AppendSwitchUnquotedIfNotNull(switch, value) + let providedMetaData = + metadataNames + |> Array.filter (String.IsNullOrWhiteSpace >> not) + if providedMetaData.Length > 0 then + tmp.AppendTextUnquoted "," + tmp.AppendTextUnquoted (providedMetaData|> String.concat ",") + let s = tmp.ToString() + if s <> String.Empty then + args <- s :: args + + member x.AppendSwitchUnquotedIfNotNull(switch:string, value:string) = + assert(switch = "") // we only call this method for "OtherFlags" + // Unfortunately we still need to mimic what cmd.exe does, but only for "OtherFlags". + let ParseCommandLineArgs(commandLine:string) = // returns list in reverse order + let mutable args = [] + let mutable i = 0 // index into commandLine + let len = commandLine.Length + while i < len do + // skip whitespace + while i < len && System.Char.IsWhiteSpace(commandLine, i) do + i <- i + 1 + if i < len then + // parse an argument + let sb = new StringBuilder() + let mutable finished = false + let mutable insideQuote = false + while i < len && not finished do + match commandLine.[i] with + | '"' -> insideQuote <- not insideQuote; i <- i + 1 + | c when not insideQuote && System.Char.IsWhiteSpace(c) -> finished <- true + | c -> sb.Append(c) |> ignore; i <- i + 1 + args <- sb.ToString() :: args + args + builder.AppendSwitchUnquotedIfNotNull(switch, value) + let tmp = new CommandLineBuilder() + tmp.AppendSwitchUnquotedIfNotNull(switch, value) + let s = tmp.ToString() + if s <> String.Empty then + args <- ParseCommandLineArgs(s) @ args + + member x.AppendSwitch(switch:string) = + builder.AppendSwitch(switch) + args <- switch :: args + + member internal x.GetCapturedArguments() = + [| + yield! x.CapturedArguments() + yield! x.CapturedFilenames() + |] diff --git a/src/fsharp/FSharp.Build/Fsc.fs b/src/fsharp/FSharp.Build/Fsc.fs index 2d1bc51cea7..f397c50914c 100644 --- a/src/fsharp/FSharp.Build/Fsc.fs +++ b/src/fsharp/FSharp.Build/Fsc.fs @@ -3,125 +3,28 @@ namespace Microsoft.FSharp.Build open System -open System.Text -open System.Diagnostics.CodeAnalysis +open System.Diagnostics +open System.Globalization open System.IO open System.Reflection open Microsoft.Build.Framework open Microsoft.Build.Utilities open Internal.Utilities -[] -[] - -[] -do() - - #if FX_RESHAPED_REFLECTION open Microsoft.FSharp.Core.ReflectionAdapters #endif -type FscCommandLineBuilder () = - - // In addition to generating a command-line that will be handed to cmd.exe, we also generate - // an array of individual arguments. The former needs to be quoted (and cmd.exe will strip the - // quotes while parsing), whereas the latter is not. See bug 4357 for background; this helper - // class gets us out of the business of unparsing-then-reparsing arguments. - - let builder = new CommandLineBuilder() - let mutable args = [] // in reverse order - let mutable srcs = [] // in reverse order - /// Return a list of the arguments (with no quoting for the cmd.exe shell) - member x.CapturedArguments() = - List.rev args - /// Return a list of the sources (with no quoting for the cmd.exe shell) - member x.CapturedFilenames() = - List.rev srcs - /// Return a full command line (with quoting for the cmd.exe shell) - override x.ToString() = - builder.ToString() - - member x.AppendFileNamesIfNotNull(filenames:ITaskItem array, sep:string) = - builder.AppendFileNamesIfNotNull(filenames, sep) - // do not update "args", not used - for item in filenames do - let tmp = new CommandLineBuilder() - tmp.AppendSwitchUnquotedIfNotNull("", item.ItemSpec) // we don't want to quote the filename, this is a way to get that - let s = tmp.ToString() - if s <> String.Empty then - srcs <- tmp.ToString() :: srcs - - member x.AppendSwitchIfNotNull(switch:string, values:string array, sep:string) = - builder.AppendSwitchIfNotNull(switch, values, sep) - let tmp = new CommandLineBuilder() - tmp.AppendSwitchUnquotedIfNotNull(switch, values, sep) - let s = tmp.ToString() - if s <> String.Empty then - args <- s :: args - - member x.AppendSwitchIfNotNull(switch:string, value:string, ?metadataNames:string array) = - let metadataNames = defaultArg metadataNames [||] - builder.AppendSwitchIfNotNull(switch, value) - let tmp = new CommandLineBuilder() - tmp.AppendSwitchUnquotedIfNotNull(switch, value) - let providedMetaData = - metadataNames - |> Array.filter (String.IsNullOrWhiteSpace >> not) - if providedMetaData.Length > 0 then - tmp.AppendTextUnquoted "," - tmp.AppendTextUnquoted (providedMetaData|> String.concat ",") - let s = tmp.ToString() - if s <> String.Empty then - args <- s :: args - - member x.AppendSwitchUnquotedIfNotNull(switch:string, value:string) = - assert(switch = "") // we only call this method for "OtherFlags" - // Unfortunately we still need to mimic what cmd.exe does, but only for "OtherFlags". - let ParseCommandLineArgs(commandLine:string) = // returns list in reverse order - let mutable args = [] - let mutable i = 0 // index into commandLine - let len = commandLine.Length - while i < len do - // skip whitespace - while i < len && System.Char.IsWhiteSpace(commandLine, i) do - i <- i + 1 - if i < len then - // parse an argument - let sb = new StringBuilder() - let mutable finished = false - let mutable insideQuote = false - while i < len && not finished do - match commandLine.[i] with - | '"' -> insideQuote <- not insideQuote; i <- i + 1 - | c when not insideQuote && System.Char.IsWhiteSpace(c) -> finished <- true - | c -> sb.Append(c) |> ignore; i <- i + 1 - args <- sb.ToString() :: args - args - builder.AppendSwitchUnquotedIfNotNull(switch, value) - let tmp = new CommandLineBuilder() - tmp.AppendSwitchUnquotedIfNotNull(switch, value) - let s = tmp.ToString() - if s <> String.Empty then - args <- ParseCommandLineArgs(s) @ args - - member x.AppendSwitch(switch:string) = - builder.AppendSwitch(switch) - args <- switch :: args - - member internal x.GetCapturedArguments() = - [| - yield! x.CapturedArguments() - yield! x.CapturedFilenames() - |] - //There are a lot of flags on fsc.exe. //For now, not all of them are represented in the "Fsc class" object model. //The goal is to have the most common/important flags available via the Fsc class, and the //rest can be "backdoored" through the .OtherFlags property. -type [] Fsc() as this = - inherit ToolTask() +[] +type public Fsc () as this = + + inherit ToolTask () + let mutable baseAddress : string = null let mutable capturedArguments : string list = [] // list of individual args, to pass to HostObject Compile() let mutable capturedFilenames : string list = [] // list of individual source filenames, to pass to HostObject Compile() @@ -160,9 +63,9 @@ type [.Assembly.Location)) + let mutable toolPath : string = + let locationOfThisDll = + try Some(Path.GetDirectoryName(typeof.Assembly.Location)) with _ -> None match FSharpEnvironment.BinFolderOfDefaultFSharpCompiler(locationOfThisDll) with | Some s -> s @@ -178,18 +81,11 @@ type [ null with e-> false - do if not runningOnMono then - typeof.InvokeMember("YieldDuringToolExecution",(BindingFlags.Instance ||| BindingFlags.SetProperty ||| BindingFlags.Public),null,this,[| box true |]) |> ignore -#else - do this.YieldDuringToolExecution <- true // See bug 6483; this makes parallel build faster, and is fine to set unconditionally -#endif + // See bug 6483; this makes parallel build faster, and is fine to set unconditionally + do this.YieldDuringToolExecution <- true let generateCommandLineBuilder () = - let builder = new FscCommandLineBuilder() + let builder = new FSharpCommandLineBuilder() // OutputAssembly builder.AppendSwitchIfNotNull("-o:", outputAssembly) // CodePage @@ -198,7 +94,7 @@ type [ null @@ -219,7 +115,7 @@ type [ null then for item in defineConstants do - builder.AppendSwitchIfNotNull("--define:", item.ItemSpec) + builder.AppendSwitchIfNotNull("--define:", item.ItemSpec) // DocumentationFile builder.AppendSwitchIfNotNull("--doc:", documentationFile) // GenerateInterfaceFile @@ -238,7 +134,7 @@ type [ "anycpu" | "X86" , _, _ -> "x86" | "X64" , _, _ -> "x64" - | "ITANIUM", _, _ -> "Itanium" - | _ -> null) + | _ -> null) // Resources if resources <> null then for item in resources do match useStandardResourceNames with | true -> builder.AppendSwitchIfNotNull("--resource:", item.ItemSpec, [|item.GetMetadata("LogicalName"); item.GetMetadata("Access")|]) | false -> builder.AppendSwitchIfNotNull("--resource:", item.ItemSpec) - + // VersionFile builder.AppendSwitchIfNotNull("--versionfile:", versionFile) // References @@ -266,7 +161,7 @@ type [ null | _ -> referencePath.Split([|';'; ','|], StringSplitOptions.RemoveEmptyEntries) - + builder.AppendSwitchIfNotNull("--lib:", referencePathArray, ",") // TargetType builder.AppendSwitchIfNotNull("--target:", @@ -296,9 +191,9 @@ type [ [|"76"|] - | _ -> (warningsAsErrors + " 76 ").Split([|' '; ';'; ','|], StringSplitOptions.RemoveEmptyEntries) + | _ -> (warningsAsErrors + " 76 ").Split([|' '; ';'; ','|], StringSplitOptions.RemoveEmptyEntries) - builder.AppendSwitchIfNotNull("--warnaserror:", warningsAsErrorsArray, ",") + builder.AppendSwitchIfNotNull("--warnaserror:", warningsAsErrorsArray, ",") // Win32ResourceFile builder.AppendSwitchIfNotNull("--win32res:", win32res) @@ -306,16 +201,16 @@ type [: Specify the codepage to use when opening source files member fsc.CodePage @@ -369,7 +264,7 @@ type [: Do not report the given specific warning. member fsc.DisabledWarnings with get() = disabledWarnings - and set(a) = disabledWarnings <- a + and set(a) = disabledWarnings <- a // --define : Define the given conditional compilation symbol. member fsc.DefineConstants @@ -399,7 +294,7 @@ type [: // Sign the assembly the given keypair file, as produced @@ -435,13 +330,13 @@ type [: Name the output file. + // -o : Name the output file member fsc.OutputAssembly with get() = outputAssembly and set(s) = outputAssembly <- s // --pdb : - // Name the debug output file. + // Name the debug output file member fsc.PdbFile with get() = pdbFile and set(s) = pdbFile <- s @@ -449,36 +344,35 @@ type [: Limit which platforms this code can run on: // x86 // x64 - // Itanium // anycpu // anycpu32bitpreferred member fsc.Platform with get() = platform - and set(s) = platform <- s + and set(s) = platform <- s // indicator whether anycpu32bitpreferred is applicable or not member fsc.Prefer32Bit with get() = prefer32bit - and set(s) = prefer32bit <- s + and set(s) = prefer32bit <- s member fsc.PreferredUILang with get() = preferredUILang - and set(s) = preferredUILang <- s + and set(s) = preferredUILang <- s - member fsc.ProvideCommandLineArgs + member fsc.ProvideCommandLineArgs with get() = provideCommandLineArgs and set(p) = provideCommandLineArgs <- p member fsc.PublicSign with get() = publicSign - and set(s) = publicSign <- s + and set(s) = publicSign <- s // -r : Reference an F# or .NET assembly. - member fsc.References - with get() = references + member fsc.References + with get() = references and set(a) = references <- a - // --lib + // --lib member fsc.ReferencePath with get() = referencePath and set(s) = referencePath <- s @@ -489,7 +383,7 @@ type [: member fsc.VersionFile with get() = versionFile and set(s) = versionFile <- s - // For specifying a win32 native resource file (.res) + // For specifying a win32 native resource file (.res) member fsc.Win32ResourceFile with get() = win32res and set(s) = win32res <- s - + // For specifying a win32 manifest file member fsc.Win32ManifestFile with get() = win32manifest and set(m) = win32manifest <- m - // For specifying the warning level (0-4) + // For specifying the warning level (0-4) member fsc.WarningLevel with get() = warningLevel and set(s) = warningLevel <- s @@ -591,7 +486,7 @@ type [ Array.map (fun (arg: string) -> TaskItem(arg) :> ITaskItem) |> Array.toList @@ -604,30 +499,42 @@ type [ base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands) | _ -> let sources = sources|>Array.map(fun i->i.ItemSpec) -#if FX_NO_CONVERTER - let baseCallDelegate = new Func(fun () -> fsc.BaseExecuteTool(pathToTool, responseFileCommands, commandLineCommands) ) -#else - let baseCall = fun (dummy : int) -> fsc.BaseExecuteTool(pathToTool, responseFileCommands, commandLineCommands) - // We are using a Converter rather than a "unit->int" because it is too hard to - // figure out how to pass an F# function object via reflection. - let baseCallDelegate = new System.Converter(baseCall) -#endif - try - let ret = - (host.GetType()).InvokeMember("Compile", BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.InvokeMethod ||| BindingFlags.Instance, null, host, - [| baseCallDelegate; box (capturedArguments |> List.toArray); box (capturedFilenames |> List.toArray) |], - System.Globalization.CultureInfo.InvariantCulture) - unbox ret - with - | :? System.Reflection.TargetInvocationException as tie when (match tie.InnerException with | :? Microsoft.Build.Exceptions.BuildAbortedException -> true | _ -> false) -> - fsc.Log.LogError(tie.InnerException.Message, [| |]) - -1 // ok, this is what happens when VS IDE cancels the build, no need to assert, just log the build-canceled error and return -1 to denote task failed + let invokeCompiler baseCallDelegate = + try + let ret = + (host.GetType()).InvokeMember("Compile", BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.InvokeMethod ||| BindingFlags.Instance, null, host, + [| baseCallDelegate; box (capturedArguments |> List.toArray); box (capturedFilenames |> List.toArray) |], + CultureInfo.InvariantCulture) + unbox ret + with + | :? TargetInvocationException as tie when (match tie.InnerException with | :? Microsoft.Build.Exceptions.BuildAbortedException -> true | _ -> false) -> + fsc.Log.LogError(tie.InnerException.Message, [| |]) + -1 // ok, this is what happens when VS IDE cancels the build, no need to assert, just log the build-canceled error and return -1 to denote task failed + | e -> reraise() + + // Todo: Remove !FX_NO_CONVERTER code path for VS2017.7 + // Earlier buildtasks usesd System.Converter for cross platform we are moving to Func + // This is so that during the interim, earlier VS's will still load the OSS project + let baseCallDelegate = Func(fun () -> fsc.BaseExecuteTool(pathToTool, responseFileCommands, commandLineCommands) ) + try + invokeCompiler baseCallDelegate + with | e -> - System.Diagnostics.Debug.Assert(false, "HostObject received by Fsc task did not have a Compile method or the compile method threw an exception. "+(e.ToString())) - reraise() +#if !FX_NO_CONVERTER + try + let baseCall = fun (dummy : int) -> fsc.BaseExecuteTool(pathToTool, responseFileCommands, commandLineCommands) + // We are using a Converter rather than a "unit->int" because it is too hard to + // figure out how to pass an F# function object via reflection. + let baseCallDelegate = new System.Converter(baseCall) + invokeCompiler baseCallDelegate + with + | e -> +#endif + Debug.Assert(false, "HostObject received by Fsc task did not have a Compile method or the compile method threw an exception. "+(e.ToString())) + reraise() override fsc.GenerateCommandLineCommands() = - let builder = new FscCommandLineBuilder() + let builder = new FSharpCommandLineBuilder() if not (String.IsNullOrEmpty(dotnetFscCompilerPath)) then builder.AppendSwitch(dotnetFscCompilerPath) builder.ToString() @@ -640,18 +547,14 @@ type [] - do() diff --git a/src/fsharp/FSharp.Build/Fsc.fsi b/src/fsharp/FSharp.Build/Fsc.fsi deleted file mode 100644 index e05d4f9e69e..00000000000 --- a/src/fsharp/FSharp.Build/Fsc.fsi +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -/// This namespace contains. MSBuild tasks for the FsYacc and FsLex tools. -namespace Microsoft.FSharp.Build -type Fsc = class - inherit Microsoft.Build.Utilities.ToolTask - new : unit -> Fsc - override GenerateCommandLineCommands : unit -> System.String - override GenerateFullPathToTool : unit -> System.String - override ToolName : System.String - override StandardErrorEncoding : System.Text.Encoding - override StandardOutputEncoding : System.Text.Encoding - - member internal InternalGenerateFullPathToTool : unit -> System.String - member internal InternalGenerateCommandLineCommands : unit -> System.String - member internal InternalGenerateResponseFileCommands : unit -> System.String - member internal InternalExecuteTool : string * string * string -> int - member internal GetCapturedArguments : unit -> string[] - member BaseAddress : string with get,set - member CodePage : string with get,set - member CommandLineArgs : Microsoft.Build.Framework.ITaskItem [] with get,set - member DebugSymbols : bool with get,set - member DebugType : string with get,set - member DefineConstants : Microsoft.Build.Framework.ITaskItem [] with get,set - member DelaySign : bool with get,set - member DisabledWarnings : string with get,set - member DocumentationFile : string with get,set - member DotnetFscCompilerPath : string with get,set - member Embed : string with get,set - member EmbedAllSources : bool with get,set - member GenerateInterfaceFile : string with get,set - member HighEntropyVA : bool with get,set - member KeyFile : string with get,set - member LCID : string with get,set - member NoFramework : bool with get,set - member Optimize : bool with get,set - member OtherFlags : string with get,set - member OutputAssembly : string with get,set - member PdbFile : string with get,set - member Platform : string with get,set - member Prefer32Bit : bool with get,set - member PreferredUILang : string with get,set - member ProvideCommandLineArgs : bool with get,set - member PublicSign : bool with get,set - member VersionFile : string with get,set - member References : Microsoft.Build.Framework.ITaskItem [] with get,set - member ReferencePath : string with get,set - member Resources : Microsoft.Build.Framework.ITaskItem [] with get,set - member SkipCompilerExecution : bool with get,set - member SourceLink : string with get,set - member Sources : Microsoft.Build.Framework.ITaskItem [] with get,set - member SubsystemVersion : string with get,set - member Tailcalls : bool with get,set - member TargetType : string with get,set - member ToolPath : string with get,set - member TargetProfile : string with get,set - member TreatWarningsAsErrors : bool with get,set - member UseStandardResourceNames : bool with get,set - member Utf8Output : bool with get,set - member VisualStudioStyleErrors : bool with get,set - member WarningLevel : string with get,set - member WarningsAsErrors : string with get,set - member Win32ResourceFile : string with get,set - member Win32ManifestFile : string with get,set - end diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index 1a4732cf1e5..8e11b8651f6 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -1290,8 +1290,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem let result = base.InvokeMsBuild(target, extraProperties) result - // Fulfill HostObject contract with Fsc task, and enable 'capture' of compiler flags for the project. - member x.Compile(compile:System.Converter, flags:string[], sources:string[]) = + member x.CoreCompile(flags:string[], sources:string[]) = // Note: This method may be called from non-UI thread! The Fsc task in FSharp.Build.dll invokes this method via reflection, and // the Fsc task is typically created by MSBuild on a background thread. So be careful. #if DEBUG @@ -1306,11 +1305,26 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem if projectSite.State = ProjectSiteOptionLifetimeState.Opening then // This is the first time, so set up interface for language service to talk to us projectSite.Open(x.CreateRunningProjectSite()) + + // ===================================================================================================== + // Todo: x.Compile(compile:System.Converter, flags:string[], sources:string[]) for VS2017.7 + // Earlier buildtasks usesd System.Converter for cross platform we are moving to Func + // This is so that during the interim, earlier VS's will still load the OSS project + // ===================================================================================================== + member x.Compile(compile:System.Converter, flags:string[], sources:string[]) = + x.CoreCompile(flags, sources) if actuallyBuild then compile.Invoke(0) else 0 + member x.Compile(compile:Func, flags:string[], sources:string[]) = + x.CoreCompile(flags, sources) + if actuallyBuild then + compile.Invoke() + else + 0 + member __.CompilationSourceFiles = match sourcesAndFlags with None -> [| |] | Some (sources,_) -> sources member __.CompilationOptions = match sourcesAndFlags with None -> [| |] | Some (_,flags) -> flags member __.CompilationReferences = match normalizedRefs with None -> [| |] | Some refs -> refs diff --git a/vsintegration/tests/unittests/Tests.Build.fs b/vsintegration/tests/unittests/Tests.Build.fs index e5bbddc166c..22faaef01a8 100644 --- a/vsintegration/tests/unittests/Tests.Build.fs +++ b/vsintegration/tests/unittests/Tests.Build.fs @@ -336,21 +336,6 @@ type Build() = "--highentropyva-" + Environment.NewLine) cmd - [] - member public this.TestPlatform2() = - let tool = new Microsoft.FSharp.Build.Fsc() - tool.Platform <- "itanium" - AssertEqual "itanium" tool.Platform - let cmd = tool.InternalGenerateResponseFileCommands() - printfn "cmd=\"%s\"" cmd - AssertEqual ("--optimize+" + Environment.NewLine + - "--platform:Itanium" + Environment.NewLine + - "--warnaserror:76" + Environment.NewLine + - "--fullpaths" + Environment.NewLine + - "--flaterrors" + Environment.NewLine + - "--highentropyva-" + Environment.NewLine) - cmd - [] member public this.TestPlatform3() = let tool = new Microsoft.FSharp.Build.Fsc()