Java开发人员需要帮助理解F#中的.NET构建过程

时间:2017-03-25 17:28:13

标签: java maven f# f#-fake paket

我的大多数开发都是在Java中,我习惯于使用运行时,编译器和构建工具。所以现在我试图进入.NET世界,特别是使用VSCode,Ionide插件和F#来构建一个F#程序。我很难理解与Java构建过程的直接比较。到目前为止,这是我的粗略理解:

  • JRE - > .NET Runtime?
  • JDK工具 - > Microsoft Build Tools 2015包括F#编译器和其他工具?
  • Paket - >行家?
  • FAKE - > pom.xml中maven的#contentSub部分?
  • paket.dependencies和paket.references - &gt; pom.xml中maven的<build>部分?
  • *。* proj文件 - &gt; ???

我对* proj文件感到很困惑。我认为这与MSBuild有关。但是我很困惑,因为我认为FAKE是MSBuild的替换,但是有些FAKE的例子我已经看过引用这个文件并将它传递给MSBuildRelease任务。

另外,为什么paket需要依赖引用文件?

我希望有人可以确认,澄清,添加或上述任何内容,到目前为止我的理解水平。非常感谢!

编辑:

我知道这个问题很复杂,而且不是很具体。感谢大家花时间去除它并回答你的能力。我很感激。

3 个答案:

答案 0 :(得分:6)

由于没有人回答你问题的Paket部分,我会解决那个问题。

在一个Git存储库中,您可能有多个项目。例如,这是一种非常常见的模式(如此常见,community packages for ArchLinux ARM以这种方式设置,因为它是大多数人想要的)为您的主代码和测试创建单独的项目。在MyApp.fsproj文件中,您可能不希望引用NUnit或XUnit,但您确实需要MyApp.Tests.fsproj文件中的这些引用。

paket.dependencies文件是每个存储库一个,它列出了所有存储库中任何项目要使用的软件包。 paket.references个复数文件是每个项目一个,并且与它们对应的.fsproj文件位于同一目录中。他们列出 项目想要引用的包。因此,在与paket.references相同的目录中的MyApp.Tests.fsproj文件中,您将列出NUnit或XUnit - 但您列出{{1}中的单元测试库}文件与paket.references在同一目录中。

如果您的Git仓库中只有一个项目,那么就不需要单独的MyApp.fsprojpaket.dependencies文件,因为它们可以合并为一个文件,同时满足这两个目的。但是,只要在单个存储库中有多个paket.references文件,那么依赖项和引用之间的分离就会变得很有用,因为您可以将所有依赖项列在repo根目录中的单个.fsproj文件中,但是为每个项目提供自己的paket.dependencies文件,以便它只能引用它特别需要的依赖项子集。

答案 1 :(得分:5)

让我试着逐一解决这些问题......

问:什么是* proj文件?

*proj文件是MSBuild的本地语言(如果您使用Mono,则为xbuild)。在最简单的情况下,它们只列出要编译的所有文件以及对它们使用的其他项目的所有引用。还有一些其他属性,比如目标平台,CPU架构等。最初的想法是一个*proj文件产生一个编译汇编单元(又名“DLL”,大致对应于JAR)。这仍然是大多数情况,但并非总是如此。例如,TypeScript项目可以生成多个JS文件。

但MSBuild的核心架构使这些文件非常灵活。它们基本上构建在一个插件系统(称为“任务”)上,其中每个任务都做一些特定的事情。框中包含许多任务,例如“编译C#文件”或“输出到日志”,但您也可以添加自己的任务,或者以包的形式安装一些任务,或者全局安装。另外,MSBuild的核心允许一些技巧,比如变量(种类),循环(类型)和分支(近似),以至于你可以完全用{{1}编写实际程序。文件。这背后的最初想法是,MSBuild将成为整个构建过程的主要工具,无需其他工具。对于简单的玩具项目来说,它就是:当你需要的只是将一堆文件编译成DLL时,MSBuild可以很好地完成工作。即使是不那么简单的项目,人们也试图完全用*proj文件来完成整个构建。有些项目甚至可以做到这一点。

然而,随着时间的推移,很明显用XML编写高级构建逻辑是如此棘手和倒退,以至于它变得非常快速无法维护。因此,出现了一堆专门用于实现高级构建逻辑的工具。这让我想到......

问:不是FAKE替代MSBuild吗?

是的,确实如此。嗯,不,实际上并非如此。也许。那种。

正如我上面所说,可以在MSBuild中编写整个构建逻辑:编译,复制,压缩(需要),捆绑(如果需要),包(适当时)和发布(合法的地方:-) 。但写作非常尴尬,很快变得无法维护。

输入FAKE:在FAKE中,您编写构建过程entirely in F#的整个逻辑。这意味着您可以使用库,抽象,高阶函数,特殊类型 - 真正的高级语言的所有优点。您可以使用glob模式指定源文件列表,使用FscHelper调用F#编译器,使用XUnitHelper运行测试,使用Paket helper打包和发布,deploy to Azure,甚至notify your teammates on Slack - 所有这一切都没有离开功能性的善良。

但有一个问题:构建脚本无法通过工具进行分析。
由于它是一个真正的程序,而不是数据格式,IDE不知道如何从中取出源文件列表,或者如何添加新文件;包管理器不知道在哪里插入对包的引用,等等 另一方面,MSBuild文件是可分析性的定义:它们是XML,并且有关于其中的内容的强有力的标准。

它变成了:我们使用MSBuild指定一些严格但简单的属性,然后使用FAKE脚本“驱动”更高级别的构建逻辑 - 例如运行测试,生成文档,发布,部署等而不是指定文件列表并直接调用F#编译器,我们的构建脚本只调用MSBuild。

问:为什么Paket需要引用依赖项?

简而言之:因为我们通常会同时处理多个编译单元(又称“项目”)(我们将这样的项目系统称为“解决方案”),我们不喜欢当一个解决方案下的不同项目使用相同软件包的不同版本时:冲突比比皆是,我们的头脑爆炸。因此,我们为整个解决方案指定了一个包列表(在“依赖关系”中),然后每个项目都可以选择它实际使用的包(在“参考”中)。

很长时间@rmunn's excellent answer会更详细地讨论这个问题。

也感兴趣:“原生”.NET包管理器NuGet实际上并没有这个属性。 NuGet下的每个项目都有自己完全独立的包列表。这个爆炸性的版本冲突确实发生了。在大型解决方案上,经常令人沮丧。这是Paket优越的原因之一。

答案 2 :(得分:0)

我在Windows平台上。 我的(旧)版本附带的F-Sharp编译器是Microsoft版本,称为Fsc.exe。我这样使用它:Fsc.exe HelloWorld.fs

我最近开始使用假。在我的Fake构建脚本中有一个命令MSBuild,它调用MSBuild,后者又调用Fsc.exe。所以从某种意义上说,所有额外的包装都在那里,所以我需要输入更少(Fsc的参数字符串很容易变得有点长,并且有很好的工具来确保参数是&#39;正确&#39;。)

.fsproj文件是一个文件,其中包含MSBuild用于发送给Fsc的信息。该文件也可以通过例如Visual Studio,以便您的文件在(Visual Studio)编辑器中显示为一个项目。