構成可能な属性(一般に select() と呼ばれます)は、コマンドラインでビルドルール属性の値を切り替えることができる Bazel の機能です。
たとえば、アーキテクチャに適した実装を自動的に 選択するマルチプラットフォーム ライブラリや、 ビルド時にカスタマイズできる機能構成可能なバイナリに使用できます。
例
# myapp/BUILD
cc_binary(
name = "mybinary",
srcs = ["main.cc"],
deps = select({
":arm_build": [":arm_lib"],
":x86_debug_build": [":x86_dev_lib"],
"//conditions:default": [":generic_lib"],
}),
)
config_setting(
name = "arm_build",
values = {"cpu": "arm"},
)
config_setting(
name = "x86_debug_build",
values = {
"cpu": "x86",
"compilation_mode": "dbg",
},
)
これは、コマンドラインのフラグに基づいて依存関係を「選択」する cc_binary を宣言します。具体的には、deps は次のようになります。
| コマンド | deps = |
bazel build //myapp:mybinary --cpu=arm |
[":arm_lib"] |
bazel build //myapp:mybinary -c dbg --cpu=x86 |
[":x86_dev_lib"] |
bazel build //myapp:mybinary --cpu=ppc |
[":generic_lib"] |
bazel build //myapp:mybinary -c dbg --cpu=ppc |
[":generic_lib"] |
select() は、
構成条件に基づいて選択される値のプレースホルダとして機能します。構成条件は、config_setting
ターゲットを参照するラベルです。構成可能な属性で select() を使用すると、属性
条件が異なる場合に異なる値を採用します。
一致は明確でなければなりません。複数の条件が一致する場合は、次のいずれかになります。
- すべて同じ値に解決される。たとえば、Linux x86 で実行する場合、両方のブランチが「hello」に解決されるため、これは明確です
{"@platforms//os:linux": "Hello", "@platforms//cpu:x86_64": "Hello"}。 - 1 つの
valuesが他のすべての厳密なスーパーセットである。たとえば、values = {"cpu": "x86", "compilation_mode": "dbg"}はvalues = {"cpu": "x86"}の明確な特殊化です。
組み込み条件 //conditions:default は、
他に一致するものがない場合に自動的に一致します。
この例では deps を使用していますが、select() は srcs、
resources、cmd、その他のほとんどの属性でも同様に機能します。属性の数はごくわずかですが、
構成できないものもあり、これらは明確にアノテーションが付けられています。たとえば、
config_setting's 独自の
values 属性は構成できません。
select() と依存関係
特定の属性は、ターゲットの下にあるすべての推移的依存関係
のビルド パラメータを変更します。たとえば、genrule's tools は、--cpu を
Bazel を実行しているマシンの CPU に変更します(クロスコンパイルにより、ターゲットのビルド対象の CPU と異なる場合があります)。これは構成の移行と呼ばれます。
次の場合
#myapp/BUILD
config_setting(
name = "arm_cpu",
values = {"cpu": "arm"},
)
config_setting(
name = "x86_cpu",
values = {"cpu": "x86"},
)
genrule(
name = "my_genrule",
srcs = select({
":arm_cpu": ["g_arm.src"],
":x86_cpu": ["g_x86.src"],
}),
tools = select({
":arm_cpu": [":tool1"],
":x86_cpu": [":tool2"],
}),
)
cc_binary(
name = "tool1",
srcs = select({
":arm_cpu": ["armtool.cc"],
":x86_cpu": ["x86tool.cc"],
}),
)
実行中
$ bazel build //myapp:my_genrule --cpu=arm
x86 開発マシンでは、ビルドが g_arm.src、tool1、
x86tool.cc にバインドされます。my_genrule にアタッチされた両方の select は、my_genrule の
ビルド パラメータ(--cpu=arm を含む)を使用します。The tools 属性は、tool1 とその推移的依存関係の
--cpu を x86 に変更します。
tool1 の select は、tool1 のビルド パラメータ(--cpu=x86 を含む)を使用します。
構成条件
構成可能な属性の各キーは、
config_setting または
constraint_value へのラベル参照です。
config_setting は、
想定されるコマンドライン フラグ設定のコレクションにすぎません。これらをターゲットにカプセル化することで、
ユーザーが複数の場所から参照できる「標準」条件を簡単に維持できます。
constraint_value は、マルチプラットフォームの動作をサポートします。
組み込みフラグ
--cpu などのフラグは Bazel に組み込まれています。ビルドツールは、すべてのプロジェクトのすべてのビルドでネイティブに認識します。これらは、
config_setting の
values 属性で指定します。
config_setting(
name = "meaningful_condition_name",
values = {
"flag1": "value1",
"flag2": "value2",
...
},
)
flagN はフラグ名です(-- なし。"--cpu" ではなく "cpu")。valueN
は、そのフラグの想定される値です。values のすべてのエントリが一致する場合、:meaningful_condition_name が一致します。順序は関係ありません。
valueN は、コマンドラインで設定された場合と同様に解析されます。具体的には、次のようになります。
values = { "compilation_mode": "opt" }はbazel build -c optと一致します。values = { "force_pic": "true" }はbazel build --force_pic=1と一致します。values = { "force_pic": "0" }はbazel build --noforce_picと一致します。
config_setting は、ターゲットの動作に影響するフラグのみをサポートします。たとえば、
--show_progress は、
Bazel がユーザーに進捗状況を報告する方法にのみ影響するため、使用できません。ターゲットはその
フラグを使用して結果を構築できません。サポートされているフラグの正確なセットは
ドキュメントに記載されていません。実際には、「意味のある」ほとんどのフラグが機能します。
カスタムフラグ
Starlark ビルド設定 を使用して、プロジェクト固有のフラグをモデル化できます。組み込みフラグとは異なり、これらは ビルドターゲットとして定義されるため、Bazel はターゲット ラベルで参照します。
これらは、config_setting's
flag_values
属性でトリガーされます。
config_setting(
name = "meaningful_condition_name",
flag_values = {
"//myflags:flag1": "value1",
"//myflags:flag2": "value2",
...
},
)
動作は組み込みフラグと同じです。有効な例については、こちら をご覧ください。
--define
は、カスタムフラグの代替のレガシー構文です(たとえば
--define foo=bar)。これは、
values 属性
(values = {"define": "foo=bar"})または
define_values 属性
(define_values = {"foo": "bar"})で表すことができます。--define は、下位互換性のみをサポートしています。可能な限り Starlark ビルド設定を使用してください。
values、flag_values、define_values は個別に評価されます。
config_setting は、すべての値が一致する場合に一致します。
デフォルト条件
組み込み条件 //conditions:default は、他に一致する条件
が一致する場合に一致します。
「完全に一致する」ルールにより、一致する条件がなく
デフォルト条件もない構成可能な属性は、"no matching conditions"エラーを生成します。これにより、
予期しない設定によるサイレント障害を防ぐことができます。
# myapp/BUILD
config_setting(
name = "x86_cpu",
values = {"cpu": "x86"},
)
cc_library(
name = "x86_only_lib",
srcs = select({
":x86_cpu": ["lib.cc"],
}),
)
$ bazel build //myapp:x86_only_lib --cpu=arm
ERROR: Configurable attribute "srcs" doesn't match this configuration (would
a default condition help?).
Conditions checked:
//myapp:x86_cpu
エラーをさらに明確にするには、select()'s
no_match_error 属性を使用してカスタム メッセージを設定します。
プラットフォーム
コマンドラインで複数のフラグを指定できるため 柔軟性が向上しますが、ターゲットをビルドするたびに各フラグを個別に設定するのは面倒な場合があります。 プラットフォーム を使用すると、これらをシンプルなバンドルに統合できます。
# myapp/BUILD
sh_binary(
name = "my_rocks",
srcs = select({
":basalt": ["pyroxene.sh"],
":marble": ["calcite.sh"],
"//conditions:default": ["feldspar.sh"],
}),
)
config_setting(
name = "basalt",
constraint_values = [
":black",
":igneous",
],
)
config_setting(
name = "marble",
constraint_values = [
":white",
":metamorphic",
],
)
# constraint_setting acts as an enum type, and constraint_value as an enum value.
constraint_setting(name = "color")
constraint_value(name = "black", constraint_setting = "color")
constraint_value(name = "white", constraint_setting = "color")
constraint_setting(name = "texture")
constraint_value(name = "smooth", constraint_setting = "texture")
constraint_setting(name = "type")
constraint_value(name = "igneous", constraint_setting = "type")
constraint_value(name = "metamorphic", constraint_setting = "type")
platform(
name = "basalt_platform",
constraint_values = [
":black",
":igneous",
],
)
platform(
name = "marble_platform",
constraint_values = [
":white",
":smooth",
":metamorphic",
],
)
プラットフォームはコマンドラインで指定できます。これにより、プラットフォームの constraint_values のサブセットを含む
config_setting が有効になり、これらの config_setting が select() 式で一致するようになります。
たとえば、my_rocks の srcs 属性を calcite.sh に設定するには、
次のコマンドを実行します。
bazel build //my_app:my_rocks --platforms=//myapp:marble_platform
プラットフォームがない場合、次のようになります。
bazel build //my_app:my_rocks --define color=white --define texture=smooth --define type=metamorphic
select() は constraint_value を直接読み取ることもできます。
constraint_setting(name = "type")
constraint_value(name = "igneous", constraint_setting = "type")
constraint_value(name = "metamorphic", constraint_setting = "type")
sh_binary(
name = "my_rocks",
srcs = select({
":igneous": ["igneous.sh"],
":metamorphic" ["metamorphic.sh"],
}),
)
これにより、単一の値に対してのみチェックする必要がある場合に、ボイラープレート config_setting が不要になります。
プラットフォームはまだ開発中です。詳しくは ドキュメントをご覧ください。
select() の組み合わせ
select は、同じ属性に複数回表示できます。
sh_binary(
name = "my_target",
srcs = ["always_include.sh"] +
select({
":armeabi_mode": ["armeabi_src.sh"],
":x86_mode": ["x86_src.sh"],
}) +
select({
":opt_mode": ["opt_extras.sh"],
":dbg_mode": ["dbg_extras.sh"],
}),
)
select は別の select の内部に表示できません。selects
をネストする必要があり、属性が他のターゲットを値として受け取る場合は、中間ターゲットを使用します。
sh_binary(
name = "my_target",
srcs = ["always_include.sh"],
deps = select({
":armeabi_mode": [":armeabi_lib"],
...
}),
)
sh_library(
name = "armeabi_lib",
srcs = select({
":opt_mode": ["armeabi_with_opt.sh"],
...
}),
)
複数の条件が一致した場合に select を一致させる必要がある場合は、AND
チェーンを検討してください。
OR チェーン
次の点を考慮してください。
sh_binary(
name = "my_target",
srcs = ["always_include.sh"],
deps = select({
":config1": [":standard_lib"],
":config2": [":standard_lib"],
":config3": [":standard_lib"],
":config4": [":special_lib"],
}),
)
ほとんどの条件は同じ依存関係に評価されます。ただし、この構文は読みにくく、保守が困難です。
[":standard_lib"] を何度も繰り返す必要がないと便利です。
1 つの方法は、値を BUILD 変数として事前定義することです。
STANDARD_DEP = [":standard_lib"]
sh_binary(
name = "my_target",
srcs = ["always_include.sh"],
deps = select({
":config1": STANDARD_DEP,
":config2": STANDARD_DEP,
":config3": STANDARD_DEP,
":config4": [":special_lib"],
}),
)
これにより、依存関係の管理が容易になります。ただし、不要な 重複が発生します。
より直接的なサポートについては、次のいずれかを使用します。
selects.with_or
Skylib の `selects` モジュールの
with_or
マクロは、selects
モジュール内で条件を直接 ORすることをサポートしていますselect。
load("@bazel_skylib//lib:selects.bzl", "selects")
sh_binary(
name = "my_target",
srcs = ["always_include.sh"],
deps = selects.with_or({
(":config1", ":config2", ":config3"): [":standard_lib"],
":config4": [":special_lib"],
}),
)
selects.config_setting_group
Skylib の `selects` モジュールの
config_setting_group
マクロは、複数の config_setting の OR をサポートしています。selects
load("@bazel_skylib//lib:selects.bzl", "selects")
config_setting(
name = "config1",
values = {"cpu": "arm"},
)
config_setting(
name = "config2",
values = {"compilation_mode": "dbg"},
)
selects.config_setting_group(
name = "config1_or_2",
match_any = [":config1", ":config2"],
)
sh_binary(
name = "my_target",
srcs = ["always_include.sh"],
deps = select({
":config1_or_2": [":standard_lib"],
"//conditions:default": [":other_lib"],
}),
)
selects.with_or とは異なり、異なるターゲットは異なる属性間で :config1_or_2 を共有できます。
複数の条件が一致する場合、1 つが他の条件の明確な 「特殊化」であるか、すべて同じ値に解決されない限り、エラーになります。詳しくはこちらをご覧ください。
AND チェーン
複数の条件が一致した場合に select ブランチを一致させる必要がある場合は、
Skylib マクロ
config_setting_group を使用します。
config_setting(
name = "config1",
values = {"cpu": "arm"},
)
config_setting(
name = "config2",
values = {"compilation_mode": "dbg"},
)
selects.config_setting_group(
name = "config1_and_2",
match_all = [":config1", ":config2"],
)
sh_binary(
name = "my_target",
srcs = ["always_include.sh"],
deps = select({
":config1_and_2": [":standard_lib"],
"//conditions:default": [":other_lib"],
}),
)
OR チェーンとは異なり、既存の config_setting を ANDed
select 内で直接行うことはできません。明示的に config_setting_group でラップする必要があります。
カスタム エラー メッセージ
デフォルトでは、条件が一致しない場合、select() がアタッチされているターゲットは
次のエラーで失敗します。
ERROR: Configurable attribute "deps" doesn't match this configuration (would
a default condition help?).
Conditions checked:
//tools/cc_target_os:darwin
//tools/cc_target_os:android
これは、no_match_error
属性でカスタマイズできます。
cc_library(
name = "my_lib",
deps = select(
{
"//tools/cc_target_os:android": [":android_deps"],
"//tools/cc_target_os:windows": [":windows_deps"],
},
no_match_error = "Please build with an Android or Windows toolchain",
),
)
$ bazel build //myapp:my_lib
ERROR: Configurable attribute "deps" doesn't match this configuration: Please
build with an Android or Windows toolchain
ルールの互換性
ルール実装は、構成可能な 属性の解決された値を受け取ります。と定義した場合:
# myapp/BUILD
some_rule(
name = "my_target",
some_attr = select({
":foo_mode": [":foo"],
":bar_mode": [":bar"],
}),
)
$ bazel build //myapp/my_target --define mode=foo
ルール実装コードは ctx.attr.some_attr を [":foo"] として認識します。
マクロは select() 句を受け取り、ネイティブ
ルールに渡すことができます。ただし、直接操作することはできません。たとえば、マクロで
select({"foo": "val"}, ...)
に変換する方法はありません。
select({"foo": "val_with_suffix"}, ...)
これには 2 つの理由があります。
まず、select が選択するパスを把握する必要があるマクロは、機能しません。
マクロは Bazel の 読み込みフェーズで評価されます。
このフェーズは、フラグの値が判明する前に行われます。
これは Bazel の設計上の制限であり、すぐに変更される可能性は低いでしょう。
2 つ目は、すべての select パスを反復処理するだけでよいマクロは、
技術的には可能ですが、一貫した UI がありません。これを変更するには、さらなる設計が必要です
。
Bazel クエリと cquery
Bazel query は Bazel's
読み込みフェーズで動作します。
つまり、ターゲットが使用するコマンドライン フラグは、ビルドの後半(
分析フェーズ)まで評価されないため、認識されません。
そのため、選択される select() ブランチを特定できません。
Bazel cquery は Bazel の分析フェーズの後に動作するため、このすべての情報があり、select() を正確に解決できます。
検討事項:
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
# myapp/BUILD
string_flag(
name = "dog_type",
build_setting_default = "cat"
)
cc_library(
name = "my_lib",
deps = select({
":long": [":foo_dep"],
":short": [":bar_dep"],
}),
)
config_setting(
name = "long",
flag_values = {":dog_type": "dachshund"},
)
config_setting(
name = "short",
flag_values = {":dog_type": "pug"},
)
query は :my_lib の依存関係を過大評価します。
$ bazel query 'deps(//myapp:my_lib)'
//myapp:my_lib
//myapp:foo_dep
//myapp:bar_dep
cquery は正確な依存関係を示します。
$ bazel cquery 'deps(//myapp:my_lib)' --//myapp:dog_type=pug
//myapp:my_lib
//myapp:bar_dep
よくある質問
マクロで select() が機能しないのはなぜですか?
select() はルールで機能します。詳しくは、ルールの互換性をご覧ください 。
この質問の主な問題は、select() が マクロで機能しないことです。これらはルールとは異なります。違いについては、 ルールとマクロ に関するドキュメントをご覧ください。 エンドツーエンドの例を次に示します。
ルールとマクロを定義します。
# myapp/defs.bzl
# Rule implementation: when an attribute is read, all select()s have already
# been resolved. So it looks like a plain old attribute just like any other.
def _impl(ctx):
name = ctx.attr.name
allcaps = ctx.attr.my_config_string.upper() # This works fine on all values.
print("My name is " + name + " with custom message: " + allcaps)
# Rule declaration:
my_custom_bazel_rule = rule(
implementation = _impl,
attrs = {"my_config_string": attr.string()},
)
# Macro declaration:
def my_custom_bazel_macro(name, my_config_string):
allcaps = my_config_string.upper() # This line won't work with select(s).
print("My name is " + name + " with custom message: " + allcaps)
ルールとマクロをインスタンス化します。
# myapp/BUILD
load("//myapp:defs.bzl", "my_custom_bazel_rule")
load("//myapp:defs.bzl", "my_custom_bazel_macro")
my_custom_bazel_rule(
name = "happy_rule",
my_config_string = select({
"//third_party/bazel_platforms/cpu:x86_32": "first string",
"//third_party/bazel_platforms/cpu:ppc": "second string",
}),
)
my_custom_bazel_macro(
name = "happy_macro",
my_config_string = "fixed string",
)
my_custom_bazel_macro(
name = "sad_macro",
my_config_string = select({
"//third_party/bazel_platforms/cpu:x86_32": "first string",
"//third_party/bazel_platforms/cpu:ppc": "other string",
}),
)
sad_macro が select() を処理できないため、ビルドが失敗します。
$ bazel build //myapp:all
ERROR: /myworkspace/myapp/BUILD:17:1: Traceback
(most recent call last):
File "/myworkspace/myapp/BUILD", line 17
my_custom_bazel_macro(name = "sad_macro", my_config_stri..."}))
File "/myworkspace/myapp/defs.bzl", line 4, in
my_custom_bazel_macro
my_config_string.upper()
type 'select' has no method upper().
ERROR: error loading package 'myapp': Package 'myapp' contains errors.
sad_macro をコメントアウトすると、ビルドは成功します。
# Comment out sad_macro so it doesn't mess up the build.
$ bazel build //myapp:all
DEBUG: /myworkspace/myapp/defs.bzl:5:3: My name is happy_macro with custom message: FIXED STRING.
DEBUG: /myworkspace/myapp/hi.bzl:15:3: My name is happy_rule with custom message: FIRST STRING.
マクロは、定義上 Bazel がビルドのコマンドライン フラグを読み取る前に 評価されるため、これを変更することはできません。つまり、select() を評価するのに十分な情報がありません。
ただし、マクロは select() を不透明な blob としてルールに渡すことができます。
# myapp/defs.bzl
def my_custom_bazel_macro(name, my_config_string):
print("Invoking macro " + name)
my_custom_bazel_rule(
name = name + "_as_target",
my_config_string = my_config_string,
)
$ bazel build //myapp:sad_macro_less_sad
DEBUG: /myworkspace/myapp/defs.bzl:23:3: Invoking macro sad_macro_less_sad.
DEBUG: /myworkspace/myapp/defs.bzl:15:3: My name is sad_macro_less_sad with custom message: FIRST STRING.
select() が常に true を返すのはなぜですか?
マクロ(ルールではない)は定義上
を評価できないため、通常はエラーが発生します。select()
ERROR: /myworkspace/myapp/BUILD:17:1: Traceback
(most recent call last):
File "/myworkspace/myapp/BUILD", line 17
my_custom_bazel_macro(name = "sad_macro", my_config_stri..."}))
File "/myworkspace/myapp/defs.bzl", line 4, in
my_custom_bazel_macro
my_config_string.upper()
type 'select' has no method upper().
ブール値はサイレントに失敗する特殊なケースであるため、特に 注意する必要があります。
$ cat myapp/defs.bzl
def my_boolean_macro(boolval):
print("TRUE" if boolval else "FALSE")
$ cat myapp/BUILD
load("//myapp:defs.bzl", "my_boolean_macro")
my_boolean_macro(
boolval = select({
"//third_party/bazel_platforms/cpu:x86_32": True,
"//third_party/bazel_platforms/cpu:ppc": False,
}),
)
$ bazel build //myapp:all --cpu=x86
DEBUG: /myworkspace/myapp/defs.bzl:4:3: TRUE.
$ bazel build //mypro:all --cpu=ppc
DEBUG: /myworkspace/myapp/defs.bzl:4:3: TRUE.
これは、マクロが select() の内容を認識しないために発生します。
そのため、実際に評価しているのは select() オブジェクト自体です。Pythonic 設計標準では、ごく一部の例外を除き、すべてのオブジェクトが自動的に true を返します。
select() を辞書のように読み取ることはできますか?
マクロは、Bazel がビルドのコマンドライン パラメータを認識する前に評価されるため、select() を評価できません。少なくとも
select()の辞書を読み取って、各値に接尾辞を追加することはできますか?
概念的には可能ですが、まだ Bazel の機能ではありません。
現在できることは、ストレートな辞書を用意して、それにフィードすることです
select()。
$ cat myapp/defs.bzl
def selecty_genrule(name, select_cmd):
for key in select_cmd.keys():
select_cmd[key] += " WITH SUFFIX"
native.genrule(
name = name,
outs = [name + ".out"],
srcs = [],
cmd = "echo " + select(select_cmd + {"//conditions:default": "default"})
+ " > $@"
)
$ cat myapp/BUILD
selecty_genrule(
name = "selecty",
select_cmd = {
"//third_party/bazel_platforms/cpu:x86_32": "x86 mode",
},
)
$ bazel build //testapp:selecty --cpu=x86 && cat bazel-genfiles/testapp/selecty.out
x86 mode WITH SUFFIX
select() とネイティブ型の両方をサポートする場合は、次の操作を行います。
$ cat myapp/defs.bzl
def selecty_genrule(name, select_cmd):
cmd_suffix = ""
if type(select_cmd) == "string":
cmd_suffix = select_cmd + " WITH SUFFIX"
elif type(select_cmd) == "dict":
for key in select_cmd.keys():
select_cmd[key] += " WITH SUFFIX"
cmd_suffix = select(select_cmd + {"//conditions:default": "default"})
native.genrule(
name = name,
outs = [name + ".out"],
srcs = [],
cmd = "echo " + cmd_suffix + "> $@",
)
select() が bind() で機能しないのはなぜですか?
まず、bind() は使用しないでください。alias() が推奨されています。
技術的な答えは、bind() はリポジトリ
ルールではなく、BUILD ルールであるということです。
リポジトリ ルールには特定の構成がなく、BUILD ルールと同じ方法で評価されません。したがって、select() の bind() は、特定のブランチに評価できません。
代わりに、alias() を使用し、select() を
actual 属性に使用して、このタイプのランタイム判定を行います。This
は BUILD ルールであり、特定の構成で評価されるため、正しく機能します。alias()
必要に応じて、bind() ターゲットを alias() にポイントすることもできます。
$ cat WORKSPACE
workspace(name = "myapp")
bind(name = "openssl", actual = "//:ssl")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(name = "alternative", ...)
http_archive(name = "boringssl", ...)
$ cat BUILD
config_setting(
name = "alt_ssl",
define_values = {
"ssl_library": "alternative",
},
)
alias(
name = "ssl",
actual = select({
"//:alt_ssl": "@alternative//:ssl",
"//conditions:default": "@boringssl//:ssl",
}),
)
この設定では、--define ssl_library=alternative を渡すと、//:ssl または //external:ssl に依存するターゲットは、@alternative//:ssl にある代替が表示されます。
ただし、bind() の使用は中止してください。
select() が想定どおりに選択されないのはなぜですか?
//myapp:foo に、想定どおりの条件を選択しない select() がある場合は、
cquery と bazel config を使用してデバッグします。
ビルドする最上位のターゲットが //myapp:foo の場合は、次のコマンドを実行します。
$ bazel cquery //myapp:foo <desired build flags>
//myapp:foo (12e23b9a2b534a)
サブグラフのどこかで
//myapp:foo に依存する別のターゲット //bar をビルドする場合は、次のコマンドを実行します。
$ bazel cquery 'somepath(//bar, //myapp:foo)' <desired build flags>
//bar:bar (3ag3193fee94a2)
//bar:intermediate_dep (12e23b9a2b534a)
//myapp:foo (12e23b9a2b534a)
//myapp:foo の横にある (12e23b9a2b534a) は、//myapp:foo の select() を解決する
構成のハッシュです。bazel config で値を確認できます。
$ bazel config 12e23b9a2b534a
BuildConfigurationValue 12e23b9a2b534a
Fragment com.google.devtools.build.lib.analysis.config.CoreOptions {
cpu: darwin
compilation_mode: fastbuild
...
}
Fragment com.google.devtools.build.lib.rules.cpp.CppOptions {
linkopt: [-Dfoo=bar]
...
}
...
次に、この出力を各 config_setting で想定される設定と比較します。
//myapp:foo は、同じビルド内の異なる構成に存在する可能性があります。適切なものを取得するための somepath の使用方法については、
cquery のドキュメントをご覧ください。
select() がプラットフォームで機能しないのはなぜですか?
Bazel は、特定のプラットフォーム がターゲット プラットフォームであるかどうかを確認する構成可能な属性をサポートしていません。セマンティクスが不明確なためです。
次に例を示します。
platform(
name = "x86_linux_platform",
constraint_values = [
"@platforms//cpu:x86",
"@platforms//os:linux",
],
)
cc_library(
name = "lib",
srcs = [...],
linkopts = select({
":x86_linux_platform": ["--enable_x86_optimizations"],
"//conditions:default": [],
}),
)
この BUILD ファイルで、ターゲット プラットフォームに
@platforms//cpu:x86 と @platforms//os:linux の両方の制約があるが、ここで定義されている
:x86_linux_platform ではない場合、どの select() を使用する必要がありますか?BUILD ファイルの作成者と、別のプラットフォームを定義したユーザーは、異なる考えを持っている可能性があります。
あれば教えてください。
代わりに、これらの制約を持つ任意のプラットフォームに一致する config_setting を定義します。
config_setting(
name = "is_x86_linux",
constraint_values = [
"@platforms//cpu:x86",
"@platforms//os:linux",
],
)
cc_library(
name = "lib",
srcs = [...],
linkopts = select({
":is_x86_linux": ["--enable_x86_optimizations"],
"//conditions:default": [],
}),
)
このプロセスでは特定のセマンティクスが定義されるため、目的の条件を満たすプラットフォームをユーザーが明確に把握できます。
どうしてもプラットフォームで select したい場合はどうすればよいですか?
ビルド要件でプラットフォームの確認が特に必要な場合は、
--platforms フラグの値を config_setting で反転させることができます。
config_setting(
name = "is_specific_x86_linux_platform",
values = {
"platforms": ["//package:x86_linux_platform"],
},
)
cc_library(
name = "lib",
srcs = [...],
linkopts = select({
":is_specific_x86_linux_platform": ["--enable_x86_optimizations"],
"//conditions:default": [],
}),
)
Bazel チームはこれをおすすめしません。ビルドが過度に制約され、 想定される条件が一致しない場合にユーザーが混乱します。