Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/buildfromsource/FSharp.Build/FSharp.Build.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@
<Compile Include="..\..\assemblyinfo\assemblyinfo.FSharp.Build.dll.fs" />
<Compile Include="..\..\utils\CompilerLocationUtils.fs" />
<Compile Include="..\..\utils\reshapedreflection.fs" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\Fsc.fsi" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\FSharpCommandLineBuilder.fs" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\Fsc.fs" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\FSharpEmbedResourceText.fs" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\FSharpEmbedResXSource.fs" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\WriteCodeFragment.fs" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\CreateFSharpManifestResourceName.fsi" />
<Compile Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\CreateFSharpManifestResourceName.fs" />
<CopyAndSubstituteText Include="$(FSharpSourcesRoot)\fsharp\FSharp.Build\Microsoft.FSharp.Targets">
<TargetFilename>Microsoft.FSharp.Targets</TargetFilename>
Expand Down
11 changes: 4 additions & 7 deletions src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@
<Compile Include="..\..\utils\CompilerLocationUtils.fs">
<Link>CompilerLocationUtils.fs</Link>
</Compile>
<Compile Include="..\FSharp.Build\CreateFSharpManifestResourceName.fsi">
<Link>CreateFSharpManifestResourceName.fsi</Link>
</Compile>
<Compile Include="..\FSharp.Build\CreateFSharpManifestResourceName.fs" >
<Link>CreateFSharpManifestResourceName.fs</Link>
</Compile>
<Compile Include="..\FSharp.Build\Fsc.fsi">
<Link>Fsc.fsi</Link>
</Compile>
<Compile Include="..\FSharp.Build\Fsc.fs">
<Compile Include="..\FSharp.Build\FSharpCommandLineBuilder.fs">
<Link>FSharpCommandLineBuilder.fs</Link>
</Compile>
<Compile Include="..\FSharp.Build\Fsc.fs">
<Link>Fsc.fs</Link>
</Compile>
<Compile Include="..\FSharp.Build\FSharpEmbedResourceText.fs">
Expand Down
9 changes: 0 additions & 9 deletions src/fsharp/FSharp.Build/CreateFSharpManifestResourceName.fsi

This file was deleted.

9 changes: 1 addition & 8 deletions src/fsharp/FSharp.Build/FSharp.Build.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,16 @@
<HasLceComments>false</HasLceComments>
<InProject>false</InProject>
</FilesToLocalize>
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="VisualFSharp.Unittests" />
</ItemGroup>

<ItemGroup>
<EmbeddedText Include="FSBuild.txt" />
<Compile Include="..\..\assemblyinfo\assemblyinfo.FSharp.Build.dll.fs" />
<Compile Include="..\..\utils\CompilerLocationUtils.fs" />
<Compile Include="..\..\utils\reshapedreflection.fs" />
<Compile Include="Fsc.fsi" />
<Compile Include="FSharpCommandLineBuilder.fs" />
<Compile Include="Fsc.fs" />
<Compile Include="FSharpEmbedResourceText.fs" />
<Compile Include="FSharpEmbedResXSource.fs" />
<Compile Include="WriteCodeFragment.fs" />
<Compile Include="CreateFSharpManifestResourceName.fsi" />
<Compile Include="CreateFSharpManifestResourceName.fs" />
<CopyAndSubstituteText Include="Microsoft.FSharp.Targets">
<TargetFilename>Microsoft.FSharp.Targets</TargetFilename>
Expand Down
106 changes: 106 additions & 0 deletions src/fsharp/FSharp.Build/FSharpCommandLineBuilder.fs
Original file line number Diff line number Diff line change
@@ -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

[<assembly: System.Runtime.InteropServices.ComVisible(false)>]
[<assembly: System.CLSCompliant(true)>]
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()
|]
Loading