在FAKE中有多种构建文件结构的方法吗?

Noo*_*ilk 12 f# f#-fake f#-fake-4

FAKE中,您通常有一个buildcript,如:

// "foo.fsx"
#r @"./packages/tools/FAKE/tools/FakeLib.dll"

open Fake

Target "Foo" (fun _ -> trace "Here I am, foo the size of a bar" )

Run "Foo"
Run Code Online (Sandbox Code Playgroud)

哪个工作正常.现在假设你想要另一个名为"bar.fsx"的buildcript,

// "bar.fsx"
#r @"./packages/tools/FAKE/tools/FakeLib.dll"
#load "foo.fsx"

open Fake

Target "Bar" (fun _ -> trace "And you have me building software ..." )

Run "Bar"
Run Code Online (Sandbox Code Playgroud)

现在这是错误的.如果您尝试运行"bar.fsx",它将首先执行任务"Foo",即使我没有明确要求将其作为依赖项.这是因为该load指令运行foo.fsx脚本.

所以,我的问题是,如何导入foo.fsx文件,获取所有目标,但不执行说Run命令.或者更有趣的是,我真正想做的事情; 如何Target在FAKE中的脚本之间共享?

如果我将Target定义放入模块中,它就没有用,如下所示:

module FooTargets =
    Target "Foo" (fun _ -> trace "Here I am, foo the size of a bar" )
Run Code Online (Sandbox Code Playgroud)

这对我来说可能有点令人惊讶......

感谢有关如何实现这一目标的任何建议.到目前为止,我的"最佳"想法是在'foo.fsx'中定义一些常量,然后load在所有其他脚本中有条件地定义.这看起来非常令人反感(编辑:很开心,甚至不可能.)

- 更新:下面是一个更完整(即可运行)的示例.由于模块Common已加载两次,并且FAKE已使用相同的"Env"目标填充目标字典,因此FAKE 2.2.12.0失败并出现Duplicate Key错误.

// "common.fsx"
#r     @"../../tools/FAKE/FakeLib.dll"

open Fake

module Common = 
    Target "Env" (fun _ -> trace "Env")
Run Code Online (Sandbox Code Playgroud)

,

// "foo.fsx"
#r     @"../../tools/FAKE/FakeLib.dll"
#load  @"common.fsx"

open Fake

module Foo =
    Target "Foo" (fun _ -> trace "Here I am, foo the size of a bar" )

"Env" ==> "Foo"
Run Code Online (Sandbox Code Playgroud)

,

// "bar.fsx"
#r     @"../../tools/FAKE/FakeLib.dll"
#load  @"common.fsx"

open Fake

module Bar =
    Target "Bar" (fun _ -> trace "And you have me building software ..."  )

"Env" ==> "Bar"
Run Code Online (Sandbox Code Playgroud)

,

// "marvin.fsx"
#r     @"../../tools/FAKE/FakeLib.dll"

#load  @"common.fsx"
#load  @"foo.fsx"
#load  @"bar.fsx"

open Fake

module Marvin =
    Target "Marvin" (fun _ -> ())

"Bar" ==> "Marvin"
"Foo" ==> "Marvin"

Run "Marvin"
Run Code Online (Sandbox Code Playgroud)

建立:fake.exe Marvin.fsx.

错误:

System.TypeInitializationException: The type initializer for '<StartupCode$FSI_0002>.$FSI_0002_Common$fsx' threw an exception. ---> System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at Fake.TargetHelper.targetFromTemplate[a](TargetTemplate`1 template, String name, a parameters)
   at Fake.TargetHelper.TargetTemplateWithDependecies@140.Invoke(String name, a parameters)
   at <StartupCode$FSI_0002>.$FSI_0002_Common$fsx..cctor() in c:\Users\Noon\dev\beep\common.fsx:line 7
   --- End of inner exception stack trace ---
   at <StartupCode$FSI_0002>.$FSI_0002_Foo$fsx.main@() in c:\Users\Noon\dev\beep\foo.fsx:line 8
Stopped due to error
Searching for process with name = fsi.exe
Searching for process with name = msbuild
Run Code Online (Sandbox Code Playgroud)

mav*_*vnn 10

Build.Tools中,我们最终将不同脚本文件中的各种目标的代码作为普通的F#函数,然后在Core.fsx中组合目标,以设置目标及其依赖项.

我的低优先级待办事项列表中的一个实际上是将Core分成两个文件 - 一个用于构建配置和目标定义,另一个用于设置依赖项和调用Run.这样,您可以重新使用所有基础目标,同时定义不必包含完整默认依赖关系树的不同运行程序.

目前的情况Core.fsx如下:

#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"
Run Code Online (Sandbox Code Playgroud)


Noo*_*ilk 1

这是我想出的一个解决方案。#load由于运行目标的现实情况和 FAKE 过程,我必须将目标从构建过程中分离出来。但至少达到了我的目的。由于文件间依赖关系之间的“松散”连接,我不完全确定自己的感受如何;但也许有人会说这是一件好事。