Flutterへのコントリビューション仲間を増やしたい

2024/11/25に公開

FlutterはGoogleが中心となって開発しているプロジェクトです。そのため、Flutterのソースコードを改善したり、バグを報告することは難しいイメージがあるのではないでしょうか?

次のPRを見てみてください。どちらも筆者が提出したPRになります。

https://github.com/flutter/flutter/pull/157220

https://github.com/flutter/website/pull/11020

いかがでしょうか? どちらも「簡単じゃん!」と思ったのではないでしょうか? そうです、Flutterへのコントリビューションは簡単なのです!
また「Flutterのコードだけど、Flutterのコードではないじゃん!」と思った方向けに、筆者の手に余りつつも、レビュアーの力を借りてPRをマージまで進めることができたPRも紹介しましょう。順調にいけば、Flutter 3.27にてリリースされる予定の修正です。

https://github.com/flutter/flutter/pull/152215

テストコードが長く見えますが、読んでみると、そう複雑なことをしているわけではありません。修正内容についても、Unicodeの仕様を反映しただけになります。
もちろん難しい修正もたくさんありますが、難しい修正だけがFlutterへのコントリビューションではありません。


本記事では、Flutterにコントリビューションするための環境構築について解説します。対象はflutter/flutterflutter/engineです。本記事は公式ドキュメントの内容を元に、筆者の経験を交えて記述しています。公式ドキュメントも十分に短い解説になっているので、気になる方はそちらも参照してください。

なおflutter/packagesも含めるか迷ったのですが、少しリポジトリの雰囲気が異なるため、今回は対象としません。flutter/packagesへのPRについては、より一般的なOSSへのコントリビューションに近いと思ってください。[1]

flutter/flutter

https://github.com/flutter/flutter

Flutterの中心的なリポジトリです。普段記述するWidgetたちはここにいます。また。ビルドやテストに利用するツールもいます。

実は、Flutterアプリを書いている皆様は、このリポジトリをclone済みです。というのも、Set up Flutterで開発マシンに落としているのが、flutter/flutterリポジトリであるためです。flutter channelflutter upgradeのコマンドは、gitで言えばflutter/flutterのbranchやtagを切り替えることで実現されています。

確かめてみましょう。筆者は~/flutterに開発用のSDKをインストールしています。次のようにディレクトリを移動して、git remote -vを実行すると、以下のような出力が得られます。
ぜひ、自分の環境でも確認してみてください。

$ cd ~/flutter
$ git remote -v
origin	https://github.com/flutter/flutter.git (fetch)
origin	https://github.com/flutter/flutter.git (push)

このリポジトリをcloneするとFlutter SDKとして使える仕組みは、flutter/flutterの変更を手元で試しやすく、PRを作成しやすいというメリットにつながります。[2] このメリットを活かして、flutter/flutterへのコントリビューションの準備を進めていきましょう。


flutter/flutterのPRを作成する場合、次の手順が必要です。一部をスキップしたり追加したりすることもありますが、基本的な流れはこうなります。

  1. flutter/flutterをGitHub上でforkする
  2. forkしたリポジトリを開発環境にcloneする
  3. cloneしたリポジトリを修正する
  4. Flutter SDKのパスをクローンしたリポジトリに設定する
  5. コードの変更や動作確認を行う
  6. 修正内容をforkしたリポジトリにpushする
  7. 修正内容をPRにして提出する

ポイントはcloneしたリポジトリをFlutter SDKのパスに設定する点です。flutter runflutter testで実行されるSDKが、コードを変更したものになるため、任意のアプリやテストを実行できます。
もしもグローバルな環境をいじりたくない場合には、fvmを利用し、クローンしたリポジトリを参照できます。都度git pushを行う必要がありますが、PRの対応に長い時間を要しそうな場合には検討の余地があるかもしれません。[3]

Issueの探し方

https://github.com/flutter/flutter/issues

flutter/flutterには、多くのIssueが登録されています。flutter/packagesに関連づくIssueも登録されているため、最初は適切なIssueを探すのが難しいかもしれません。
貴重な時間を割くものでもあるので、自分のスキルや興味に合ったIssueを探すことは大切です。

Issueに関連づけられているlabelを見ることで、ある程度の絞り込みができます。初めてのIssueを探す場合には、次のようなlabelが付与されたIssueを探すと良いでしょう。

ただgood first issueは初心者向けのIssueとされていますが、「本当に初心者向け〜?」と感じるものも混じっています。一方、has reproducible stepsは再現手順が記載されているため、Issueの内容を手元で確認しやすくなっています。どうしてもIssueによって難度がバラつくので、has reproducible stepsが付与されている、関心が高かったり理解度が高い領域のものを確認するのが良いと思います。

もしも腕に覚えがある場合には、重要度の高いIssueを探すのが良いでしょう。flutter/flutterのIssueには、開発チームが重要度を付与したものがあります。

  • P0
    • Critical issues such as a build break or regression
  • P1
    • High-priority issues at the top of the work list
  • P2
    • Important issues not at the top of the work list
  • P3
    • Issues that are less important to the Flutter project

P0P1は対応が進んでいることが多いのですが、P2P3になると(手が回らないのか)対応が遅れているIssueが見つかります。例えば、記事の前半で紹介したPRに関連づけられたIssueにはP2のラベルが付与されていました。

https://github.com/flutter/flutter/issues/149099

重要なIssueを修正できれば、それだけFlutterの安定性に寄与できます。達成感もありますし、PRをマージされたときの喜びも大きいものがあります。一度P2P3のついた、自分の関心が高いWidgetや機能に関連づけられたIssueを探してみるのはいかがでしょうか? Pは難度ではなく重要度の指標であるため、(未解決なため)簡単ではないでしょうが、しかし取り組めないほど難しいものだけではないはずです。

flutter/engine

https://github.com/flutter/engine

flutter/flutterに比べると、格段に難しいのがflutter/engineです。Flutterのコア部分である描画処理などに加えて、AndroidやiOSのネイティブAPIをFlutterで利用するための実装が含まれます。このため、プラットフォーム固有の不具合を調査していると、flutter/engineをいじる必要が出てくることがあります。

https://github.com/flutter/engine/blob/main/docs/contributing/Setting-up-the-Engine-development-environment.md

flutter/engineを手元で動かすためには、上記のドキュメントに従って環境を構築する必要があります。flutter/flutterに比べると複雑なことをしなければならないため、flutter/engineの環境構築の際には、最新のドキュメントを参照することをお勧めします。この記事で扱っているのは、2024年11月ごろの情報です。

筆者が試した感想としては手順通りやればなんとかなる程度のややこしさです。ツールのダウンロードに時間が取られる面もあるので、余裕のある時に、飲み物を片手に作業するのが良いかもしれません。
筆者がmacOS上でflutter/engineをセットアップした際に感じたポイントは、以下の3つです。

  1. python3Homebrewなどでインストールする
  2. depot_toolsをドキュメントに従ってインストールする
  3. depot_toolsで導入したfetchコマンドを利用し(fetch flutter)、開発用の環境を手順通りにセットアップする

セットアップが完了すると、任意の修正を加えたFlutter SDKを利用してアプリを実行できるようになります。printデバッグなどが必要になってくるので、やはり修正難度は高めです。

androidiosを手元の環境に差し替えたい場合には、flutter runコマンドにいくつかのオプションを渡します。オプションは一見するとややこしいのですが、手元でビルドしたFlutter Engineを指定します。

https://github.com/flutter/engine/blob/main/docs/Debugging-the-engine.md

web_uiを手元の環境に差し替えたい場合には、次のドキュメントを参考にします。webの場合にはレンダラーの指定も必要となるため、少し手間がかかるはずです。

https://github.com/flutter/engine/blob/main/lib/web_ui/README.md

筆者が手元でweb_uiの環境構築を行なった際には、次のような環境変数をセットしました。[4] 普段の開発においては、これらの環境変数をコメントアウトして運用しています。

export PATH=$PATH:$HOME/depot_tools
export FLUTTER_ENGINE=$HOME/packages/engine/src
export PATH=$PATH:$HOME/packages/engine/src/flutter/lib/web_ui/dev

flutter/engineの複雑さを鑑みれば、十二分に簡単なセットアップでだと思います。とはいえflutter/engineへの修正モチベーションが高くなければ、準備をしておく必要もないと思います。

Issueの探し方

flutter/engineに関連するIssueを探そうと思って探す人はいないと思いますが、探したい人はengineを確認すると良いでしょう。
思い通りのIssueが見つからない場合には、team-enginetriaged-engineが付与されたIssueを探す手もあります。

大抵の場合、気がついたらflutter/engine側の調査や修正が必要になっていた、というケースでしょう。例えば、AndroidやiOSのキーボードと連携する機能の不具合を調査していると、EditTextUITextFieldに到達することがあります。このように、Issueが実はflutter/engineに関連していることもあるため、engineが付与されていなくともflutter/engineの調査や変更が必要になるケースがあります。

余談

flutter/flutterにマージされたPRを通知するX(旧Twitter)アカウントがあります。

https://x.com/FlutterMerge

筆者はこのアカウントをフォローしており、PRがマージされたときに通知を受け取るようにしています。マージされたPRを眺めていると、「次のバージョンにはこんな変更が入るのか」ということに気づいたり、「あの機能、ついに実装されたのか」ということに気づいたりします。また、「え、あの機能バグってたの!?」と埋もれていたバグに気づくこともあるのではと。

flutter/flutterのIssueを解決することに直接役立つわけではありませんが、コントリビューション欲を高めることができるため、フォローすることをお勧めします。

まとめ

FlutterはOSSであり、広くコントリビューションを受け入れています。この記事ではPRを中心に解説しましたが、見つけた不具合をIssueにすることもコントリビューションの一環です。
台所の包丁を研ぐような感覚で、気軽にコントリビューションしてみるのはどうでしょうか? あなたのコードが、明日のFlutterコミュニティを支えるかもしれません。

脚注
  1. 実装の難度で言えばflutter/packagesの方が低い傾向にあります。しかしメンテナー不足が影響しているのか、flutter/flutterよりも大変な印象が筆者にはあります。 ↩︎

  2. ~/flutterの中のコードを直接編集するだけで、変更を試すことができます。アプリ開発とflutter/flutterへのPRを同時に進めるには不適切なため、本格的にコントリビューションを行うためには環境を構築するべきでしょう。さっと動作チェックする分には便利なので、筆者はやりがちです。 ↩︎

  3. 筆者が調べたところ、fvmがローカルマシン内のpathを参照する仕組みはありませんでした。もしもやり方を知っている人がいれば、コメントなどで教えてください! ↩︎

  4. ~/packages/engineflutter/engineをクローンしています。 ↩︎

GitHubで編集を提案

Discussion