MyFirstTypoFix¶
はじめに¶
このチュートリアルでは、LLVMに変更を加え、それをLLVMプロジェクトに貢献するプロセスを説明します。
注意
ここに示されているコードの変更は単なる例であり、実際にLLVMプロジェクトに提出するべきものではありません。LLVMへの最初の実際の変更では、コードは異なりますが、ガイドの残りの部分は引き続き適用されます。
Clangに変更を加えますが、LLVMの他の部分の手順は同じです。行う変更は単純ですが、LLVMのビルド、テストの実行、コードレビューなどの手順について説明します。これは良い練習であり、より大きな変更を加える準備ができます。
以下を前提とします。
エディターの使い方を知っている。
基本的なC++の知識がある。
システムにソフトウェアをインストールする方法を知っている。
コマンドラインに慣れている。
gitの基本的な知識がある。
行う変更¶
Clangには無限再帰に対する警告があります。
$ echo "void foo() { foo(); }" > ~/test.cc
$ clang -c -Wall ~/test.cc
test.cc:1:12: warning: all paths through this function will call itself [-Winfinite-recursion]
これは十分に明確ですが、正確にキャッチーではありません。少し言葉遣いを改善しましょう。
test.cc:1:12: warning: to understand recursion, you must first understand recursion [-Winfinite-recursion]
依存関係¶
いくつかのツールが必要です。
git: LLVMソースコードをチェックアウトするため。
C++コンパイラ: LLVMソースコードをコンパイルするため。Clang、GCC、またはVisual Studioの最近のバージョン<host_cpp_toolchain>が必要です。
CMake: システムでLLVMをどのようにビルドするかを設定するために使用されます。
ninja: LLVMの特定の部分を(再)ビルドするためにC++コンパイラを実行します。
python: LLVMテストを実行するため。
例として、Ubuntuでは
$ sudo apt-get install git clang cmake ninja-build python
LLVMのビルド¶
チェックアウト¶
ソースコードは、1つの大きなリポジトリ(「モノレポ」)でGithubに保存されています。
ダウンロードには時間がかかる場合があります!
$ git clone https://github.com/llvm/llvm-project.git
これにより、すべてのソースコードを含む「llvm-project」というディレクトリが作成されます。(匿名でチェックアウトしても問題ありません。コミットのプッシュは、後で説明するように、異なるメカニズムを使用します。)
ワークスペースの設定¶
コードをビルドする前に、CMakeを実行してビルド方法を正確に設定する必要があります。CMakeは3つのソースからの情報を組み合わせます。
自分で選択した明示的な選択(これはデバッグビルドですか?)
システムから検出された設定(ライブラリはどこにインストールされていますか?)
プロジェクト構造(どのファイルが「clang」の一部ですか?)
まず、ビルドするディレクトリを作成します。通常、これはllvm-project/build
です。
$ mkdir llvm-project/build
$ cd llvm-project/build
次に、CMakeを実行します。
$ cmake -G Ninja ../llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=clang
すべてがうまくいけば、「テストの実行」という行が多数表示され、最終的には
Configuring done
Generating done
Build files have been written to: /path/llvm-project/build
現在のディレクトリにbuild.ninja
ファイルが表示されます。
最後のコマンドを少し分解してみましょう。
-G Ninja: ninjaを使用してビルドし、
build.ninja
ファイルを作成するようにCMakeに指示します。../llvm: これは「メイン」LLVMプロジェクトのソースへのパスです。
2つの-Dフラグは、CMake変数でCMake/プロジェクトのデフォルトを上書きします。
CMAKE_BUILD_TYPE=Release: (驚くべきことに)最も高速なオプションである最適化モードでビルドします。
デバッガーで実行する場合は、デフォルトのDebug(完全に最適化されておらず、テストの実行が10倍以上遅くなります)または中間点であるRelWithDebInfoを使用する必要があります。
アサーションは、デフォルトでは
Release
ビルドでは有効になっていません。LLVM_ENABLE_ASSERTIONS=ON
を使用して有効にすることができます。LLVM_ENABLE_PROJECTS=clang: これは、LLVM自体に加えて、ビルドに関心のあるLLVMサブプロジェクトをリストします。
clang;lldb
のように、セミコロンで区切って複数のプロジェクトをリストできます。この例では、Clangに変更を加えるため、clangのみを追加します。
最後に、llvm-project/build/compile-commands.json
のシンボリックリンク(またはコピー)をllvm-project/
に作成します。
$ ln -s build/compile_commands.json ../
(これはビルドとテストには厳密には必要ありませんが、clang-tidy、clang-query、clangdなどのツールがソースツリーで動作できるようにします)。
ビルドとテスト¶
最後に、コードをビルドできます!まずこれを行い、変更を加える前に良好な状態であることを確認することが重要です。しかし、何をビルドするのでしょうか?ninjaでは、ターゲットを指定します。clangバイナリをビルドしたいだけの場合、ターゲット名は「clang」であり、次を実行します。
$ ninja clang
最初のビルドは非常に遅くなります。Clang + LLVMは大量のコードです。ただし、インクリメンタルビルドは高速です。ninjaは、変更された部分のみを再ビルドします。最終的に完了すると、動作するclangバイナリができます。次を実行してみてください。
$ bin/clang --version
すべてのclangテストをビルドおよび実行するためのターゲットもあります。
$ ninja check-clang
これはLLVMの一般的なパターンです。check-llvmはLLVMのコアに対するすべてのチェックであり、他のプロジェクトにはcheck-lldb
、check-flang
などのターゲットがあります。
変更を加える¶
変更点¶
エラーメッセージを含むファイルを見つける必要があります。
$ git grep "all paths through this function" ..
../clang/include/clang/Basic/DiagnosticSemaKinds.td: "all paths through this function will call itself">,
DiagnosticSemaKinds.td
に表示される文字列は、Clangによって出力される文字列です。*.td
ファイルはテーブルを定義します。この場合は、clangが出力できる警告とエラー、およびそれらのメッセージのリストです。お気に入りのエディターでメッセージを更新しましょう。
$ vi ../clang/include/clang/Basic/DiagnosticSemaKinds.td
メッセージを見つけて(warn_infinite_recursive_function
の下にあるはずです)、メッセージを「再帰を理解するためには、最初に再帰を理解する必要があります」に変更します。
再度テスト¶
変更を確認するために、clangをビルドして、手動で動作することを確認できます。
$ ninja clang
$ bin/clang -c -Wall ~/test.cc
test.cc:1:12: warning: in order to understand recursion, you must first understand recursion [-Winfinite-recursion]
また、テストを実行して、何かが壊れていないことを確認する必要があります。
$ ninja check-clang
今回はビルドがはるかに高速ですが、テストの実行には同じ時間がかかることに注意してください。ninjaは、どのテストが影響を受ける可能性があるかを知らないため、すべてのテストを実行します。
********************
Failing Tests (1):
Clang :: SemaCXX/warn-infinite-recursion.cpp
まあ、それは理にかなっています…そして、テスト出力は古い文字列「call itself」を探しており、代わりに新しいメッセージを見つけていることを示唆しています。新しいテストが時間の経過と共に追加されると、同様の方法でさらに多くのテストが失敗する可能性があることに注意してください。
テストの期待値を更新して修正しましょう。
$ vi ../clang/test/SemaCXX/warn-infinite-recursion.cpp
// expected-warning{{call itself}}
(または元の警告テキストに似たもの)が表示されるすべての場所で、// expected-warning{{to understand recursion}}
に置き換えましょう。
ここで、すべてのテストを再度実行できますが、これは変更を繰り返すための遅い方法です。代わりに、特定のテストのみを再実行する方法を見つけましょう。LLVMには、主に2種類のテストがあります。
litテスト(例:
SemaCXX/warn-infinite-recursion.cpp
)。
これらは、コマンドラインツールを実行して出力を検証する凝ったシェルスクリプトです。clang/**test**/FixIt/dereference-addressof.c
のようなファイルに存在します。次のように再実行します。
$ bin/llvm-lit -v ../clang/test/SemaCXX/warn-infinite-recursion.cpp
ユニットテスト(例:
ToolingTests/ReplacementTest.CanDeleteAllText
)
これらは、LLVM関数を呼び出して結果を検証するC++プログラムです。ToolingTestsのようなスイートに存在します。次のように再実行します。
$ ninja ToolingTests && tools/clang/unittests/Tooling/ToolingTests --gtest_filter=ReplacementTest.CanDeleteAllText
ローカルにコミット¶
ローカルgitブランチに変更を保存します。これにより、変更がレビューされている間、他の作業を行うことができます。変更には、変更が行われた理由をレビューアと将来のコードの読者に説明するためのタイトルと説明が必要です。
今のところ、タイトルのみを追加します。
$ git checkout -b myfirstpatch
$ git commit -am "[clang][Diagnostic] Clarify -Winfinite-recursion message"
これで、この変更を世界に送り出す準備ができました!
[clang]
および [Diagnostic]
のプレフィックスは、タグと呼ばれるものです。このゆるい慣習は、gitログの読者に、変更がどの領域を修正しているかを伝えます。変更したモジュールのタグがわからない場合は、リポジトリのそれらの領域のコミット履歴を確認できます。
$ git log --oneline ../clang/
または、GitHubを使用する場合は、たとえば https://github.com/llvm/llvm-project/commits/main/clang を参照してください。
タグ付けは不正確な場合があるので、何を付けるか確信がなくても心配する必要はありません。レビュー担当者が必要だと判断した場合は、提案してくれるでしょう。
コードレビュー¶
レビューのための変更のアップロード¶
LLVMコードレビューはGitHubでのプルリクエストを通じて行われます。GitHubでプルリクエストを開く方法については、GitHub のドキュメントを参照してください。
レビュー担当者の検索¶
変更は、LLVMコミュニティの誰でもレビューできます。大規模で複雑な変更の場合は、レビュー担当者がLLVMのその領域の経験があり、設計目標をよく知っていることが重要です。変更の作成者は、特定のレビュー担当者を割り当てることがよくあります。git blame
および git log
は、レビューできる以前の作成者を見つけるのに役立ちます。
GitHubのボットは、LLVM周辺のさまざまな「チーム」にもタグ付けして通知します。チームメンバーは、特定の領域のコードを定期的に貢献およびレビューするため、特定の担当者を選択しない場合、誰かがあなたの変更をレビューします。
レビュープロセス¶
プルリクエストを開くと、自動化によってコメントが追加され、変更した部分に応じてサブプロジェクトのさまざまなメンバーに通知されます。
数日以内に、誰かがレビューを開始するはずです。レビュー担当者として自分自身を追加するか、単にコメントを残し始める場合があります。レビューが更新されるたびに、別のメールが届きます。詳細については、コードレビューポリシーを参照してください。
変更の更新¶
レビュー担当者のコメントに応じて変更を加える場合は、コミットを追加してブランチを更新し、llvm-project
のGitHubフォークにプッシュするだけです。すべての変更を再度読んでもらうことを期待するのではなく、レビュー担当者からのコメントに直接返信するのが最適です。
たとえば、「これを実行しました」や「この部分を実行できましたが、…について質問があります」などとコメントすることがあります。
レビューの期待¶
LLVMを長期的に持続可能な取り組みにするためには、コードが保守可能で、十分にテストされている必要があります。コードレビューは、その目標を達成するのに役立ちます。特に新しい貢献者の場合、多くの場合、プロジェクトの全体的なアーキテクチャにうまく適合しない設計上の決定に対して、何度もレビューと反発が発生することを意味します。
最初のパッチの場合、これは次のことを意味します。
親切にし、レビュー担当者も親切であることを期待してください。LLVMには、誰もが従うべき 行動規範 があります。
辛抱強く待ちましょう。新しい機能がプロジェクトのアーキテクチャにどのように適合するかを理解するには、時間がかかることがよくあります。また、人々はこれを生活の他の責任と両立させる必要があります。応答がない場合は、週に1回レビューをpingしてください。
同意できない場合は、一般的に、レビュー担当者が要求することを行うのが最善の方法です。コードの可読性を最適化しますが、レビュー担当者は判断するのに有利な立場にいます。これが正しい選択ではないと感じる場合は、コメントで尋ねるか、別のレビュー担当者を追加してセカンドオピニオンを求めることができます。
プルリクエストの承認¶
レビュー担当者が変更に満足すると、プルリクエストを承認します。マージする前に対応する必要がある、さらに細かいコメントが残される場合がありますが、この時点でレビューは完了です。マージする時が来ました!
コミットアクセス¶
プロキシによるコミット¶
これは最初の変更であるため、まだ自分でマージするアクセス権はありません。レビュー担当者はこれを知らないため、伝える必要があります!次のようなレビューにコメントを残してください。
@<レビュー担当者のユーザー名>ありがとうございます。コミットアクセス権がないので、このPRをマージしてもらえますか?
プルリクエストはクローズされ、GitHubから通知されます。
コミットアクセスの取得¶
LLVMにいくつかのパッチを貢献したら、自分でコミットアクセスを取得することを検討し始めてください。おそらく、次の場合は良いでしょう。
「タイプミスを修正する」よりも大きな範囲のパッチを3〜5つ作成した場合
自分のものと密接に関連する変更をレビューしても構わない場合
LLVMへの貢献を続けたい場合。
プロセスは、開発者ポリシー文書に記載されています。
大きな力には¶
実際、開発者ポリシーの残りの部分も読む絶好の機会です。
PRの適用後に発生する問題¶
変更が送信されると、さまざまな構成でパッチをビルドおよびテストする自動ビルドボットによってピックアップされます。
http://lab.llvm.org/buildbot/#/console の「コンソール」ビューには、特定のコミットの結果が表示されます。変更がビルドボットにどのように影響しているかを追跡したい場合は、ここを最初に確認する必要があります。
列はビルド構成、行は個々のコミットです。行に沿って色付きの泡があります。泡の色はビルドのステータスを表します。緑は合格、赤は失敗、黄色はビルドが進行中です。
赤いビルドは、変更がコミットされる前からすでに失敗している可能性があります。これは、ビルドを壊したわけではないものの、新しい問題を追加して悪化させなかったかどうかを確認する必要があることを意味します。
注意
コンソールビューには、最近の変更のみが表示されます。変更が表示されない場合は、PRコメントとビルドボットのメールを利用して、問題が発生した場合に通知を受けるようにしてください。
変更を含むビルドに問題がある場合は、メールまたはPRのコメントとしてレポートを受け取る場合があります。問題が特に変更によって引き起こされたかどうかを確認してください。ビルドには多くの作成者からの変更が含まれており、関係のないインフラストラクチャの問題が原因で失敗する場合があるためです。
ビルドの詳細を表示するには、コンソールビューで泡をクリックするか、問題レポートに記載されているリンクをクリックします。そのビルドの各段階のログを表示およびダウンロードできます。
問題の理解に助けが必要な場合や、その他の質問がある場合は、PRのコメントとして、またはDiscordで質問できます。
問題の報告がない場合は、何もする必要はありません。変更は期待どおりに機能しています。よくできました!
リバート¶
変更によって問題が発生した場合は、できるだけ早くリバートする必要があります。これは、すべてのコミッター(経験に関係なく)が経験するLLVM開発の正常な一部です。
変更をすぐに修正できるかどうか少しでも疑問がある場合は、リバートしてください。そうすれば、調査して堅実な修正を作成するための時間が十分にあります。
他の人が変更をリバートしてくれる場合もあれば、GitHubインターフェースを使用してリバートプルリクエストを作成することもできます。可能であれば、この新しいプルリクエストに元のレビュー担当者を追加してください。
結論¶
これで、LLVMプロジェクトへの貢献のライフサイクルについて理解できたはずです。
まだ不明な点がある場合は、心配しないでください。LLVMプロジェクトのプロセスは、GitHubの他の場所で慣れているものとは異なります。プロジェクト内では、異なるサブプロジェクトの期待も異なる場合があります。
そのため、何に貢献していても、完璧を期待していないことを知っておいてください。不明な場合はいつでも質問してください。何かを見落とした場合は、誰かが丁寧に指摘して対応を手伝ってくれると期待してください。
コメント¶
レビュー担当者は変更にコメントを残すことができ、あなたは返信できます。一部のコメントは特定の行に添付され、コードと交互に表示されます。これらに返信できます。おそらく、質問された内容を明確にするため、またはレビュー担当者に要求されたことを実行したことを伝えるためです。