diff --git a/build-web-bundles.fsx b/build-web-bundles.fsx index 6a94ecba66a..ba842f33bb6 100644 --- a/build-web-bundles.fsx +++ b/build-web-bundles.fsx @@ -57,4 +57,4 @@ Target "Default" DoNothing ==> "Default" // start build -RunParameterTargetOrDefault "target" "Default" +RunTargetOrDefault "Default" diff --git a/build.fsx b/build.fsx index ab0b2651fa6..73d6d0d5b1f 100644 --- a/build.fsx +++ b/build.fsx @@ -229,7 +229,7 @@ let dotnetAssemblyInfos = "Fake.Core.ReleaseNotes", "Parsing ReleaseNotes" "Fake.Core.SemVer", "Parsing and working with SemVer" "Fake.Core.String", "Core String manipulations" - "Fake.Core.Targets", "Defining and running Targets" + "Fake.Core.Target", "Defining and running Targets" "Fake.Core.Tasks", "Repeating and managing Tasks" "Fake.Core.Tracing", "Core Logging functionality" "Fake.Core.Xml", "Core Xml functionality" diff --git a/help/markdown/contributing.md b/help/markdown/contributing.md index b85b544815d..59341c565c5 100644 --- a/help/markdown/contributing.md +++ b/help/markdown/contributing.md @@ -104,7 +104,7 @@ to automatically deploy a preconfigured virtual machine. See the [Vagrant docs]( ## API-Design -We [learned from our mistakes](fake-fake5-learn-more.html), so we use the following guidelines: +We [learned from our mistakes](fake-fake5-learn-more.html), so we use the following guidelines, **please read them very carefully** (ask if you don't understand any rule): - AutoOpen is no longer used - we replace `` functions with `.` @@ -113,7 +113,11 @@ We [learned from our mistakes](fake-fake5-learn-more.html), so we use the follow - For compatibility reasons (migration from legacy). We assume the user doesn't open the global `Fake` namespace. -> This means we don't add anything in there in the new API. - - Old APIs are marked as Obsolete with a link (hint) to the new API location. + - Old APIs are marked as Obsolete with a link (hint) to the new API location. We use codes to make explicit + - FAKE0001 for moving part from one Module to another + - FAKE0002 for removed API we don't know who is using it and how => please open an issue if you use it + - FAKE0003 for API that is no more accessible (basically became internal) => please open an issue if you use it + - FAKE0004 for API not yet migrated, waiting for your contribution - Operators are opened seperatly with a separate `Operators` module - We avoid the `Helpers` suffix (because we now expect users to write `.`) diff --git a/help/markdown/core-targets.md b/help/markdown/core-targets.md index c2aae35829d..6644e1416f5 100644 --- a/help/markdown/core-targets.md +++ b/help/markdown/core-targets.md @@ -53,27 +53,27 @@ Now we have the following options: ## Final targets Final targets can be used for TearDown functionality. -These targets will be executed even if the build fails but have to be activated via ActivateFinalTarget(). +These targets will be executed even if the build fails but have to be activated via ActivateFinal(). - FinalTarget "CloseSomePrograms" (fun _ -> + Target.CreateFinal "CloseSomePrograms" (fun _ -> // close stuff and release resources ) - // Activate FinalTarget somewhere during build - ActivateFinalTarget "CloseSomePrograms" + // Activate Final target somewhere during build + Target.ActivateFinal "CloseSomePrograms" ## Build failure targets Build failure targets can be used to execute tasks after a build failure. -These targets will be executed only after a build failure but have to be activated via ActivateBuildFailureTarget(). +These targets will be executed only after a build failure but have to be activated via ActivateBuildFailure(). - BuildFailureTarget "ReportErrorViaMail" (fun _ -> + CreateBuildFailure "ReportErrorViaMail" (fun _ -> // send mail about the failure ) - // Activate BuildFailureTarget somewhere during build - ActivateBuildFailureTarget "ReportErrorViaMail" + // Activate Build Failure Target somewhere during build + ActivateBuildFailure "ReportErrorViaMail" ## Visualising target dependencies @@ -87,7 +87,7 @@ the dependency graph to the standard output *instead* of building anything. This the build script contains a call like this: ``` -RunTargetOrDefault "Default" +Target.RunOrDefault "Default" ``` ### Example @@ -113,7 +113,7 @@ resulting in an image like this: ![graph](pics/specifictargets/graph.png "Dependency graph") -# Using FAKE's parallel option +## Using FAKE's parallel option Since multithreading is beneficial (especially for large projects) FAKE allows to specify the number of threads used for traversing the dependency tree. @@ -121,7 +121,7 @@ This option of course only affects independent targets whereas dependent targets still be exectued in order. -## Setting the number of threads +### Setting the number of threads The number of threads used can be set using the environment variable ``parallel-jobs``. This can be achieved in various ways where the easiest one is to use FAKE's built-in support for setting environment variables: diff --git a/help/markdown/fake-commandline.md b/help/markdown/fake-commandline.md index 762869b7b2b..ac41ebdba37 100644 --- a/help/markdown/fake-commandline.md +++ b/help/markdown/fake-commandline.md @@ -96,24 +96,23 @@ For this short sample we assume you have the latest version of FAKE installed an source https://nuget.org/api/v2 source ../../../nuget/dotnetcore - nuget Fake.Core.Targets prerelease + nuget Fake.Core.Target prerelease nuget FSharp.Core prerelease -- Fake Dependencies -- *) open Fake.Core - open Fake.Core.Targets - Target "Clean" (fun () -> trace " --- Cleaning stuff --- ") + Target.Create "Clean" (fun () -> trace " --- Cleaning stuff --- ") - Target "Build" (fun () -> trace " --- Building the app --- ") + Target.Create "Build" (fun () -> trace " --- Building the app --- ") - Target "Deploy" (fun () -> trace " --- Deploying app --- ") + Target.Create "Deploy" (fun () -> trace " --- Deploying app --- ") "Clean" ==> "Build" ==> "Deploy" - RunTargetOrDefault "Deploy" + Target.RunOrDefault "Deploy" If you are on windows then create this small redirect script: diff --git a/help/markdown/fake-fake5-custom-modules.md b/help/markdown/fake-fake5-custom-modules.md index c253fe13785..12d802fe9a0 100644 --- a/help/markdown/fake-fake5-custom-modules.md +++ b/help/markdown/fake-fake5-custom-modules.md @@ -48,7 +48,7 @@ One example would be: (* -- Fake Dependencies paket-inline source https://nuget.org/api/v2 - nuget Fake.Core.Targets prerelease + nuget Fake.Core.Target prerelease nuget MyTaskNuGetPackage -- Fake Dependencies -- *) #load "./.fake/build.fsx/intellisense.fsx" diff --git a/help/markdown/fake-fake5-modules.md b/help/markdown/fake-fake5-modules.md index d764fb824f0..76b8c97d1e9 100644 --- a/help/markdown/fake-fake5-modules.md +++ b/help/markdown/fake-fake5-modules.md @@ -15,7 +15,7 @@ Create a new file `paket.dependencies` and add the following content group NetcoreBuild source https://nuget.org/api/v2 - nuget Fake.Core.Targets prerelease + nuget Fake.Core.Target prerelease ``` Now you can directly use `open Fake.Core` and use the [Target module](core-targets.html). @@ -86,7 +86,7 @@ To write your build dependencies in-line you can put the following at the top of (* -- Fake Dependencies paket-inline source https://nuget.org/api/v2 - nuget Fake.Core.Targets prerelease + nuget Fake.Core.Target prerelease -- Fake Dependencies -- *) #load "./.fake/build.fsx/intellisense.fsx" diff --git a/help/markdown/fake-migrate-to-fake-5.md b/help/markdown/fake-migrate-to-fake-5.md index c80109accbe..9a8d9ffd86e 100644 --- a/help/markdown/fake-migrate-to-fake-5.md +++ b/help/markdown/fake-migrate-to-fake-5.md @@ -4,7 +4,7 @@ In this tutorial you will learn how to migrate your existing build scripts to the new FAKE 5 dotnet-core version. -First we want you to know that there are two version of FAKE 5. One is just an update to the regular FAKE 4, but contains the new netcore API. +First we want you to know that there are two versions of FAKE 5. One is just an update to the regular FAKE 4, but also contains the new API. We will call this the "legacy FAKE version" it is just like the FAKE you are already used to. The second version is the "new/dotnetcore/standalone FAKE 5" or just "FAKE 5". This "new" version has several advantages: @@ -13,30 +13,35 @@ This "new" version has several advantages: * Paket bootstrapper / build.cmd and build.sh are no longer required (you can still use them) * This will be the only Version available in FAKE 6 -Therefore you have the FAKE 5 timeframe to update your build scripts to the new version. +Therefore you have the FAKE 5 timeframe to update your build scripts to the new version. If you have any issues in the migration process, please see [how to fill issues or discuss about your issues](/contributing.html) (don't be shy about contributing ;)). ## Migration Guide -Upgrading to FAKE 5 is a multi step process and has various manual steps in between. Here are the steps: +Upgrading to FAKE 5 is a multi step process and has various manual steps in between. **If you do these steps out of order it will be a lot harder for you to migrate the script successfully**. Here are the steps: -- Regular update to FAKE 5. This should not be breaking. If it breaks you please open an issue. -- Fix all the (obsolete) warnings in your build-script to use the new API (see the 'Use the new FAKE-API' section). +- Update to legacy FAKE 5. This should not be breaking. If it breaks you please open an issue. + + - With Paket: add `prerelease` after `nuget FAKE` in paket.dependencies file then `.paket/paket.exe update FAKE`, check that paket.lock references FAKE version 5 + +- Fix all the (obsolete) warnings in your build-script to use the new API (see the [Use the new FAKE-API](#Use-the-new-FAKE-API) section). This should still not break your build. If things break here or you have difficulties after reading the 'Use the new FAKE-API' section please open an issue. + - Becareful if you update only some warning, it could break. For example, if you use `Target.Create`, but continue to use old operators definition, you will probably experiment some errors like "Target [...] is not defined". - Change to the new version of FAKE 5. - This is for example done by installing FAKE as dependency on your build infrastructure. There are a variety of installing options available. (TODO: Link to 'installing FAKE' section) - Add a FAKE header (TODO: add Link), and tell FAKE which features/packages you want to use in the dependencies file or in-line. - See the 'Adding FAKE dependencies' section below. - - Run the build with the new version of FAKE :). You might want to read the 'CLI migration' section + See the [Adding FAKE dependencies](#Adding-FAKE-dependencies) section below. + - Run the build with the new version of FAKE :). You might want to read the [CLI migration](#CLI-Migration) section If things break in the last step please let us know as well. -If you do these steps out of order it will be a lot harder for you to migrate the script successfully. - ### Use the new FAKE-API +After upgrading to legacy FAKE 5 the warnings should tell you exactly what you do. If there is stuff missing or a warning message should be improved let us know. +Some warnings indicate how we want the new FAKE version to be used. + The most important part to know is that basically every feature/function changes its location and sometimes they were even grouped in different modules as the old API was growing several years now and we never could do breaking changes. @@ -49,14 +54,6 @@ as the old API was growing several years now and we never could do breaking chan So please try it out and if stuff breaks let us know :). The good thing is you can always "lock" the versions of the FAKE modules until you are ready to upgrade. -After upgrading to legacy FAKE 5 the warnings should tell you exactly what you do. If there is stuff missing or a warning message should be improved let us know. -Some warnings indicate how we want the new FAKE version to be used. - -The "open Fake" and AutoOpen modules are completely obsolete. -We urge you to finish your API-Migration (after fixing all warnings) by removing "open Fake". -This removes a lot of automatically opened stuff and if your build fails you ar probably stuff where we forgot to add the obsolete warning (let us know) or that -stuff you are using was not migrated yet (let us know or send a PR, TODO: Add link to guideline). - In this new work you should write "Module.Method a b" instead of "MethodModule a b". Which means in the old world we had lots of methods like "ReadFile argument" (the module probably even opened via `[]`), which is considered bad style now. In the new world we would open the `Fake.IO.FileSystem` namespace to indicate that we are using the file-system. @@ -64,6 +61,10 @@ At the same time we would write `File.Read argument`, which is only a bit longer > If you still find places where we use the "bad" style in the new API, let us know (open an issue). +The "open Fake" and AutoOpen modules are completely obsolete. +We urge you to finish your API-Migration (after fixing all warnings) by removing "open Fake". +This removes a lot of automatically opened stuff and if your build fails you have probably stuff where we forgot to add the obsolete warning (let us know) or that +stuff you are using was not migrated yet (let us know or send a PR, TODO: Add link to guideline). ### Add FAKE dependencies diff --git a/integrationtests/core-reference-fake-core-targets/before/reference_fake-targets.fsx b/integrationtests/core-reference-fake-core-targets/before/reference_fake-targets.fsx index 5690cabd865..edfb195efbd 100644 --- a/integrationtests/core-reference-fake-core-targets/before/reference_fake-targets.fsx +++ b/integrationtests/core-reference-fake-core-targets/before/reference_fake-targets.fsx @@ -3,7 +3,7 @@ storage: none source https://nuget.org/api/v2 source ../../../nuget/dotnetcore -nuget Fake.Core.Targets prerelease +nuget Fake.Core.Target prerelease nuget FSharp.Core prerelease -- Fake Dependencies -- *) diff --git a/paket.dependencies b/paket.dependencies index b0f11588eb5..83bf5ffa0f6 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -77,7 +77,7 @@ group NetcoreBuild nuget FSharp.Core ~> 4.1.0 nuget System.AppContext prerelease nuget Paket.Core prerelease - nuget Fake.Core.Targets prerelease + nuget Fake.Core.Target prerelease nuget Fake.Core.Globbing prerelease nuget Fake.Core.SemVer prerelease nuget Fake.IO.FileSystem prerelease diff --git a/src/Fake-netcore.sln b/src/Fake-netcore.sln index d3f403fdfb5..fc3b8727a99 100644 --- a/src/Fake-netcore.sln +++ b/src/Fake-netcore.sln @@ -23,7 +23,7 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.Core.String", "app\Fak EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.Core.Tracing", "app\Fake.Core.Tracing\Fake.Core.Tracing.fsproj", "{9430365D-C956-4290-A006-A87F9083DC4B}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.Core.Targets", "app\Fake.Core.Targets\Fake.Core.Targets.fsproj", "{0C28F2FB-2B12-4893-AAA4-2C2548926847}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.Core.Target", "app\Fake.Core.Target\Fake.Core.Target.fsproj", "{0C28F2FB-2B12-4893-AAA4-2C2548926847}" EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.Core.Tasks", "app\Fake.Core.Tasks\Fake.Core.Tasks.fsproj", "{83860B89-4A95-49A5-B4D6-B8F3345498E9}" EndProject diff --git a/src/app/Fake.Core.Targets/AssemblyInfo.fs b/src/app/Fake.Core.Target/AssemblyInfo.fs similarity index 100% rename from src/app/Fake.Core.Targets/AssemblyInfo.fs rename to src/app/Fake.Core.Target/AssemblyInfo.fs diff --git a/src/app/Fake.Core.Targets/Fake.Core.Targets.fsproj b/src/app/Fake.Core.Target/Fake.Core.Target.fsproj similarity index 97% rename from src/app/Fake.Core.Targets/Fake.Core.Targets.fsproj rename to src/app/Fake.Core.Target/Fake.Core.Target.fsproj index a810faaca76..3d4f2742549 100644 --- a/src/app/Fake.Core.Targets/Fake.Core.Targets.fsproj +++ b/src/app/Fake.Core.Target/Fake.Core.Target.fsproj @@ -5,7 +5,7 @@ netstandard1.6 pdbonly true - Fake.Core.Targets + Fake.Core.Target Library $(PackageTargetFallback);portable-net45+win8;dnxcore50 diff --git a/src/app/Fake.Core.Targets/Target.fs b/src/app/Fake.Core.Target/Target.fs similarity index 94% rename from src/app/Fake.Core.Targets/Target.fs rename to src/app/Fake.Core.Target/Target.fs index f6ddebe9f4c..8d53de3c9cb 100644 --- a/src/app/Fake.Core.Targets/Target.fs +++ b/src/app/Fake.Core.Target/Target.fs @@ -301,8 +301,8 @@ module Target = | exn -> targetError name exn) - /// Prints all targets. - let Print() = + /// List all targets available. + let ListAvailable() = Trace.log "The following targets are available:" for t in getTargetDict().Values do Trace.logfn " %s%s" t.Name (match t.Description with Some s -> sprintf " - %s" s | _ -> "") @@ -348,7 +348,7 @@ module Target = /// The target for which the dependencies should be printed. let PrintDependencyGraph verbose target = match getTargetDict().TryGetValue (target) with - | false,_ -> Print() + | false,_ -> ListAvailable() | true,target -> Trace.logfn "%sDependencyGraph for Target %s:" (if verbose then String.Empty else "Shortened ") target.Name @@ -407,14 +407,6 @@ module Target = /// [omit] let internal isListMode = Environment.hasEnvironVar "list" - /// Prints all available targets. - let internal listTargets() = - Trace.tracefn "Available targets:" - getTargetDict().Values - |> Seq.iter (fun target -> - Trace.tracefn " - %s %s" target.Name (match target.Description with Some d -> " - " + d | _ -> "") - Trace.tracefn " Depends on: %A" target.Dependencies) - // Instead of the target can be used the list dependencies graph parameter. let internal doesTargetMeanListTargets target = target = "--listTargets" || target = "-lt" @@ -480,7 +472,7 @@ module Target = /// Runs a target and its dependencies. let internal run targetName = - if doesTargetMeanListTargets targetName then listTargets() else + if doesTargetMeanListTargets targetName then ListAvailable() else match getLastDescription() with | Some d -> failwithf "You set a task description (%A) but didn't specify a task. Make sure to set the Description above the Target." d | None -> () @@ -543,39 +535,33 @@ module Target = | [] -> () | errors -> failwithf "A target failed: %A" errors - /// Registers a BuildFailureTarget (not activated). - let BuildFailureTarget name body = + /// Creates a target in case of build failure (not activated). + let CreateBuildFailure name body = Create name body getBuildFailureTargets().Add(name,false) - /// Activates the BuildFailureTarget. - let ActivateBuildFailureTarget name = + /// Activates the build failure target. + let ActivateBuildFailure name = let t = Get name // test if target is defined getBuildFailureTargets().[name] <- true - /// Registers a final target (not activated). - let FinalTarget name body = + /// Creates a final target (not activated). + let CreateFinal name body = Create name body getFinalTargets().Add(name,false) - /// Activates the FinalTarget. - let ActivateFinalTarget name = + /// Activates the final target. + let ActivateFinal name = let t = Get name // test if target is defined getFinalTargets().[name] <- true - /// Runs a Target and its dependencies - let RunTarget targetName = run targetName - - // Runs the target given by the build script parameter or the given default target - //let RunParameterTargetOrDefault parameterName defaultTarget = Environment.environVarOrDefault parameterName defaultTarget |> Run + /// Runs a target and its dependencies + let Run targetName = run targetName /// Runs the target given by the target parameter or the given default target - let RunOrDefault defaultTarget = Environment.environVarOrDefault "target" defaultTarget |> RunTarget + let RunOrDefault defaultTarget = Environment.environVarOrDefault "target" defaultTarget |> Run /// Runs the target given by the target parameter or lists the available targets let RunOrList() = - if Environment.hasEnvironVar "target" then Environment.environVar "target" |> RunTarget - else listTargets() - - /// Runs the target given by the target parameter - let Run() = Environment.environVarOrDefault "target" "" |> RunTarget \ No newline at end of file + if Environment.hasEnvironVar "target" then Environment.environVar "target" |> Run + else ListAvailable() \ No newline at end of file diff --git a/src/app/Fake.Core.Targets/TargetOperators.fs b/src/app/Fake.Core.Target/TargetOperators.fs similarity index 100% rename from src/app/Fake.Core.Targets/TargetOperators.fs rename to src/app/Fake.Core.Target/TargetOperators.fs diff --git a/src/app/Fake.Core.Targets/paket.references b/src/app/Fake.Core.Target/paket.references similarity index 100% rename from src/app/Fake.Core.Targets/paket.references rename to src/app/Fake.Core.Target/paket.references diff --git a/src/app/FakeLib/AdditionalSyntax.fs b/src/app/FakeLib/AdditionalSyntax.fs index d146aadd814..2c4c6698825 100644 --- a/src/app/FakeLib/AdditionalSyntax.fs +++ b/src/app/FakeLib/AdditionalSyntax.fs @@ -5,47 +5,59 @@ module Fake.AdditionalSyntax open System.Collections.Generic /// Allows to use Tokens instead of strings +[] let (?) f s = f s /// Allows to use Tokens instead of strings for TargetNames +[] let (?<-) f str action = f str action /// Allows to use For? syntax for Dependencies +[] let For x y = x <== y /// Converts a dependency into a list +[] let Dependency x = [x] /// Appends the dependency to the list of dependencies +[] let And x y = y @ [x] /// Runs a Target and its dependencies +[] let Run targetName = run targetName /// Runs the target given by the build script parameter or the given default target +[] let RunParameterTargetOrDefault parameterName defaultTarget = getBuildParamOrDefault parameterName defaultTarget |> Run /// Runs the target given by the target parameter or the given default target +[] let RunTargetOrDefault defaultTarget = getBuildParamOrDefault "target" defaultTarget |> Run /// Runs the target given by the target parameter or lists the available targets +[] let RunTargetOrListTargets() = if hasBuildParam "target" then getBuildParam "target" |> Run else listTargets() /// Runs the target given by the target parameter +[] let RunTarget() = getBuildParam "target" |> Run /// Stores which targets are on the same level let private sameLevels = new Dictionary<_,_>() /// Specifies that two targets are on the same level of execution +[] let targetsAreOnSameLevel x y = match sameLevels.TryGetValue y with | true, z -> () | _ -> sameLevels.[y] <- x /// Specifies that two targets have the same dependencies +[] let rec addDependenciesOnSameLevel target dependency = match sameLevels.TryGetValue dependency with | true, x -> @@ -54,6 +66,7 @@ let rec addDependenciesOnSameLevel target dependency = | _ -> () /// Specifies that two targets have the same dependencies +[] let rec addSoftDependenciesOnSameLevel target dependency = match sameLevels.TryGetValue dependency with | true, x -> @@ -63,6 +76,7 @@ let rec addSoftDependenciesOnSameLevel target dependency = /// Defines a dependency - y is dependent on x +[)")>] let inline (==>) x y = addDependenciesOnSameLevel y x Dependencies y [x] @@ -70,16 +84,19 @@ let inline (==>) x y = /// Defines a soft dependency. x must run before y, if it is present, but y does not require x to be run. +[)")>] let inline (?=>) x y = addSoftDependenciesOnSameLevel y x SoftDependencies y [x] y /// Defines a soft dependency. x must run before y, if it is present, but y does not require x to be run. +[] let inline (<=?) y x = x ?=> y /// Defines that x and y are not dependent on each other but y is dependent on all dependencies of x. +[)")>] let inline (<=>) x y = let target_x = getTarget x Dependencies y target_x.Dependencies @@ -87,4 +104,5 @@ let inline (<=>) x y = y /// Defines a conditional dependency - y is dependent on x if the condition is true +[)")>] let inline (=?>) x (y,condition) = if condition then x ==> y else x diff --git a/src/app/FakeLib/FakeLib.fsproj b/src/app/FakeLib/FakeLib.fsproj index 5ab827a9aa8..5d82da2e303 100644 --- a/src/app/FakeLib/FakeLib.fsproj +++ b/src/app/FakeLib/FakeLib.fsproj @@ -100,11 +100,11 @@ Fake.Core.Tracing/Trace.fs - - Fake.Core.Targets/Target.fs + + Fake.Core.Target/Target.fs - - Fake.Core.Targets/TargetOperators.fs + + Fake.Core.Target/TargetOperators.fs Fake.Core.Globbing/Globbing.fs diff --git a/src/app/FakeLib/TargetHelper.fs b/src/app/FakeLib/TargetHelper.fs index 0862d55d053..f834b992475 100644 --- a/src/app/FakeLib/TargetHelper.fs +++ b/src/app/FakeLib/TargetHelper.fs @@ -1,6 +1,6 @@ [] /// Contains infrastructure code and helper functions for FAKE's target feature. -[] +[] module Fake.TargetHelper #nowarn "44" @@ -10,11 +10,11 @@ open System.Collections.Generic open System.Linq /// [omit] -[] +[] type TargetDescription = string /// [omit] -[] +[] type 'a TargetTemplate = { Name: string; Dependencies: string list; @@ -23,7 +23,7 @@ type 'a TargetTemplate = Function : 'a -> unit} /// A Target can be run during the build -[] +[] type Target = unit TargetTemplate type private DependencyType = @@ -37,16 +37,16 @@ type private DependencyLevel = } /// [omit] -[] +[] let mutable PrintStackTraceOnError = false /// [omit] -[] +[] let mutable LastDescription = null /// Sets the Description for the next target. /// [omit] -[] +[] let Description text = if LastDescription <> null then failwithf "You can't set the description for a target twice. There is already a description: %A" LastDescription @@ -54,29 +54,29 @@ let Description text = /// TargetDictionary /// [omit] -[] +[] let TargetDict = new Dictionary<_,_>(StringComparer.OrdinalIgnoreCase) /// Final Targets - stores final targets and if they are activated. -[] +[] let FinalTargets = new Dictionary<_,_>(StringComparer.OrdinalIgnoreCase) /// BuildFailureTargets - stores build failure targets and if they are activated. -[] +[] let BuildFailureTargets = new Dictionary<_,_>(StringComparer.OrdinalIgnoreCase) /// The executed targets. -[] +[] let ExecutedTargets = new HashSet<_>(StringComparer.OrdinalIgnoreCase) /// The executed target time. /// [omit] -[] +[] let ExecutedTargetTimes = new List<_>() /// Resets the state so that a deployment can be invoked multiple times /// [omit] -[] +[] let reset() = TargetDict.Clear() ExecutedTargets.Clear() @@ -84,17 +84,17 @@ let reset() = ExecutedTargetTimes.Clear() FinalTargets.Clear() -[] +[] let mutable CurrentTargetOrder = [] -[] +[] let mutable CurrentTarget = "" /// Returns a list with all target names. -[] +[] let getAllTargetsNames() = TargetDict |> Seq.map (fun t -> t.Key) |> Seq.toList /// Gets a target with the given name from the target dictionary. -[] +[] let getTarget name = match TargetDict.TryGetValue (name) with | true, target -> target @@ -105,7 +105,7 @@ let getTarget name = failwithf "Target \"%s\" is not defined." name /// Returns the DependencyString for the given target. -[] +[] let dependencyString target = if target.Dependencies.IsEmpty then String.Empty else target.Dependencies @@ -114,7 +114,7 @@ let dependencyString target = |> sprintf "(==> %s)" /// Returns the soft DependencyString for the given target. -[] +[] let softDependencyString target = if target.SoftDependencies.IsEmpty then String.Empty else target.SoftDependencies @@ -123,12 +123,12 @@ let softDependencyString target = |> sprintf "(?=> %s)" /// Do nothing - fun () -> () - Can be used to define empty targets. -[] +[] let DoNothing = (fun () -> ()) /// Checks whether the dependency (soft or normal) can be added. /// [omit] -[] +[] let checkIfDependencyCanBeAddedCore fGetDependencies targetName dependentTargetName = let target = getTarget targetName let dependentTarget = getTarget dependentTargetName @@ -145,19 +145,19 @@ let checkIfDependencyCanBeAddedCore fGetDependencies targetName dependentTargetN /// Checks whether the dependency can be added. /// [omit] -[] +[] let checkIfDependencyCanBeAdded targetName dependentTargetName = checkIfDependencyCanBeAddedCore (fun target -> target.Dependencies) targetName dependentTargetName /// Checks whether the soft dependency can be added. /// [omit] -[] +[] let checkIfSoftDependencyCanBeAdded targetName dependentTargetName = checkIfDependencyCanBeAddedCore (fun target -> target.SoftDependencies) targetName dependentTargetName /// Adds the dependency to the front of the list of dependencies. /// [omit] -[] +[] let dependencyAtFront targetName dependentTargetName = let target,dependentTarget = checkIfDependencyCanBeAdded targetName dependentTargetName @@ -165,7 +165,7 @@ let dependencyAtFront targetName dependentTargetName = /// Appends the dependency to the list of dependencies. /// [omit] -[] +[] let dependencyAtEnd targetName dependentTargetName = let target,dependentTarget = checkIfDependencyCanBeAdded targetName dependentTargetName @@ -174,7 +174,7 @@ let dependencyAtEnd targetName dependentTargetName = /// Appends the dependency to the list of soft dependencies. /// [omit] -[] +[] let softDependencyAtEnd targetName dependentTargetName = let target,dependentTarget = checkIfDependencyCanBeAdded targetName dependentTargetName @@ -182,26 +182,26 @@ let softDependencyAtEnd targetName dependentTargetName = /// Adds the dependency to the list of dependencies. /// [omit] -[] +[] let dependency targetName dependentTargetName = dependencyAtEnd targetName dependentTargetName /// Adds the dependency to the list of soft dependencies. /// [omit] -[] +[] let softDependency targetName dependentTargetName = softDependencyAtEnd targetName dependentTargetName /// Adds the dependencies to the list of dependencies. /// [omit] -[] +[] let Dependencies targetName dependentTargetNames = dependentTargetNames |> List.iter (dependency targetName) /// Adds the dependencies to the list of soft dependencies. /// [omit] -[] +[] let SoftDependencies targetName dependentTargetNames = dependentTargetNames |> List.iter (softDependency targetName) /// Backwards dependencies operator - x is dependent on ys. -[] +[] let inline (<==) x ys = Dependencies x ys /// Set a dependency for all given targets. @@ -228,7 +228,7 @@ let AllTargetsDependOn target = /// Creates a target from template. /// [omit] -[] +[] let targetFromTemplate template name parameters = match TargetDict.ContainsKey name with | true -> @@ -284,7 +284,8 @@ let targetFromTemplate template name parameters = /// // hook targets to normal build pipeline /// "T1" ==> "T2" ==> "Test" /// -[] + +[] let TargetTemplateWithDependencies dependencies body name parameters = let template = { Name = String.Empty @@ -294,19 +295,19 @@ let TargetTemplateWithDependencies dependencies body name parameters = Function = body } targetFromTemplate template name parameters -[] +[] let TargetTemplateWithDependecies dependencies = TargetTemplateWithDependencies dependencies /// Creates a TargetTemplate. -[] +[] let TargetTemplate body = TargetTemplateWithDependencies [] body /// Creates a Target. -[] +[] let Target name body = TargetTemplate body name () /// Represents build errors -[] +[] type BuildError = { Target : string Message : string } @@ -314,11 +315,11 @@ type BuildError = { let mutable private errors = [] /// Get Errors - Returns the errors that occured during execution -[] +[] let GetErrors() = errors /// [omit] -[] +[] let targetError targetName (exn:System.Exception) = closeAllOpenTags() errors <- @@ -344,7 +345,7 @@ let targetError targetName (exn:System.Exception) = if not isFailedTestsException then sendTeamCityError <| error exn -[] +[] let addExecutedTarget target time = lock ExecutedTargets (fun () -> ExecutedTargets.Add (target) |> ignore @@ -353,7 +354,7 @@ let addExecutedTarget target time = /// Runs all activated final targets (in alphabetically order). /// [omit] -[] +[] let runFinalTargets() = FinalTargets |> Seq.filter (fun kv -> kv.Value) // only if activated @@ -370,7 +371,7 @@ let runFinalTargets() = /// Runs all build failure targets. /// [omit] -[] +[] let runBuildFailureTargets() = BuildFailureTargets |> Seq.filter (fun kv -> kv.Value) // only if activated @@ -387,7 +388,7 @@ let runBuildFailureTargets() = /// Prints all targets. -[] +[] let PrintTargets() = let sb = StringBuilder() let appendfn fmt = Printf.ksprintf (sb.AppendLine >> ignore) fmt @@ -438,7 +439,7 @@ let private visitDependencies fVisit targetName = /// Writes a dependency graph. /// Whether to print verbose output or not. /// The target for which the dependencies should be printed. -[] +[] let PrintDependencyGraph verbose target = match TargetDict.TryGetValue (target) with | false,_ -> PrintTargets() @@ -461,7 +462,7 @@ let PrintDependencyGraph verbose target = sb.Length <- sb.Length - Environment.NewLine.Length log <| sb.ToString() -[] +[] let PrintRunningOrder() = let sb = StringBuilder() let appendfn fmt = Printf.ksprintf (sb.AppendLine >> ignore) fmt @@ -476,7 +477,7 @@ let PrintRunningOrder() = log <| sb.ToString() /// Writes a dependency graph of all targets in the DOT format. -[] +[] let PrintDotDependencyGraph () = let sb = StringBuilder() let appendfn fmt = Printf.ksprintf (sb.AppendLine >> ignore) fmt @@ -496,7 +497,7 @@ let PrintDotDependencyGraph () = log <| sb.ToString() /// Writes a summary of errors reported during build. -[] +[] let WriteErrors () = traceLine() errors @@ -505,7 +506,7 @@ let WriteErrors () = /// Writes a build time report. /// The total runtime. -[] +[] let WriteTaskTimeSummary total = traceHeader "Build Time Report" @@ -555,11 +556,11 @@ module ExitCode = let private changeExitCodeIfErrorOccured() = if errors <> [] then Environment.ExitCode <- ExitCode.Value; ExitCode.exitCode := ExitCode.Value /// [omit] -[] +[] let isListMode = hasBuildParam "list" -/// Prints all available targets. -[] +/// List all available targets. +[] let listTargets() = tracefn "Available targets:" TargetDict.Values @@ -568,7 +569,7 @@ let listTargets() = tracefn " Depends on: %A" target.Dependencies) // Instead of the target can be used the list dependencies graph parameter. -[] +[] let doesTargetMeanListTargets target = target = "--listTargets" || target = "-lt" /// @@ -578,7 +579,7 @@ let doesTargetMeanListTargets target = target = "--listTargets" || target = "-l let private doesTargetMeanPrintDotGraph target = target = "--dotGraph" || target = "-dg" /// Determines a parallel build order for the given set of targets -[] +[] let determineBuildOrder (target : string) (parallelJobs : int) = let t = getTarget target @@ -671,7 +672,7 @@ let determineBuildOrder (target : string) (parallelJobs : int) = |> Seq.toList /// Runs a single target without its dependencies -[] +[] let runSingleTarget (target : TargetTemplate) = try if errors = [] then @@ -687,7 +688,7 @@ let runSingleTarget (target : TargetTemplate) = targetError target.Name exn /// Runs the given array of targets in parallel using count tasks -[] +[] let runTargetsParallel (count : int) (targets : Target[]) = targets.AsParallel() .WithDegreeOfParallelism(count) @@ -695,7 +696,7 @@ let runTargetsParallel (count : int) (targets : Target[]) = .ToArray() |> ignore -[] +[] let runTargets (targets: TargetTemplate array) = let lastTarget = targets |> Array.last if errors = [] && ExecutedTargets.Contains (lastTarget.Name) |> not then @@ -707,7 +708,7 @@ let runTargets (targets: TargetTemplate array) = targets |> Array.iter runSingleTarget /// Runs a target and its dependencies. -[] +[] let run targetName = if doesTargetMeanPrintDotGraph targetName then PrintDotDependencyGraph() else if doesTargetMeanListTargets targetName then listTargets() else @@ -746,25 +747,25 @@ let run targetName = changeExitCodeIfErrorOccured() /// Registers a BuildFailureTarget (not activated). -[] +[] let BuildFailureTarget name body = Target name body BuildFailureTargets.Add(name,false) /// Activates the BuildFailureTarget. -[] +[] let ActivateBuildFailureTarget name = let t = getTarget name // test if target is defined BuildFailureTargets.[name] <- true /// Registers a final target (not activated). -[] +[] let FinalTarget name body = Target name body FinalTargets.Add(name,false) /// Activates the FinalTarget. -[] +[] let ActivateFinalTarget name = let t = getTarget name // test if target is defined FinalTargets.[name] <- true