Any way to have a many-buildfile structure in FAKE?
In Build.Tools we ended up putting the code for the various targets in different script files as normal F# functions, and then composing the targets together in a Core.fsx that sets up the targets and their dependencies.
One of the things on my low priority todo list is actually to separate Core into two files - one which builds up the configuration and target definitions, and one which sets up the dependencies and calls Run
. In that way you could re-use all underlying targets while defining different runners that didn't have to include the full default dependency tree.
The current Core.fsx
looks like this:
#r "./fake/fakelib.dll"
#load "./Utils.fsx"
#load "./Packaging.fsx"
#load "./Versioning.fsx"
#load "./Solution.fsx"
#load "./Test.fsx"
#load "./Specflow.fsx"
open System.IO
open Fake
let config =
Map.ofList [
"build:configuration", environVarOrDefault "configuration" "Release"
"build:solution", environVar "solution"
"core:tools", environVar "tools"
"packaging:output", environVarOrDefault "output" (sprintf "%s\output" (Path.GetFullPath(".")))
"packaging:updateid", environVarOrDefault "updateid" ""
"packaging:pushurl", environVarOrDefault "pushurl" ""
"packaging:apikey", environVarOrDefault "apikey" ""
"packaging:packages", environVarOrDefault "packages" ""
"versioning:build", environVarOrDefault "build_number" "0"
"versioning:branch", match environVar "teamcity_build_branch" with
| "<default>" -> environVar "vcsroot_branch"
| _ -> environVar "teamcity_build_branch"
]
Target "Default" <| DoNothing
Target "Packaging:Package" <| Packaging.package config
Target "Packaging:Restore" <| Packaging.restore config
Target "Packaging:Update" <| Packaging.update config
Target "Packaging:Push" <| Packaging.push config
Target "Solution:Build" <| Solution.build config
Target "Solution:Clean" <| Solution.clean config
Target "Versioning:Update" <| Versioning.update config
Target "Test:Run" <| Test.run config
Target "SpecFlow:Run" <| Specflow.run config
"Solution:Clean"
==> "Packaging:Restore"
==> "Versioning:Update"
==> "Solution:Build"
==> "Packaging:Package"
==> "SpecFlow:Run"
==> "Test:Run"
=?> ("Packaging:Push", not isLocalBuild)
==> "Default"
RunParameterTargetOrDefault "target" "Default"
Here's a solution I came up with. I had to separate out the targets from the build process, due to the realities of #load
and the FAKE process for running targets. But it at least accomplishes my goal. I'm not entirely sure how I feel about it, because of the "loose" connection between the inter-file dependencies; but perhaps one could argue that that is a good thing.