Android Rust 模块

作为一般原则,rust_* 模块定义与 cc_* 的用法和预期紧密相符。以下是 Rust 二进制文件的模块定义示例

rust_binary {
    name: "hello_rust",
    crate_name: "hello_rust",
    srcs: ["src/hello_rust.rs"],
    host_supported: true,
}

本页介绍了 rust_* 模块最常用的属性。如需详细了解特定模块类型和示例模块定义,请参阅二进制模块库模块测试模块

基本模块类型

类型定义更多信息
rust_binaryRust 二进制文件 二进制模块页面
rust_library生成 Rust 库,并提供 rlibdylib 变体。 rust_library,库模块页面。
rust_ffi生成可供 cc 模块使用的 Rust C 库,并提供静态和共享变体。 rust_ffi,库模块页面
rust_proc_macro生成 proc-macro Rust 库。(这些类似于编译器插件。) rust_proc_macro,库模块页面
rust_test生成使用标准 Rust 测试工具的 Rust 测试二进制文件。 测试模块页面
rust_fuzz生成利用 libfuzzerRust 模糊测试二进制文件。 rust_fuzz 模块示例
rust_protobuf生成源代码并生成 Rust 库,该库为特定的 protobuf 提供接口。 Protobuf 模块源代码生成器页面
rust_bindgen生成源代码并生成 Rust 库,其中包含 Rust 到 C 库的绑定。 Bindgen 绑定模块源代码生成器页面

重要的通用属性

这些属性在所有 Android Rust 模块中都很常见。与各个 Rust 模块关联的任何其他(独特)属性都列在该模块的页面上。

name

name 是模块的名称。与其他 Soong 模块一样,这在大多数 Android.bp 模块类型中必须是唯一的。默认情况下,name 用作输出文件名。如果输出文件名必须与模块名称不同,请使用 stem 属性来定义它。

stem

stem(可选)直接控制输出文件名(不包括文件扩展名和其他后缀)。例如,stem 值为 libfoorust_library_rlib 库会生成 libfoo.rlib 文件。如果您未为 stem 属性提供值,则输出文件名默认采用模块名称。

当您无法将模块名称设置为所需的输出文件名时,请使用 stem 函数。例如,用于 log crate 的 rust_library 命名为 liblog_rust,因为 liblog cc_library 已存在。在这种情况下使用 stem 属性可确保输出文件命名为 liblog.* 而不是 liblog_rust.*

srcs

srcs 包含一个源文件,该文件表示模块的入口点(通常是 main.rslib.rs)。rustc 处理编译所需的所有其他源文件的解析和发现,这些文件在生成的 deps 文件中列出。

如果可能,请避免将此用法用于平台代码;有关详情,请参阅源代码生成器

crate_name

crate_name 通过 rustc --crate_name 标志设置 crate 名称元数据。对于生成库的模块,这必须与源代码中使用的预期 crate 名称匹配。例如,如果模块 libfoo_bar 在源代码中被引用为 extern crate foo_bar,则这必须是 crate_name: "foo_bar"。

此属性在所有 rust_* 模块中都很常见,但对于生成 Rust 库的模块(例如 rust_libraryrust_ffirust_bindgenrust_protobufrust_proc_macro)来说,它是必需的。这些模块对 crate_name 和输出文件名之间的关系强制执行 rustc 要求。有关详情,请参阅库模块部分。

lints

默认情况下,除源代码生成器之外的所有模块类型都运行rustc linter。定义并使用了一些 lint 集来验证模块源代码。此类 lint 集的可能值如下:

  • default 默认的 lint 集,具体取决于模块的位置
  • android 应用于所有 Android 平台代码的最严格的 lint 集
  • vendor 应用于供应商代码的较宽松的 lint 集
  • none 忽略所有 lint 警告和错误

clippy_lints

默认情况下,除源代码生成器之外的所有模块类型也都运行clippy linter。定义了一些 lint 集,用于验证模块源代码。以下是一些可能的值:

  • default 默认的 lint 集,具体取决于模块的位置
  • android 应用于所有 Android 平台代码的最严格的 lint 集
  • vendor 应用于供应商代码的较宽松的 lint 集
  • none 忽略所有 lint 警告和错误

edition

edition 定义用于编译此代码的 Rust 版本。这类似于 C 和 C++ 的 std 版本。有效值包括 20152018(默认值)。

flags

flags 包含要传递给编译期间的 rustc 的标志字符串列表。

ld_flags

ld-flags 包含在编译源代码时要传递给链接器的标志字符串列表。这些标志通过 -C linker-args rustc 标志传递。clang 用作链接器前端,调用 lld 进行实际链接。

features

features 是编译期间必须启用的功能字符串列表。这通过 --cfg 'feature="foo"' 传递给 rustc。大多数功能都是累加的,因此在许多情况下,这包括所有依赖模块所需的完整功能集。但是,如果功能互斥,请在提供冲突功能的任何构建文件中定义其他模块。

cfgs

cfgs 包含要在编译期间启用的 cfg 标志字符串列表。这通过 --cfg foo--cfg "fizz=buzz" 传递给 rustc

构建系统会在特定情况下自动设置某些 cfg 标志,如下所示:

  • 作为 dylib 构建的模块将设置 android_dylib cfg。

  • 将使用 VNDK 的模块将设置 android_vndk cfg。这类似于 C++ 的 __ANDROID_VNDK__ 定义。

strip

strip 控制是否以及如何剥离输出文件(如果适用)。如果未设置此项,则设备模块默认剥离除迷你调试信息之外的所有内容。默认情况下,主机模块不剥离任何符号。有效值包括 none(禁用剥离)和 all(剥离所有内容,包括迷你调试信息)。其他值可以在Soong 模块参考中找到。

host_supported

对于设备模块,host_supported 参数指示模块是否也应提供主机变体。

定义库依赖项

Rust 模块可以通过以下属性依赖于 CC 和 Rust 库:

属性名称 描述
rustlibs rust_library 模块的列表,这些模块也是依赖项。使用此方法作为声明依赖项的首选方法,因为它允许构建系统选择首选的链接。(请参阅下文链接到 Rust 库时
rlibs 必须静态链接为 rlibsrust_library 模块的列表。(谨慎使用;请参阅下文链接到 Rust 库时。)
shared_libs 必须动态链接为共享库的 cc_library 模块的列表。
static_libs 必须静态链接为静态库的 cc_library 模块的列表。
whole_static_libs 应静态链接为静态库并完整包含在生成的库中的 cc_library 模块的列表。对于 rust_ffi_static 变体,whole_static_libraries 将包含在生成的静态库归档文件中。对于 rust_library_rlib 变体,whole_static_libraries 库将捆绑到生成的 rlib 库中。

链接到 Rust 库时,最佳做法是使用 rustlibs 属性,而不是 rlibsdylibs,除非您有特定的理由这样做。这允许构建系统根据根模块的需求选择正确的链接,并且减少了依赖项树同时包含库的 rlibdylib 版本(这将导致编译失败)的可能性。

不受支持和有限支持的构建功能

Soong 的 Rustvendorvendor_ramdisk 映像和快照提供有限的支持。但是,支持 staticlibscdylibsrlibsbinaries。对于供应商映像构建目标,将设置 android_vndk cfg 属性。如果系统目标和供应商目标之间存在差异,则可以在代码中使用此属性。rust_proc_macros 未作为供应商快照的一部分捕获;如果依赖于这些宏,请确保您对其进行适当的版本控制。

不支持 Product、VNDK 和 Recovery 映像。

增量构建

开发人员可以通过将 SOONG_RUSTC_INCREMENTAL 环境变量设置为 true 来启用 Rust 源代码的增量编译。

警告:这不能保证生成的二进制文件与 buildbot 生成的二进制文件完全相同。对象文件中包含的函数或数据的地址可能不同。为了确保生成的工件与 EngProd 基础架构构建的工件 100% 相同,请将此值保持未设置状态。