Привет друзья. В жизни разработчика рано или поздно наступает момент, когда проектов становится так много, что одной единственной (обычно это stable) версией flutter sdk уже не обойтись. Это может произойти по причине использования форкнутым проектом старой, несовместимой (это не только мажорные) с текущей любимой stable, версии. Либо же вы хотите попробовать новую функциональность из beta версии в вашем проекте. Вроде можно обойтись разделом "Flutter SDK archive" и вручную менять пути в IDE, но предлагаю вам вариант получше.
Сегодня я поведаю о том, как можно использовать пакет (программу) fvm для управления разными версиями flutter sdk. Изначально я предполагал, что такой материал уже есть на Хабре, но поиск результатов не дал (здесь было моё большое удивление, ведь его нет даже в формате "Перевод"). Поэтому смело восполняю данный пробел.
В конце данной статьи вы также найдёте полезные ссылки на материалы других авторов по данной теме. Приступим!
Содержание
Введение
Начало работы
Команды
Частые
Редкие
Эпизодические
Применение
В системе
В IDE
В Android Studio
В VS Code
GUI
Мини-расследование
Полезные советы
Бонусная история
Аналоги
Puro
Заключение
Полезные ссылки
Введение
Управление разными версиями чего бы то ни было — одна из важных тем в разработке программного обеспечения. В контексте flutter sdk это означает, что может существовать только одна используемая версия, а переключение между ними занимает много времени из-за отсутствия кэширования (я про flutter [down|up]grade
).
Получается так, что если мы работаем над многими проектами с разными требуемыми версиями flutter sdk, то нужно каким-то образом иметь необходимые версии под рукой и переключаться между ними по мановению программерской палочки. Более того, это оказывается крайне удобным для тестировании "реакции" вашего приложения на разные каналы flutter sdk, быстро прыгая между ветками stable и beta.
Этой палочкой и является FVM, инструмент для контроля flutter sdk версий. Первый commit датируется от 22 февраля 2019г, а первый релиз состоялся уже 27 фев 2019г. Официальной страницей является сгенерированный сайт-документация fvm.app, и вот что встречает нас на широком крыльце парадного входа:
Множество Flutter SDK версий – "Возможность управлять и кэшировать несколько версий Flutter SDK. Быстрое переключение между каналами и релизами. Просмотр доступных каналов и релизов."
Управление версиями проекта – "Настройте и используйте версию Flutter SDK для каждого проекта. Динамические пути SDK для поддержки отладки в IDE. Обеспечивает согласованность между командами и CI средами."
Расширенный инструментарий – "Управление глобальной версией Flutter SDK. Создание процессов в любой версии Flutter SDK. Docker-образы для CI и рабочего процесса разработки. Установка Flutter из определенных коммитов."
В общем, без преувеличений, всё так и есть.
Начало работы
Для начала установите flutter sdk следуя официальной документации. Это версия будет использоваться глобально. Затем переходим к установке fvm.
ℹ Весь материал основан на версии 2.4.1. На момент выпуска статьи в
changelog.md
уже есть некоторая информация о версии 3.0.0, и косвенно я прошёлся по некоторым представленным там грядущим изменениям.
Есть несколько способов установить сие обеспечение на ваш пк. Начнём с того, что рекомендуемый способ установки заключается в использовании brew для unix или choco для windows:
brew tap leoafarias/fvm
brew install fvm
choco install fvm
Либо, вы можете просто скачать исполняемый файл последней версии из репозитория проекта.
В качестве другого решения вы можете использовать fvm как глобально действующий dart-пакет, установив его простой командой:
dart pub global activate fvm
Большинство статей, на которые я наталкивался, советуют делать именно так (мы же flutter dev!?), однако данный способ уже не рекомендуется (на официальном уровне), потому что будет возникать вот такая милая ошибочка – Running a globally activated binary after SDK upgrade - Can't load Kernel binary: Invalid SDK hash. Это происходит потому, что в момент изменения глобальной версии flutter происходит изменение встроенной версии dart, на которую и опирается snapshot данного пакета. И нет никаких гарантий того, что VM новой версии dart захочет запустить snapshot, сделанный старой версией dart.
Поэтому смело устанавливаем первым способом и движемся дальше.
Команды
Посмотрим на имеющиеся команды с помощью простого запуска fvm
из командной строки:
Available commands:
config Set configuration for FVM
dart Proxies Dart Commands
destroy Destroy FVM cache by deleting FVM directory
doctor Shows information about environment, and project configuration.
exec Executes scripts with the configured Flutter SDK
flavor Switches between different project flavors
flutter Proxies Flutter Commands
global Sets Flutter SDK Version as a global
install Installs Flutter SDK Version
list Lists installed Flutter SDK Versions
releases View all Flutter SDK releases available for install.
remove Removes Flutter SDK Version
spawn Spawns a command on a Flutter version
use Sets Flutter SDK Version you would like to use in a project
Доступно 14 великолепных команд, каждую из которых мы рассмотрим детально, используя микроскоп (gh repo clone fluttertools/fvm
) периодически :)
Частые
Чаще всего вы будете использовать следующие команды:
fvm install <version>
– позволяет скачать и закэшировать определённую версию/канал flutter sdk.fvm dart
– вызывайте команды dart sdk, встроенный в текущий flutter sdk. Это крайне полезно, если необходимо иметь доступ к командам dart sdk, таким как:dart run build_runner build
,dart pub upgrade
,dart migrate
,dart fix —apply
,dart create
,dart test
и прочим;
fvm flutter
– представляет оригинальные команды из flutter sdk, такие какflutter build
,flutter pub
,flutter run
и т.д.fvm use <version>
– используйте данную команду, чтобы к текущему проекту применить определенную flutter sdk версию. Это создаст папку.fvm
в корне проекта с символической ссылкой на flutter sdk и файлfvm_config.json
с текущей конфигурацией. Есть также некоторые полезные флаги:--force
, чтобы игнорировать предупреждения о том, что текущий проект не является flutter-проектом. Это может быть полезно в разных случаях, например, при использовании в dart-проекте или же, если вы хотите создать flutter-проект позже.--pin
, чтобы использовать именно последний релиз с канала. Например,fvm use stable --pin
предложит скачать последнюю версию flutter sdk с каналаstable
(если она ещё не закэширована) и будет использовать именно её в данном проекте.--flavor
позволяет использовать разные версии sdk для разных релизов. Собственно, логика похожа на "ароматы", представленные во flutter. Чтобы выбрать определённую версию flutter sdk для конкретного "аромата" делаем так:fvm use <version> --flavor <flavor_name>
и после нескольких итераций мы имеем такой конфиг-файл:
{
"flutterSdkVersion": "stable",
"flavors": {
"dev": "beta",
"staging": "2.0.3",
"prod": "1.22.6"
}
}
И теперь, когда нам понадобится определённый "аромат", мы делаем так:
fvm flavor staging
, что переключает данный проект на использование flutter sdk версии2.0.3
Редкие
Теперь рассмотрим команды, которые вы будете использовать реже:
fvm global
– установить данную версию в качествеdefault
-версии. Это означает, что когда вы будете находиться НЕ в проекте и вызыватьfvm flutter <command>
, то будет использоваться именно эта глобальная версия. Эту опцию автор пакета в будущем хочет объявить в качестве устаревшей ИЛИ включить в качестве экспериментальной по ряду причин.fvm list
– просмотр всех кэшированных версий flutter sdk. Это крайне удобно сделать перед тем, как использовать командуfvm use
, чтобы случайно не загрузить лишнюю версию (хотя и есть предупреждение на установку) или же, если имеется кастомная версия со сложным названием.fvm releases
– посмотреть все доступные выпуски для установки. Признаюсь честно, это может выглядеть крайне запутанным, быть может из-за того, что dev канал был недавно закрыт.fvm destroy
– удалятся все кэшированные версии flutter sdk и сама директория fvm.fvm remove
– возможность удалить конкретный кэшированный выпуск. То есть пишем командуfvm remove <version>
и происходит удаление sdk. Есть также флаг--force
, чтобы пропустить проверку "Установлена ли данная версия в качестве глобальной".
Эпизодические
И есть ещё более редкие команды, которые я рассмотрю, чтобы сделать данное руководство наиболее полным:
fvm exec
– позволяет выполнить произвольную команду flutter cli из найденной рядом версии flutter sdk (лежащей в директории.fvm/flutter_sdk/bin
). Частая ситуация, когда необходимо выполнить какой-либо скрипт из под текущей версии flutter. Например, у вас лежит скриптgenerate_secrets.sh
. Теперь обзор двух вариантов того, как мы можем это сделать:обычным образом:
PATH="$(pwd)/.fvm/flutter_sdk/bin:$PATH" ./generate_secrets.sh
с помощью
exec
:
fvm exec ./generate_secrets.sh
Некоторую дополнительную информацию вы можете найти в этом issue, который завершился внедрением данной функциональности: [Feature Request] fvm exec.
fvm spawn <version>
– выполнить определённую команду в flutter cli для конкретной версии flutter sdk. Это сильно похоже на обычное проксирование команд с помощьюfvm flutter
за тем исключением, что мы сами выбираем версию sdk, на которой будем выполнять команду. Примеры:
fvm spawn 3.10.6 test
fvm spawn 3.13.0-0.3.pre test
fvm spawn 2.10.5 analyze
fvm config
– работа с конфигурационным файлом fvm. В данный момент этот файл называется.settings
(почему бы не назвать егоsettings.json
? Намёк на то, чтобы ручками не лазили? ) и находится по пути домашнего каталога (USERPROFILE
для windows пользователей,HOME
для unix). Доступные флаги:--cache-path
– указать путь, где будут лежать ваши кэшированные версии flutter sdk. Это будет иметь приоритет над переменной окруженияFVM_HOME
, которую мы можем установить в переменные среды и, согласно которой путь будет%USERPROFILE%/fvm/versions/
.--[no-]skip-setup
– можно пропустить настройку flutter sdk, лишь скачав её дистрибутив (под капотом это подразумевает, что мы пропускаем запуск командыflutter --version
)--[no-]git-cache
– кэширует локальную версию репозитория Flutter для более быстрой загрузки
fvm doctor
– если команда запускается не из под проекта, то мы увидим конфигурацию переменных окружения: путиFlutter
,Dart
,FVM_HOME
,FVM_GIT_CACHE
(установка данной переменной позволяет использовать свой flutter репозиторий, будь-то форк или локальный кэш). При запуске из-под проекта дополнительно получим название текущего проекта, полный путь до проекта, используемую версию flutter sdk и настройку flavor'ов + настроенные пути к flutter sdk в IDE. Есть подсказки, когда всё ещё только предстоит настроить.
Стоит отметить, что официальная документация (ровно как и документация кода) слабенькая, непоследовательная, неполноценная, частенько очевидно-избыточная (ужимка ради 96.2% dartdoc comments?) и всё в том самом духе с приставкой не
. Плюс малоинформативное readme.md
, что в большей степени компенсируется отдельным gh-pages сайтом fvm.app/docs
, однако и тот сильно упрощён и отрывочен. Короче, opensource, все всё понимают, и данный абзац не хочет цинично уничтожить труды контрибьютеров и уважаемого Leo Farias, а лишь подчёркивает данный изъян для любителей форкнуть, разобраться самостоятельно и внести вклад. И тут я поспешу вас обрадовать, потому что сам код более чем понятный и структурированный. Быть может, нам дано увидеть наяву практику "Самодокументируемый Код" от известного дядюшки?
На этом этапе я смело заявляю, что можно попробовать чудо сие в деле применить. Или даже не так: покажу как это делаю я.
Применение
Буду писать абзацами, а не шагами, дабы не ограничивать своё воображение мнимыми рамками беспощадных циферок. Более того, заметьте, что этот крайне скучный, но уже рутинный способ использования не претендует на листья лавра благородного.
В системе
Скачиваем дистрибутив (или помним о brew и choco) и размещаем его в своей любимой папочке с тулзами. Весь дистрибутив выглядит так (fvm-2.4.1-windows-x64.zip
):
fvm
└─fvm.bat
└─src
└─dart.exe
└─fvm.snapshot
└─LICENSE
Так как скоро fvm global
станет устаревшей командой, установите flutter sdk глобально согласно официальной инструкции. В моём случае глобально установлена stable-ветка flutter sdk. Это предполагает, что мы выделим отдельную папочку для stable, а fvm будем использовать исключительно для управления версиями проектов.
Ага и ахах, как бы не так. В реальности мои env-пути выглядят вот так (если будете так делать, то располагайте пути обязательно именно в этом порядке – да, я просто развожу руками от том, что здесь всё "вот-так" и мы обретаем зависимость от единственно-верного расположения путей, но тем самым предостерегаю вас от потраченного времени на отладку):
Папка default
здесь это символическая ссылка на реальную версию flutter sdk. И это прекрасно работает, как и ожидается, в том числе и из-под терминала Android Studio. Вот пруф из обычной консоли:
Это позволяет проверять самые различные гипотезы быстро и надёжно, даже не будучи в данный момент в проекте с настроенной папочкой .fvm
– из любого места, о чём далее и пойдёт речь.
Добавляем путь к файлу fvm.bat
в переменные среды
> переменная Path
> C:\...\tools\fvm\fvm.bat
и теперь обязательно перезапустите вашу консоль (или IDE), чтобы изменения вступили в силу. Поздравляю, доступ к fvm имеется повсюду.
Теперь необходимо указать путь к FVM_HOME
в переменных средах, при чём именно сейчас, так как иначе после он будет создан автоматически по пути домашнего каталога, а мы хотим всё хранить там же, где хранятся наши flutter sdk. Ну, по крайне мере, я так хочу. Если вы не я, пропустите этот шаг :)
Далее, настроим конфиг fvm – для этого вызываем команду fvm config
(не забудьте ввести свой путь до места, где будут храниться ваши flutter sdk):
fvm config --no-skip-setup --git-cache --cache-path=C:\<YOUR_PATH>\sdk\flutter\v\
Теперь самое время установить (то есть закэшировать) вашу первую версию flutter sdk. Делаем вот так (вы также можете установить конкретную ревизию, указав git-коммит или короткий хэш):
fvm install 3.10.6
Поздравляю