使用fvm导致一些CLI工具无法找到flutter命令的解决方案
在使用fvm时由于Flutter命令需要fvm代理,例如使用如下形式:fvm flutter
,除非你的环境变量设置了其中一个版本的Flutter SDK的路径,否则直接使用flutter
命令会提示找不到命令。并且有些时候会遇到一些令人费解的问题,例如当你在.zshenv
文件(如果你使用其他shell,可能是其他的环境变量文件)中设置了正确的Flutter SDK路径,但是尝试运行which dart
或者which flutter
时发现还是输出错误的位置。本文以macOS下的Zsh为例来解决这个问题,其他shell请自行替换成对应的rc和env文件。
fvm代理flutter命令的问题
一旦你使用fvm进行flutter版本的管理,每次执行flutter命令都必须在前面加一个fvm,写成fvm flutter
的形式,诚然,你可以通过alias flutter="fvm flutter"
来让使用flutter命令更加便捷,但是这样做对一些CLI工具来说是无效的,例如在使用Riverpod时riverpod_lint工具无法找到对应的flutter命令,并且还可能出现即使鬼使神差地找到了flutter命令,但是使用的flutter和dart并不是对应版本的魔幻情况,至于这个问题,我们在下一个小节再讨论,这里先解决fvm代理flutter的问题。
其实fvm会在用户目录下创建一个~/fvm
目录,这个目录下有:
versions
子目录中存放的就是所有的Flutter SDK,注意到这里还有个链接文件default
,可以看到在上图中,这个链接文件指向的是我本地的3.24.2版本。fvm有一个fvm global <Flutter Version>
命令,可以用来设置全局的Flutter版本,而这个default
就是指向这个全局版本的。遗憾的是虽然是全局版本,我们还是需要fvm flutter
来执行flutter命令,为了解决这一点,我们可以将这个default
链接添加到环境变量PATH
中!
使用
1 |
|
打开Zsh的环境配置脚本
为了保证我们环境变量的优先级,建议在最后一样这样进行添加:
添加完毕后保存,然后重启终端即可
不要仅尝试使用
source ~/.zshenv
命令来更新变量,最好还是重启一下,具体原因下一小节解释
重启终端后,使用which dart
和which flutter
,如果这俩是来自同一目录下,说明配置生效了,如果这俩还是来自不同目录,请看下一小节
Homebrew或其他包管理器造成的环境变量优先级问题
根据上一小节最后内容,如果你发现dart命令和flutter命令来自不同的目录,并且其中有一方是来自你的Homebrew(或者其他你使用的包管理器目录)的话,说明你遇到了环境变量优先级的问题,首先说明,你之前配置的环境变量是没有问题的,不信可以echo $PATH
,确实可以看到我们配置的default
目录是在环境变量中的。
Zsh的启动脚本执行顺序
我们在.zshenv
中设定环境变量时,还特定将我们的环境变量优先级设置到了最高,可是最后还是遇到了问题,唯一可能的问题就是还有其他地方也往PATH中添加了路径,并且是添加在我们所添加的路径的前面的。
那么Zsh在启动时除了执行我们配置过的.zshenv
脚本,还会执行其他脚本吗?会的,其实大多数shell都会根据启动类型来执行不同的脚本,在Zsh中,有以下类型的脚本:
- .zshenv
- .zshrc
- .zprofile
- .zlogin
- .zlogout
这些脚本根据打开shell时是否是登录类型来确定是否执行
- 登录Shell:通过SSH远程打开、通过
zsh -l
命令打开时为登录shell,此时脚本执行顺序为:.zshenv → .zprofile → .zshrc → .zlogin
- 非登录Shell:使用图形界面打开、使用
zsh
命令打开、使用zsh -i
命令打开时为非登录Shell,此时脚本的执行顺序为:.zshenv → .zshrc
在平时开发的时候,我们基本都是使用图形化界面打开Shell的,所以基本都是非登录Shell,只需要重点关注.zshenv
和.zshrc
这两个脚本即可。
解决
刚才我们的环境变量被降低了优先级,那肯定就是在.zshrc
中发生的,解决方案自然而然,只需要在.zshrc
脚本最后添加我们刚才在.zshenv
中添加的那行export
命令即可,这样就能保证我们的环境变量是最高优先级。
后话
前面我们说不要仅仅只是用source ~/.zshenv
来更新Shell变量,这是因为,source命令会重新执行.zshenv
脚本,但是却不会执行.zshrc
脚本!所以如果.zshrc
中有对.zshenv
中的环境变量的优先级覆盖行为,运行source ~/.zshenv
命令后会发现你似乎配置成功了,但是下一次再打开Shell,变量优先级还是会被覆盖!