diff --git a/src/app/FakeLib/CscHelper.fs b/src/app/FakeLib/CscHelper.fs
new file mode 100644
index 00000000000..4ad05b9ad6d
--- /dev/null
+++ b/src/app/FakeLib/CscHelper.fs
@@ -0,0 +1,121 @@
+/// Contains tasks to compile C# source files with CSC.EXE (C# Compiler).
+module Fake.CscHelper
+open System
+
+/// Supported output types
+type CscTarget =
+ | Exe
+ | Winexe
+ | Library
+ | Module
+
+/// Supported platforms
+type CscPlatform =
+ | X86
+ | Itanium
+ | X64
+ | AnyCpu32BitPreferred
+ | AnyCpu
+
+/// Compiler parameters
+type CscParams =
+ { /// Specifies the output file name and path.
+ Output : string
+ /// Specifies the compiled artifact target type.
+ Target : CscTarget
+ /// Specifies the compiled artifact target platform.
+ Platform : CscPlatform
+ /// Specifies assemblies to reference for the compilation.
+ References : string list
+ /// Specifies whether to emit debug information (default is false).
+ Debug : bool
+ /// Specifies other params for the compilation. Freeform strings.
+ OtherParams : string list }
+
+ /// The default parameters to the compiler.
+ static member Default =
+ { Output = ""
+ Target = Exe
+ Platform = AnyCpu
+ References = []
+ Debug = false
+ OtherParams = [] }
+
+let cscExe (srcFiles : string list) (opts : string list) : int =
+ let processResult =
+ ExecProcessAndReturnMessages (fun p ->
+ p.FileName <- if isMono then "mcs" else "csc"
+ p.Arguments <- [
+ opts |> separated " "
+ srcFiles |> separated " "
+ ] |> separated " "
+ ) (TimeSpan.FromMinutes 10.)
+
+ trace <| sprintf "CSC with args:%A" (Array.ofSeq opts)
+
+ processResult.ExitCode
+
+/// Compiles the given C# source files with the specified parameters.
+///
+/// ## Parameters
+///
+/// - `setParams` - Function used to overwrite the default CSC parameters.
+/// - `inputFiles` - The C# input files.
+///
+/// ## Returns
+///
+/// The exit status code of the compile process.
+///
+/// ## Sample
+///
+/// ["file1.cs"; "file2.cs"]
+/// |> csc (fun parameters ->
+/// { parameters with Output = ...
+/// Target = ...
+/// ... })
+let csc (setParams : CscParams -> CscParams) (inputFiles : string list) : int =
+ let inputFiles = inputFiles |> Seq.toList
+ let taskDesc = inputFiles |> separated ", "
+ let cscParams = setParams CscParams.Default
+
+ let output = if cscParams.Output <> "" then [sprintf "/out:%s" cscParams.Output] else []
+ let target =
+ match cscParams.Target with
+ | Exe -> [ "/target:exe" ]
+ | Winexe -> [ "/target:winexe" ]
+ | Library -> [ "/target:library" ]
+ | Module -> [ "/target:module" ]
+ let platform =
+ match cscParams.Platform with
+ | X86 -> [ "/platform:x86" ]
+ | Itanium -> [ "/platform:itanium" ]
+ | X64 -> [ "/platform:x64" ]
+ | AnyCpu32BitPreferred -> [ "/platform:anycpu32bitpreferred" ]
+ | AnyCpu -> [ "/platform:anycpu" ]
+ let references =
+ cscParams.References
+ |> List.map (fun r -> sprintf "/reference:%s" r)
+ let debug = if cscParams.Debug then [ "/debug" ] else []
+ let argList =
+ output @ target @ platform @ references @ debug @ cscParams.OtherParams
+ traceStartTask "Csc " taskDesc
+ let res = cscExe inputFiles argList
+ traceEndTask "Csc " taskDesc
+ res
+
+/// Compiles one or more C# source files with the specified parameters.
+/// ## Parameters
+///
+/// - `setParams` - Function used to overwrite the default CSC parameters.
+/// - `inputFiles` - The C# input files.
+///
+/// ## Sample
+///
+/// ["file1.cs"; "file2.cs"]
+/// |> Csc (fun parameters ->
+/// { parameters with Output = ...
+/// Target = ...
+/// ... })
+let Csc (setParams : CscParams -> CscParams) (inputFiles : string list) : unit =
+ let res = csc setParams inputFiles
+ if res <> 0 then raise <| BuildException("Csc: compile failed with exit code", [ string res ])
diff --git a/src/app/FakeLib/FakeLib.fsproj b/src/app/FakeLib/FakeLib.fsproj
index 09398ec930a..af23dd5c6a4 100644
--- a/src/app/FakeLib/FakeLib.fsproj
+++ b/src/app/FakeLib/FakeLib.fsproj
@@ -142,6 +142,7 @@
+
@@ -637,4 +638,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/Test.FAKECore/CscSpecs.cs b/src/test/Test.FAKECore/CscSpecs.cs
new file mode 100644
index 00000000000..8ba1dc83d4f
--- /dev/null
+++ b/src/test/Test.FAKECore/CscSpecs.cs
@@ -0,0 +1,64 @@
+using System;
+using System.IO;
+using System.Linq;
+using Fake;
+using Machine.Specifications;
+using Microsoft.FSharp.Core;
+using Microsoft.FSharp.Collections;
+
+namespace Test.FAKECore
+{
+ public class compile_csfiles_to_dll
+ {
+ static string tempDir, outFile, csFile1, csFile2;
+ static FSharpFunc cscParams;
+
+ Establish context = () =>
+ {
+ tempDir = Path.GetTempPath();
+ csFile1 = Path.Combine(tempDir, "test1.cs");
+ csFile2 = Path.Combine(tempDir, "test2.cs");
+
+ File.WriteAllText(csFile1, @"
+using System;
+
+namespace Test {
+ public class Class1 {
+ public string Hello(string what) {
+ return String.Format(""Hello {0}"", what);
+ }
+ }
+}");
+
+ File.WriteAllText(csFile2, @"
+using System;
+
+namespace Test {
+ public class Class2 : Class1 {
+ public void HelloWorld() {
+ Console.WriteLine(this.Hello(""World""));
+ }
+ }
+}");
+
+ outFile = Path.Combine(tempDir, "test.dll");
+ try { File.Delete(outFile); } catch (FileNotFoundException) {}
+
+ cscParams = FSharpFuncUtil.ToFSharpFunc(
+ p => new CscHelper.CscParams(
+ output: outFile,
+ target: CscHelper.CscTarget.Library,
+ platform: p.Platform,
+ references: p.References,
+ debug: p.Debug,
+ otherParams: p.OtherParams
+ )
+ );
+ };
+
+ Because of = () => CscHelper.Csc(cscParams, ListModule.OfSeq(new [] { csFile1, csFile2 }));
+
+ It should_compile_to_dll = () => File.Exists(outFile).ShouldBeTrue();
+ }
+}
+
diff --git a/src/test/Test.FAKECore/Test.FAKECore.csproj b/src/test/Test.FAKECore/Test.FAKECore.csproj
index 4f9d8da6164..c0388ca78c2 100644
--- a/src/test/Test.FAKECore/Test.FAKECore.csproj
+++ b/src/test/Test.FAKECore/Test.FAKECore.csproj
@@ -119,6 +119,7 @@
+
@@ -715,4 +716,4 @@
-
\ No newline at end of file
+