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生成使用 libfuzzer 的 Rust 模糊测试二进制文件。 rust_fuzz 模块示例
rust_protobuf生成源代码,并生成为特定 protobuf 提供接口的 Rust 库。 protobuf 模块源代码生成器页面
rust_bindgen生成源代码,并生成包含与 C 库的 Rust 绑定的 Rust 库。 bindgen 绑定模块源代码生成器页面

重要的通用属性

这些属性在所有 Android Rust 模块中通用。与各 Rust 模块关联的任何其他(独有)属性将在相应模块的页面上列出。

name

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

stem

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

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

srcs

srcs 包含代表模块入口点的单个源代码文件(通常是 main.rslib.rs)。rustc 负责解析和发现编译所需的所有其他源代码文件,生成的 deps 文件中将列举这些文件。

请尽可能避免对平台代码使用这种方式;如需了解详情,请参阅源代码生成器

crate_name

crate_name 通过 rustc --crate_name 标志设置 crate 名称元数据。对于会生成库的模块,此属性必须与源代码中预期使用的 crate 名称相匹配。例如,如果源代码中以 extern crate foo_bar 的形式引用模块 libfoo_bar,那么此属性就必须crate_name: "foo_bar"

此属性对所有 rust_* 模块都是通用的,但是对于会生成 Rust 库的模块(例如 rust_libraryrust_ffirust_bindgenrust_protobufrust_proc_macro)是必需的。这些模块强制执行有关 rustc 与输出文件名之间关系的 crate_name 要求。如需了解详情,请参阅库模块部分。

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++ 标准的版本类似。有效的值为 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 用于控制是否剥离以及如何剥离输出文件中的内容(如果适用)。如果未设置此属性,设备模块将默认剥离除 mini debuginfo 外的所有内容。默认情况下,主机模块不会剥离任何符号。有效值包括用于停用剥离的 none,以及用于剥离所有内容(包括 mini debuginfo)的 all。如需查看其他值,请参阅 Soong 模块参考文档

host_supported

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

定义库依赖项

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

属性名称 说明
rustlibs 也属于依赖项的 rust_library 模块的列表。请将此属性用作声明依赖项的首选方法,因为它允许构建系统选择首选关联。(请参阅下文关联到 Rust 库时
rlibs 必须作为 rlibs 静态关联的 rust_library 模块的列表。(应谨慎使用;请参阅下文关联到 Rust 库时。)
dylibs 要作为 dylibs 动态关联的 rust_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 的 Rust 对 vendorvendor_ramdisk 映像与快照提供有限支持,但支持 staticlibscdylibsrlibsbinaries。对于供应商映像构建目标,已设置了 android_vndk cfg 属性。如果系统目标和供应商目标之间存在差异,您可以在代码中使用此属性。rust_proc_macros 不会作为供应商快照的一部分捕获;如果依赖于这些宏,请确保对其进行适当的版本控制。

不支持产品映像、VNDK 和恢复映像。

增量构建

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

警告:我们无法保证生成的二进制文件与 buildbot 生成的二进制文件完全相同。对象文件中包含的函数或数据的地址可能不同。如要确保生成的工件与 EngProd 基础架构构建的工件完全相同,请勿设置此值。