Chromium
About
ChromiumはOSSのWebブラウザー。Google Chromeのベースコードになっている。
Base
baseディレクトリーに共通のユーティリティーなどがいろいろある。
strings
string_util.h
StartsWith/EndsWith。大文字小文字の区別もできるので便利。
base::StartsWith(label, "WOPI", base::CompareCase::INSENSITIVE_ASCII));
Bind
出典:
- Chromium Docs - Threading and Tasks in Chrome
- Chromium Docs - OnceCallback<> and BindOnce(), RepeatingCallback<> and BindRepeating()
Bindがよく登場するので整理しておく。
PostTask(FROM_HERE, base::BindOnce(cb, 42));
cbがコールバック関数。42がコールバックの引数。
int Floor(float f) { return std::floor(f); } std::string IntToString(int i) { return base::NumberToString(i); } base::OnceCallback<int(float)> first = Base::BindOnce(&Floor); base::OnceCallback<std::string(int)> second = Base::BindOnce(&IntToString);
base::BindOnce/base::BindCallbackでbase::OnceCallback/base::RepeatingCallbackを生成する。
Callbackに引数がある場合、使用するときの引数となる。Bind時の関数に、その引数受取の存在が必要になる。
バインド時に引数を設定することができる。その場合、引数の型は空にする。
void MyFunc(int i, const std::string& str) {} base::RepeatingCallback<void()> cb = Base::BindRepeating(&MyFunc, 23, "hello world"); // base::RepeatingClosure cb = Base::BindRepeating(&MyFunc, 23, "hello world"); cb.Run(); int Return5() { return 5; } base::RepeatingCallback<int()> func_cb = Base::BindRepeating(&Return5); LOG(INFO) << func_cb.Run(); // Prints 5.
バインド時にインスタンスメソッドを指定する場合は第2引数にthisなどのインスタンスを指定する。staticなどインスタンスメソッドでなければ、インスタンス指定はいらない。
引数が空の場合は、base::OnceClosureと同じ意味になる。つまり、以下は同一。
base::RepeatingCallback<void()> base::RepeatingClosure<void>
部分的に引数を指定することもできる。例えば、コールバック呼出し時には引数を使いたいが、割り当て時に引数を指定したい時など。
void ReadIntFromFile(const std::string& filename, base::OnceCallback<void(int)> on_read); void DisplayIntWithPrefix(const std::string& prefix, int result) { LOG(INFO) << prefix << result; } void AnotherFunc(const std::string& file) { ReadIntFromFile(file, base::BindOnce(&DisplayIntWithPrefix, "MyPrefix: ")); };
上記の例だと、コールバックon_readの呼び出し時に引数にintを使用するが、このコールバックの元関数DisplayIntWithPrefixバインド時に第1引数に文字列を設定している。RepeatingCallback/BIndRepeatingは何回も実行できるから、std::moveで渡すのではなく、コピー渡しにする必要がある。 例が分かりにくい。
base/callback.hがわかりやすい。
// // The lambda takes two arguments, but the first argument |x| is bound at // // callback creation. // base::OnceCallback<int(int)> cb = base::BindOnce([] (int x, int y) { // return x + y; // }, 1); // // Run() only needs the remaining unbound argument |y|. // printf("1 + 2 = %d\n", std::move(cb).Run(2)); // Prints 3 // printf("cb is null? %s\n", // cb.is_null() ? "true" : "false"); // Prints true // std::move(cb).Run(2); // Crashes since |cb| has already run.
OnceCallback/RepeatingCallbackの引数は、[返却型(引数の型)] の書式になる。
Repeating→Onceにはそのまま暗黙に変換できる。逆はできない。
BindRepeatingの関数内で、std::moveしたいなら、引数に渡す際にはstd::refにする。違う。こうしないとクラッシュする。
std::move(cb).Run() }, base::OwnedRef(std::move(cb))
この引数が曲者。
単に変更可能な参照を渡す場合はstd::ref。コピーや既存値の移譲など、値の所有権が必要な場合、base::OwnedRefを使う。
base::BindRepeating/base::BindOnceは右辺値として渡されると、内部ストレージへパラメーターを移譲する。base::BindOnceは問答無用で移譲するが、base::BindRepeatingはbase::Passedを使用したときだけ。
base::BindOnceではstd::move/base::BindRepeatingではbase::Passedで1回だけの処理のパラメーターを移譲する。
- std::move
- base::Passed: base::BIndRepeatingでの1回だけのパラメーターの移譲。
- base::Owned: コールバック削除時にパラメーターも削除。
- std::ref: 単に変更可能な参照を渡す場合。
- base::OwnedRef: コピーや既存値の移譲など、値の所有権が必要な場合。
- base::Unretained
- base::RetainedRef: 参照を保持し、コールバック実行時に生ポインターを渡す。
Bindする際にラムダ式で関数を生成する場合、キャプチャーは使えない。使おうとするとコンパイルエラーになる。変数を参照したい場合、Bind時に引数を渡してClosureなどにする。
Debug
Logging
ChromiumはLOG/DLOGとVLOG/DVLOGの2系統のログ出力マクロが用意されている。それぞれ対応するオプションが異なる。VLOG/DVLOGが新しくて推奨されている。
情報源
- Chromium Docs - Tips for debugging on Linux
- How to enable logging
- base/logging.h - chromium/src - Git at Google
DLOG/DVLOGはis_debug=trueのときのみ有効になる。
- --log-level=0: LOG/DLOGの出力ログの制御。
- --v=0: VLOG/DVLOGの出力ログの制御。
- --enable-logging: is_debug=falseでもログ出力する?
Stacktrace
以下のようなコードでスタックトレースを出力できる (ChromiumOS Docs - How to get a stack trace at runtime for debugging purposes)。
#include "base/logging.h" #include "base/debug/stack_trace.h" LOG(ERROR) << base::debug::StackTrace(); base::debug::StackTrace().Print(); // stderr
CHECK/DCHECK
assert用のマクロがある (Chromium C++ style guide)。
DCHECKはDCHECK_IS_ONがtrueの場合にコンパイルされる。基本はこれを使う。
Option
起動オプションは [content/public/common/content_switches.cc - chromium/src - Git at Google] のソースコードにある。
GN
情報源:
GNはChromiumで採用されているBUILD.gnのビルド設定記述言語。
GN build configuration
情報源: Chromium - GN build configuration。
Chromiumのargs.gnのビルド設定で使用できる設定がいくつかある。
- is_debug=false
- dcheck_always_on=true
- is_component_build
- symol_level
- enable_nacl
- remove_webcore_debug_symbols
- target_cpu
- use_goma
- is_official_build
- is_chrome_branded
Targets
[target] というのがあって、これがビルドグラフのノードになる。一般的には、生成物のバイナリー、ライブラリーを指す。targetは別のtargetに依存する。組み込みのtargetは以下となる。gn help <targettype> で細かい情報を確認できる。
- action
- action_foreach
- bundle_data
- create_bundle
- executable
- group: targetのグループ。
- shared_library
- loadable_module
- source_set: 軽量仮想静的ライブラリー。
- static_library: .lib/.aファイル (source_setを使ったほうがいい)。
templateを使うことでカスタムtargetタイプを作れる。Chromeでは以下のtemplateを使っている。
- component: ビルドタイプに応じたsource_setかshred_library。
Variable
Configs
[configs] は名前付きオブジェクト。ディレクトリーやdefineを含むフラグの集合を指定する。[target] に適用され、依存targetに押し込まれる。
以下のように定義する。
config("myconfig") { includes = [ "src/include" ] defines = [ "ENABLE_DOOM_MELON" ] }
targetへのconfigの適用には以下のようにする。
executable("doom_melon") { configs = [ ":myconfig" ] }
一般的に、configs += “:myconfig” でデフォルトのリストに追記する。
deps
targetにリンクされる依存関係。
Public configs
targetは依存している他のtargetに設定を適用できる。もっとも一般的な例はサードパーティーtargetだ。適切なコンパイルのためのヘッダーのためのdefineやディレクトリーincludeを必要とする。サードパーティーライブラリーと同様に、そのサードパーティーライブラリーを使用するtargetもコンパイルのために、設定を適用したいでしょう。
このために、適用したい設定のconfigを以下のように書く。
config("my_external_library_config") { includes = "." defines = [ "DISABLE_JANK" ] }
それから、以下の記述でこのconfigはpublic configとしてtargetに追加される。これは依存しているtargetと同様にtargetにも両方に適用する。
shared_library("my_external_library") { ... # Targets that depend on this get this config applied. public_configs = [ ":my_external_library_config" ] }
依存targetは、public_depsとしてあなたのtargetに追加することで、他の依存ツリーレベルを前倒しできる。
static_library("intermediate_library") { ... # Targets that depend on this one also get the configs from "my external library". public_deps = [ ":my_external_library" ] }
targetは全依存物にconfigを進められる。all_dependent_configとしての設定のリンク境界に達するまで。これは推奨しない。代わりに、フラグの適用場所の制御にはpublic_depsを使う。
Chromeには、build/buildflag_header.gniのビルドフラグヘッダーシステムがある。コンパイラーdefineのdefineのために。
わかりにくいので整理する。
- public_configs: targetと依存targetの両方に指定したconfigが適用される。
- public_deps: targetと依存targetの両方に指定したtargetのconfigが適用される。
public_configsがconfig同士なのに対し、public_depsはtarget同士になる。基本はpublic_configsだろうか。
sources
target用のソースファイルのリスト。