我正在交叉编译 Android 的本机库。我的
.bazelrc
是:
build:android --platforms=@io_bazel_rules_go//go/toolchain:android_arm64_cgo
build:android --extra_toolchains=@androidndk//:all
我构建本机 C++ 库,然后使用以下方法将该本机库打包到 jar 文件中:
java_library(
name = "mylib",
resources = ["//:my-native-lib.so"]
)
一切正常,我可以使用
bazel build --config //:mylib
构建我的 jar,它会生成 libmylib.jar
,其中包含我的 .so 本机库。到目前为止一切顺利。
但是我想在我的 jar 文件的名称中包含目标架构(在这种情况下
arm64
)。例如成为libmylib-arm64.jar
。我不想硬编码该名称,而是想以某种方式从我用来构建的平台获取 CPU 架构。
有什么想法可以做到这一点吗?
如果您进行交叉编译,则不需要主机的CPU,而是需要目标的CPU。一种方法是为您支持的每个 cpu 架构定义规则,bazel 将自动启用/禁用给定目标架构的适当规则。
例如,在类似
multi_cpu_rules.bzl
: 的文件中
supported_cpus = [
"x86_64",
"arm",
]
def must_be_str(val):
if type(val) != "string":
fail("invalid type, got: " + type(val))
return val
def format(unformatted_data, cpu):
if type(unformatted_data) == "list":
return [
must_be_str(data).format(cpu = cpu)
for data in unformatted_data
]
if type(unformatted_data) == "dict":
return {
key: must_be_str(value).format(cpu = cpu)
for key, value in formatted_data.items()
}
return must_be_str(unformatted_data).format(cpu = cpu)
def fn_wrap_rule(function, **kwargs):
for cpu in supported_cpus:
values = {
key: format(value, cpu)
for key, value in kwargs.items()
}
function(
**values
)
target_compatible_with
属性是为所有规则定义的。
然后可以在构建文件中将目标定义为:
load("multi_cpu_rules.bzl", "fn_wrap_rule")
fn_wrap_rule(
java_library,
name = "mylib-{cpu}",
resources = ["//:my-native-lib.so"],
target_compatible_with = [
"@platforms//cpu:{cpu}",
],
)
这将为每个目标架构定义一个工件,并且 bazel 将仅构建适合当前所选平台的工件。这些目标需要使用架构字符串在命令行上引用,但是 bazel 可以使用
构建包中的所有目标bazel build //my_lib/...
或者,如果您只想检查编译器运行的主机平台,可以使用以下方式读取约束:
load("@local_config_platform//:constraints.bzl", "HOST_CONSTRAINTS")
这是当前平台的属性列表。因此,要选取需要循环的 cpu 值,但是
BUILD
文件中不允许循环,因此需要将其包装在函数(或宏)中。
因此添加一个文件,例如名为
get_host_cpu.bzl
,其中包含:
load("@local_config_platform//:constraints.bzl", "HOST_CONSTRAINTS")
def get_host_cpu():
cpu_constraint = "@platforms//cpu:"
for constraint in HOST_CONSTRAINTS:
if constraint.startswith(cpu_constraint):
return constraint[len(cpu_constraint):]
然后修改规则调用来使用该函数。然而,在其他地方使用它也需要调用这个函数,所以我们也可以创建一个别名。将您的构建文件更新为:
load(":get_host_cpu.bzl", "get_host_cpu")
java_library(
name = "mylib" + get_host_cpu(),
resources = ["//:my-native-lib.so"]
)
alias(
name = "mylib",
actual = "mylib" + get_host_cpu(),
)