可設定屬性 (通常稱為 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
追蹤 Deployment
指令列具體來說,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 上執行時,這會是明確的 {"@platforms//os:linux": "Hello", "@platforms//cpu:x86_64": "Hello"}
,因為兩個分支都會解析為「hello」。* 一個 values
是所有其他 values
的嚴格超集。例如:values = {"cpu": "x86", "compilation_mode": "dbg"}
是 values = {"cpu": "x86"}
的明確專業認證。
系統會在下列情況自動比對內建條件 //conditions:default
不會產生其他影響
雖然這個範例使用 deps
,但 select()
同樣適用於 srcs
、resources
、cmd
和大多數其他屬性。只有少數屬性是不可設定的,且這些屬性會清楚標註。舉例來說,config_setting
本身的 values
屬性無法設定。
select()
和依附元件
某些屬性會變更目標下所有傳遞依附元件的建構參數。舉例來說,genrule
的 tools
會將 --cpu
變更為
執行 Bazel 的機器 (由於跨平台程式碼編譯)
而非該目標所需的 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
。tools
屬性會將 --cpu
變更為 x86
,適用於 tool1
及其遞移依附元件。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
的
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()
的 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",
],
)
您可以透過指令列指定平台。它會啟動
config_setting
,其中包含平台的 constraint_values
、
讓這些 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"]
次
次。
其中一個選項是預先將值定義為 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
with_or
巨集位於 Skylib 的
selects
模組支援直接在 select
內使用 OR
條件:
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
config_setting_group
巨集位於 Skylib 的
selects
模組支援 OR
多個 config_setting
:
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
。
除非其中一個條件是其他條件的明確「專門化」(specialization),或是所有條件都解析為相同的值,否則多個條件無法相符。詳情請參閱這篇文章。
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
無法直接在 select
中 AND
。您必須明確將這些元素包裝在 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"}, ...)
這麼做有兩個原因。
首先,需要知道 select
會選擇哪個路徑的巨集無法運作,因為巨集是在 Bazel 的載入階段中評估,而這個階段會在旗標值已知之前發生。這只是核心 Bazel 設計限制,不太可能隨時變更。
其次,雖然技術上可行,但只需遍歷所有 select
路徑的巨集,缺乏一致的 UI。必須進一步設計才能變更
而負責任的 AI 技術做法
有助於達成這項目標
Bazel 查詢和 cquery
Bazel query
會在 Bazel 的載入階段中運作。這表示,服務並不知道目標使用的指令列,因為那些指令列會標記
等到建構的稍後階段 (在
分析階段)。
因此無法判斷要選擇哪些 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({
"//tools/target_cpu:x86": "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({
"//tools/target_cpu:x86": "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()s 的資料。
不過,巨集可以將 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({
"//tools/target_cpu:x86": 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()
物件本身。根據
Python 設計
除了極少數例外狀況之外的所有物件
會自動傳回 true
我可以像字典一樣讀取 select() 嗎?
宏會在 Bazel 知道建構作業的命令列參數為何之前進行評估,因此無法評估選取項目。至少能夠閱讀
舉例來說,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 = {
"//tools/target_cpu:x86": "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()
是 WORKSPACE 規則,而非 BUILD 規則。
工作區規則沒有特定設定,且評估方式與 BUILD 規則不同。因此,bind()
中的 select()
無法
實際評估任何特定分支版本
您應改用 alias()
,並在 actual
屬性中加入 select()
,以執行這類的執行階段判斷。這個
可以正常運作,因為 alias()
是 BUILD 規則,而會以
特定設定
如有需要,您甚至可將 bind()
目標點設為 alias()
。
$ cat WORKSPACE
workspace(name = "myapp")
bind(name = "openssl", actual = "//:ssl")
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
的替代項目。
為什麼我的 select() 沒有選擇預期的內容?
如果 //myapp:foo
的 select()
未選擇您預期的條件,
使用 cquery 和 bazel config
進行偵錯:
如果 //myapp:foo
是您要建構的頂層目標,請執行以下指令:
$ bazel cquery //myapp:foo <desired build flags>
//myapp:foo (12e23b9a2b534a)
如果您要建構其他目標 //bar
,且該目標依附於子圖中的 //myapp:foo,請執行以下操作:
$ bazel cquery 'somepath(//bar, //myapp:foo)' <desired build flags>
//bar:bar (3ag3193fee94a2)
//bar:intermediate_dep (12e23b9a2b534a)
//myapp:foo (12e23b9a2b534a)
(12e23b9a2b534a)
旁邊的 //myapp:foo
是雜湊
設定該設定會解析 //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
檔案中,如果目標平台同時擁有select()
@platforms//cpu:x86
和 @platforms//os:linux
限制條件,但「不是」
這裡已定義 :x86_linux_platform
?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
,該怎麼辦?
如果您的建構需求需要檢查平台,
可以翻轉 config_setting
中的 --platforms
旗標值:
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 團隊不會為此背書。會對建構造成太大影響 使用者會因預期狀況不符,而感到混淆。