Как перевести этот скрипт MSBuild в F # / FAKE? - PullRequest
1 голос
/ 01 апреля 2019

Как переводится следующий скрипт MSBuild на F # / FAKE?

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup>
        <CurrentMode>None</CurrentMode>
    </PropertyGroup>

    <Target Name="Compile_A">
        <Message Text="Hello from Compile_A" />

        <CallTarget Targets="SetToA"/>
        <CallTarget Targets="IntermediateStage"/>
    </Target>

    <Target Name="Compile_B">
        <Message Text="Hello from Compile_B" />

        <CallTarget Targets="SetToB"/>
        <CallTarget Targets="IntermediateStage"/>
    </Target>

    <Target Name="IntermediateStage">
        <Message Text="Hello from IntermediateStage" />

        <CallTarget Targets="Compile"/>
    </Target>

    <Target Name="Compile">
        <Message Text="Hello from Compile. I'm using $(CurrentMode)" />
    </Target>

    <!-- The following Targets are only necessary due to a MSBuild bug (CallTarget and CreateProperty cannot be combined) -->
    <Target Name="SetToA">
        <CreateProperty Value="A">
            <Output TaskParameter="Value" PropertyName="CurrentMode" />
        </CreateProperty>
    </Target>

    <Target Name="SetToB">
        <CreateProperty Value="B">
            <Output TaskParameter="Value" PropertyName="CurrentMode" />
        </CreateProperty>
    </Target>
</Project>

Моя главная цель - установить свойство в самых верхних целях с различными значениями (CurrentMode равно A или B) и использовать его в самой глубокой цели (Compile).

1 Ответ

3 голосов
/ 02 апреля 2019

Лучший ответ, вероятно, будет отличаться в зависимости от вашего реального сценария.В частности, вам могут даже не потребоваться отдельные цели для разных этапов вашего процесса, если вы никогда не планируете запускать их отдельно (в этом случае просто используйте функцию, которая принимает режим в качестве параметра, и вызываете его из CompileAи CompileB будет работать нормально).

Однако, если вы хотите сохранить отдельные цели для всех шагов, вы можете сделать что-то вроде этого:

#load ".fake/build.fsx/intellisense.fsx"
open Fake.Core
open Fake.Core.TargetOperators

let mutable CurrentMode = "None"

Target.create "SetA" (fun _ ->
  CurrentMode <- "A"
)

Target.create "SetB" (fun _ ->
  CurrentMode <- "B"
)

Target.create "IntermediateStage" (fun _ ->
  printfn "In the intermediate stage"
)

Target.create "Compile" (fun _ ->
  printfn "Compiling using mode %s" CurrentMode
)

Target.create "CompileA" ignore
Target.create "CompileB" ignore

"SetA" ==> "CompileA"
"SetB" ==> "CompileB"
"IntermediateStage" ==> "Compile" ==> "CompileA"
"IntermediateStage" ==> "Compile" ==> "CompileB"
"SetA" ?=> "IntermediateStage"
"SetB" ?=> "IntermediateStage"

Target.runOrDefault "CompileA"

При этом используется изменяемая переменная CurrentMode, которое устанавливается с помощью SetA или SetB целей (возможно, не очень функционально, но оно отражает то, что вы делаете).

Зависимости между целями задаются с помощью ==>.Обратите внимание, что SetA должно произойти до CompileA (и аналогично для B), а IntermediateStage - до Compile, что является обязательным условием для обоих типов компиляций.

Существует один тонкийуловка - вы не хотите говорить, что SetA и SetB требуются для IntermediateStep, потому что тогда FAKE будет работать как в недетерминированном порядке.Оператор ?=> позволяет указать мягких зависимостей , которые говорят, что если должны выполняться и IntermediateStep, и SetA, то SetA должен идти первым - поэтому последние две строки не добавляютсязависимости, но с явным упорядочением.

...