这是.NET Core离线开发与编译系列的第二篇。本系列目录如下:

  1. .NET Core 离线开发与编译-初步
  2. .NET Core 离线开发与编译-进阶
  3. .NET Core 离线开发与编译-VS离线安装

offline.jpg

Paket安装

dotnet tool管理

最简单的方式是通过dotnet tool来安装:

安装成全局工具

dotnet tool install --global Paket

这样就可以使用paket命令了。不过,我并不喜欢这个方式。原因很简单,强迫所有代码仓库都使用同一个版本的Paket进行管理不够灵活。

好在我们可以把Paket安装成局部工具:

dotnet new tool-manifest

dotnet tool install Paket

这种情况下,我们可以在每个具体的项目目录下,以dotnet paket子命令的形式使用Paket。相比于全局工具安装,这个方式非常方便、干净。

但是,这个方式有两个缺点:

  1. 在完全断网的情况下,dotnet tool install默认需要联网安装。我们当然可以把nuget包下载到本地来安装,但是这样依然不够方便。
  2. 此外,dotnet tool局部工具对于fsx#r "paket: nuget ...."的支持并不友好。该机制需要会逐级向上查找父目录是否存在.paket/paket.exe(最终如果没有找到,会再去查找全局的)。但是本地dotnet tool的方式下并不会把paket.exe这个二进制文件拷贝到.paket/下。

解决办法有两个:

  1. 安装成局部工具的同时指定到.paket/路径: dotnet tool install paket --tool-path ./.paket。这样dotnet tool就会在仓库目录下创建一个.paket/paket.exe。注意这时候paket不会变成dotnet子命令(dotnet paket不起作用,需要直接调用.paket/paket.exe
  2. 直接拷贝paket.exe二进制文件到.paket/文件夹下。

直接使用paket.exe二进制文件

除了使用dotnet tool来安装Paket,还可以直接使用paket.exe二进制文件。使用这种方法,我们可以做到在线下载、离线分发和安装。

  1. GitHub上下载paket.bootstrapper.exe——这是一个下载器,会帮我们下载号最新的paket.exe
  2. 在项目根目录下创建一个.paket目录,并将paket.bootstrapper.exe拷贝到其中。
  3. 运行下载器.paket/paket.bootstrapper.exe。下载完成后,Paket会被保存到路径./.paket/paket.exe
  4. 运行.paket/paket.exe <子命令>来调用Paket工具

代码仓库的项目结构

- .paket/
    paket.bootstrapper.exe # paket.exe下载器
    paket.exe              # 二进制文件
    paket.targets          
    Paket.Restore.targets  
- paket.dependencies       # 整个代码仓库的依赖定义
- paket.lock               # 版本锁定文件
- paket-files/             # 应该加到gitignore中。
- 项目1/
    paket.references       # 当前子项目的依赖声明
    ... 其他项目文件
- 项目2/
    paket.references       # 当前子项目的依赖声明
    ... 其他项目文件

对于一个代码仓库,所有的依赖是放在一起管理的(由paket.dependencies定义)。每个子项目的引用是代码仓库依赖的一个子集(由独立的paket.references声明)。

Paket命令行工具

初始化:

npm init类似,Paket也有一个init命令:

dotnet paket init

该命令会替我们创建两个文件:

  • 在当前目录下,创建一个paket.dependencies依赖文件。
  • .paket/目录下,创建一个paket.targets项目文件

,供具体的*.csproj导入

添加Nuget包依赖、安装、与恢复

dotnet add package <包名>命令类似,paket也提供了类似的方式:

dotnet paket add <包名>

该命令会在paket.dependencies里添加一行依赖声明。

安装依赖:

dotnet paket install

恢复依赖:

dotnet paket restore

离线缓存和本地存储

配置离线

可以用cachestorage控制离线功能:

source https://api.nuget.org/v3/index.json
cache ./nuget-caches                           # 缓存
// storage: none                               # 注释掉这个,使用默认值,会创建一个传统 packages/ 文件夹。

cache可以指定一个本地路径或者一个网络共享位置,并把依赖的*.nupkg缓存到其中。

storage则指定了*.nupkg依赖解压后的本地存储选项。storage选项可以指定三种值:

  • storage: packages 默认值,把依赖文件存储到 packages/ 文件夹下。
  • storage: none 禁用packages/文件夹,使用 全局NuGet cache
  • storage: symlink使用packages/文件夹,但是使用软连接而非物理文件

如何从离线缓存中恢复

  1. 首先确保cache所指定的文件夹能被离线机器访问。
  2. 移除paket-files/文件夹
  3. 然后执行.paket/paket.exe restore。这时会创建packages/文件夹
  4. 执行dotnet restore --source ./packages来恢复依赖

FSX的支持

.NET5开始,.NET Core支持在fsx中直接通过#r自动引用相关依赖。FSharp提供了一个扩展机制来支持Paket。也即通过#r "paket: nuget..."的方式引用nupkg

#r "paket: nuget NewtonSoft.Json"

open Newtonsoft.Json
let a = {| A = 1 ;B = "a" |}

JsonConvert.SerializeObject(a)

当然,这样做的前提是,为FSharp安装依赖管理器扩展

FSharp的依赖管理器扩展

为了让#r支持paket扩展,我们需要从 nuget.org 上下载 FSharp.DependencyManager.Paket ,或者在GitHub Release上下载。然后把其中的FSharp.DependencyManager.Paket.dll拷贝到FSharp SDK的目录下。如果你使用的是Windows操作系统,路径可能长这样:

C:/Program Files/dotnet/sdk/6.0.101/FSharp

一般来说,FSharp会内置一个FSharp.DependencyManager.Nuget.dll,当我们把FSharp.DependencyManager.Paket.dll拷进去后,就会出现两个dll

C:/Program Files/dotnet/sdk/6.0.101/FSharp
    ... //  其他文件和文件夹
    FSharp.DependencyManager.Nuget.dll
    FSharp.DependencyManager.Paket.dll
    ... //  其他文件和文件夹

除了这个全局扩展,我们还需要一个可以被发现的Paket.exe。具体来说,是fsx文件的父目录或者逐级向上的父目录中要存在.paket/paket.exe(如果找不到,则会去一些全局位置检索,但是我个人更喜欢逐级向上检索这样的方式)。

dotnet fsi的执行

执行之前,需要在脚本所在目录下先执行恢复依赖的命令:

.paket/paket.exe restore

当执行dotnet fsi <脚本文件.fsx>时,会创建一个临时文件,并把相关paket文件都拷贝进去。然后从cache路径中恢复依赖到本地packages/中。

VSCode fsx智能提示

当然,在VSCode中,还有一个额外的动作才能让智能提示工作:把FSharp.DependencyManager.Paket.dll也拷贝到vscodefsharp扩展中。举个例子,在我的电脑上,路径可能是
~/.vscode/extensions/ionide.ionide-fsharp-5.10.2/bin

标签: C#, F#, .NET

添加新评论