【问题标题】:Java developer needs help understanding the .NET build process in F#Java 开发人员需要帮助了解 F# 中的 .NET 构建过程
【发布时间】:2017-03-25 17:28:13
【问题描述】:

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

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

我真的对 *proj 文件感到困惑。我认为这与 MSBuild 有关。但我很困惑,因为我认为 FAKE 是 MSBuild 的替代品,但我看到的一些 FAKE 示例引用了这个文件并将其传递给 MSBuildRelease 任务。

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

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

编辑:

我知道这个问题很复杂,而且不是很具体。感谢大家抽出宝贵的时间来梳理它并回答你的能力。我很感激。

【问题讨论】:

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


    【解决方案1】:

    由于尚未有人回答您问题的 Paket 部分,我会解决这个问题。

    在一个 Git 存储库中,您可能有多个项目。例如,为您的主代码和测试创建一个单独的项目是一种非常常见的模式(如此普遍,以至于ProjectScaffold repo 是这样设置的,因为这是大多数人想要的)。在您的 MyApp.fsproj 文件中,您可能不希望在您的 MyApp.Tests.fsproj 文件中引用 NUnit 或 XUnit。

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

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

    【讨论】:

    • 您对将单元测试分离到他们自己的项目中的解释有助于我理解这一点。在 java 中,我们通常将单元测试与代码分开放在不同的文件夹下,并告诉构建工具我们的测试所在的位置。此外,maven 和 gradle 没有列出不同编译单元的依赖项的不同 .references 文件,而是具有“范围”依赖项,您可以在其中将依赖项标记为“测试”、“编译”、“仅运行时”的一部分等等。我猜只是一种不同的方式或组织事物。感谢您的回答!
    • 我们还将测试放在不同的文件夹中。而且我们还有“范围”依赖。但范围不够。我们想为每个编译单元单独指定依赖关系。
    【解决方案2】:

    让我尝试一一解决这些问题......

    问:*proj 文件有什么用?

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

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

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

    问:FAKE 不是 MSBuild 的替代品吗?

    是的,是的。嗯,不,实际上不是。也许。有点。

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

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

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

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

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

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

    长篇大论@rmunn's excellent answer 更详细地讨论了这一点。

    也很有趣:“本机”.NET 包管理器 NuGet 实际上没有这个属性。 NuGet 下的每个项目都有自己的、完全独立的包列表。而这种令人头疼的版本冲突确实会发生。在大型解决方案上,常常令人沮丧。这是 Paket 优越的众多原因之一。

    【讨论】:

    • 所以,您是说存在 .dependencies 文件 .references 文件的原因是,每个项目都保证使用相同版本的依赖项作为解决方案中的其他项目?为什么这在 .NET 领域很重要?下载时不同版本的依赖项会相互覆盖吗? Java的构建工具似乎没有问题。我的意思是,我当然希望我的脑袋爆炸:),但你能详细说明这一点吗?顺便说一句,很好的答案。感谢您抽出宝贵时间。
    • 我的理解是,Java 中确实存在相同的问题,但就像 .NET 默认的冲突解决方案一样,可能会缓解大多数这些问题,直到它出现,然后你必须处理它。我听说过一些关于 Java 9+ 中的模块更改如何旨在解决同样问题的讨论。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 2016-05-03
      相关资源
      最近更新 更多