Use ToolTask for ShellWrapper for simpler effective logging

This commit is contained in:
Thomas Goyne 2012-11-09 19:30:31 -08:00
parent e7ab194809
commit 31e347febf

View file

@ -22,15 +22,6 @@ open Microsoft.Build.Evaluation
open Microsoft.Build.Framework open Microsoft.Build.Framework
open Microsoft.Build.Utilities open Microsoft.Build.Utilities
/// Search the executable path for the directory containing the given file and
/// return it or empty string if not found
let searchPath file =
Environment.GetEnvironmentVariable("path").Split ';'
|> Seq.map (fun p -> IO.Path.Combine(p, file))
|> Seq.filter IO.File.Exists
|> Seq.append [""]
|> Seq.nth 1
/// Read all of the defined properties from the calling project file and stuff /// Read all of the defined properties from the calling project file and stuff
/// them in a Map /// them in a Map
let propertyMap (be : IBuildEngine) = let propertyMap (be : IBuildEngine) =
@ -49,69 +40,79 @@ let mungePath projectDir path =
let matchre pat str = let matchre pat str =
let m = System.Text.RegularExpressions.Regex.Match(str, pat) let m = System.Text.RegularExpressions.Regex.Match(str, pat)
if m.Success if m.Success
then List.tail [ for g in m.Groups -> g.Value ] then List.tail [ for g in m.Groups -> g.Value ]
else [] else []
match IO.Path.Combine(projectDir, path) |> matchre "([A-Za-z]):\\\\(.*)" with match IO.Path.Combine(projectDir, path) |> matchre "([A-Za-z]):\\\\(.*)" with
| drive :: path :: [] -> sprintf "/%s/%s" drive (path.Replace('\\', '/')) | drive :: path :: [] -> sprintf "/%s/%s" drive (path.Replace('\\', '/'))
| _ -> failwith <| sprintf "Bad path: '%s' '%s'" projectDir path | _ -> failwith <| sprintf "Bad path: '%s' '%s'" projectDir path
type ShellWrapper(props : Map<String, String>) = type ShellWrapper(props : Map<String, String>) =
let setPath msysRoot = inherit ToolTask()
Environment.SetEnvironmentVariable("path", msysRoot + "\\bin;" + props.["NativeExecutablePath"])
Environment.SetEnvironmentVariable("CC", "cl")
Environment.SetEnvironmentVariable("INCLUDE", props.["IncludePath"])
Environment.SetEnvironmentVariable("LIB", props.["LibraryPath"])
let sh =
match props.TryFind "MsysBasePath" with
| None | Some "" -> searchPath "sh.exe"
| Some path -> setPath path; sprintf "%s\\bin\\sh.exe" path
let cwd = function let cwd = function
| null | "" -> props.["AegisubSourceBase"] | null | "" -> props.["AegisubSourceBase"]
| x -> if not <| IO.Directory.Exists x then ignore <| IO.Directory.CreateDirectory(x) | x -> if not <| IO.Directory.Exists x then ignore <| IO.Directory.CreateDirectory(x)
x x
member this.call args workingDir = member val Arguments = "" with get, set
if not <| IO.File.Exists sh then member val WorkingDirectory = "" with get, set
member this.callScript scriptName args =
this.Arguments <- sprintf "%s %s" (mungePath props.["ProjectDir"] scriptName) args
this.Execute()
// ToolTask overrides
override val ToolName = "sh.exe" with get
override this.GenerateFullPathToTool() = sprintf "%s\\bin\\sh.exe" props.["MsysBasePath"]
override this.GenerateCommandLineCommands() = this.Arguments
override this.GetWorkingDirectory() = this.WorkingDirectory
override this.Execute() =
if this.GenerateFullPathToTool() |> IO.File.Exists |> not then
failwith "sh.exe not found. Make sure the MSYS root is set to a correct location." failwith "sh.exe not found. Make sure the MSYS root is set to a correct location."
let info = new ProcessStartInfo(FileName = sh this.WorkingDirectory <- cwd this.WorkingDirectory
, Arguments = args this.UseCommandProcessor <- false
, WorkingDirectory = cwd workingDir this.StandardOutputImportance <- "High"
, RedirectStandardOutput = true this.EnvironmentVariables <- [|
, UseShellExecute = false) "CC=cl";
"CPP=cl -E";
"CFLAGS=-nologo";
"PATH=" + props.["MsysBasePath"] + "\\bin;" + props.["NativeExecutablePath"];
"INCLUDE=" + props.["AegisubSourceBase"] + "//include;" + props.["IncludePath"];
"LIB=" + props.["AegisubLibraryDir"] + ";" + props.["LibraryPath"];
"PKG_CONFIG_PATH=" + (mungePath props.["ProjectDir"] props.["AegisubLibraryDir"]) + "/pkgconfig"
|]
use p = new Process(StartInfo = info) base.Execute()
ignore(p.Start())
let output = p.StandardOutput.ReadToEnd()
p.WaitForExit()
if p.ExitCode <> 0 then
failwith output
member this.callScript scriptName args workingDir =
this.call (sprintf "%s %s" (mungePath props.["ProjectDir"] scriptName) args) workingDir
type ExecShellScript() = type ExecShellScript() =
inherit Task() inherit Task()
// Task arguments
member val WorkingDirectory = "" with get, set member val WorkingDirectory = "" with get, set
member val Command = "" with get, set member val Command = "" with get, set
member val Script = "" with get, set member val Script = "" with get, set
member val Arguments = "" with get, set member val Arguments = "" with get, set
member private this.realArgs (props : Map<String, String>) =
if this.Script.Length > 0
then sprintf "%s %s" (mungePath props.["ProjectDir"] this.Script) this.Arguments
else sprintf "-c '%s %s'" this.Command this.Arguments
override this.Execute() = override this.Execute() =
try try
let sw = ShellWrapper (propertyMap this.BuildEngine) let props = propertyMap this.BuildEngine
if this.Script.Length > 0 let sw = ShellWrapper(props,
then this.Log.LogMessage("Calling '{0}' {1}", this.Script, this.Arguments); BuildEngine = this.BuildEngine,
sw.callScript this.Script this.Arguments this.WorkingDirectory HostObject = this.HostObject,
else this.Log.LogMessage("Calling '{0}' {1}", this.Command, this.Arguments); Arguments = this.realArgs props,
sw.call (sprintf "-c '%s %s'" this.Command this.Arguments) this.WorkingDirectory WorkingDirectory = this.WorkingDirectory)
true
with Failure(e) -> sw.Execute()
this.Log.LogError(e) with
false | Failure(e) -> this.Log.LogError(e); false
| e -> this.Log.LogErrorFromException(e); false
type MsysPath() = type MsysPath() =
inherit Task() inherit Task()