在FAKE中,您通常有一个类似的构建脚本:
// "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"
哪个工作正常。现在假设您需要另一个名为“bar.fsx”的构建脚本,
// "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"
现在这是错误的。如果您尝试运行“bar.fsx”,它将首先执行任务“Foo”,即使我没有明确要求将其作为依赖项。这是因为load
指令运行foo.fsx
脚本。
所以,我的问题是,如何导入foo.fsx
文件,获取所有目标,但不执行Run
命令。或者更有趣的是,我真正想做的事情;如何在FAKE中的脚本之间共享Target
?
如果我将Target
定义放入模块中,这样做无效:
module FooTargets =
Target "Foo" (fun _ -> trace "Here I am, foo the size of a bar" )
这对我来说可能有点令人惊讶......
欣赏有关如何实现这一目标的任何建议。到目前为止,我的“最佳”想法是在'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")
,
// "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"
,
// "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"
,
// "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"
使用: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
答案 0 :(得分:9)
在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"
答案 1 :(得分:1)
Here's我想出了一个解决方案。由于#load
的实际情况以及运行目标的FAKE流程,我不得不从构建过程中分离出目标。但它至少可以实现我的目标。我并不完全确定我的感受,因为&#34;松散&#34;文件间依赖关系之间的连接;但也许人们可以说这是件好事。