Android Rust modules

As a general principle, rust_* module definitions adhere closely to cc_* usage and expectations. The following is an example of a module definition for a Rust binary:

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

This page covers the most common properties for rust_* modules. For more information about specific module types and example module definitions, see the Binary Modules, Library Modules, or Test Modules pages.

Basic module types

TypeDefinitionFor More Information
rust_binaryA Rust binary Binary Modules page
rust_libraryProduces a Rust library, and provides both rlib and dylib variants. rust_library, Library Modules page.
rust_ffiProduces a Rust C library usable by cc modules, and provides both static and shared variants. rust_ffi, Library Modules page
rust_proc_macroProduces a proc-macro Rust library. (These are analogous to compiler plugins.) rust_proc_macro, Libraries Modules page
rust_testProduces a Rust test binary that uses the standard Rust test harness. Test Modules page
rust_fuzzProduces a Rust fuzz binary leveraging libfuzzer. rust_fuzz module example
rust_protobufGenerates source and produces a Rust library that provides an interface for a particular protobuf. Protobufs Modules and Source Generators pages
rust_bindgenGenerates source and produces a Rust library containing Rust bindings to C libraries. Bindgen Bindings Modules and Source Generators pages

Important common properties

These properties are common across all Android Rust Modules. Any additional (unique) properties associated with individual Rust modules are listed on that module's page.

name

name is the name of your module. Like other Soong modules, this must be unique across most Android.bp module types. By default, name is used as the output filename. If the output filename must be different from the module name, use the stem property to define it.

stem

stem (optional) provides direct control over the output filename (excluding the file extension and other suffixes). For example, a rust_library_rlib library with a stem value of libfoo produces a libfoo.rlib file. If you don't provide a value for the stem property, the output filename adopts the module name by default.

Use the stem function when you can't set the module name to the desired output filename. For example, the rust_library for the log crate is named liblog_rust, because a liblog cc_library already exists. Using the stem property in this case ensures that the output file is named liblog.* instead of liblog_rust.*.

srcs

srcs contains a single source file that represents the entry point to your module (usually main.rs or lib.rs). rustc handles the resolution and discovery of all other source files required for compilation, and these are enumerated in the deps file that gets produced.

When possible, avoid this usage for platform code; see Source Generators for more information.

crate_name

crate_name sets the crate name metadata through the rustc --crate_name flag. For modules which produce libraries, this must match the expected crate name used in source. For example, if the module libfoo_bar is referenced in source as extern crate foo_bar, then this must be crate_name: "foo_bar".

This property is common to all rust_* modules, but it's required for modules which produce Rust libraries (such as rust_library rust_ffi, rust_bindgen, rust_protobuf, and rust_proc_macro). These modules enforce rustc requirements on the relationship between crate_name and the output filename. For more information, see the Library Modules section.

lints

The rustc linter is run by default for all module types except source generators. Some lint sets are defined and used to validate module source. Possible values for such lint sets are as follows:

  • default the default set of lints, depending on the module's location
  • android the strictest lint set that applies to all Android platform code
  • vendor a relaxed set of lints applied to vendor code
  • none to ignore all lint warnings and errors

clippy_lints

The clippy linter is also run by default for all module types except source generators. A few sets of lints are defined which are used to validate module source. These are some possible values:

  • default default set of lints depending on the module's location
  • android the strictest lint set that applies to all Android platform code
  • vendor a relaxed set of lints applied to vendor code
  • none to ignore all lint warnings and errors

edition

edition defines the Rust edition to use for compiling this code. This is similar to std versions for C and C++. Valid values are 2015 and 2018 (default).

flags

flags contains a string list of flags to pass to rustc during compilation.

ld_flags

ld-flags contains a string list of flags to pass to the linker when compiling source. These are passed by the -C linker-args rustc flag. clang is used as the linker front-end, invoking lld for the actual linking.

features

features is a string list of features that must be enabled during compilation. This is passed to rustc by --cfg 'feature="foo"'. Most features are additive, so in many cases this consists of the full features set required by all dependent modules. However, in cases where features are exclusive of one another, define additional modules in any build files that provide conflicting features.

cfgs

cfgs contains a string list of cfg flags to be enabled during compilation. This is passed to rustc by --cfg foo and --cfg "fizz=buzz".

The build system automatically sets certain cfg flags in particular situations, listed below:

  • Modules built as a dylib will have the android_dylib cfg set.

  • Modules which would use the VNDK will have the android_vndk cfg set. This is similar to the __ANDROID_VNDK__ definition for C++.

strip

strip controls whether and how the output file is stripped (if applicable). If this is unset, device modules default to strip everything except mini debuginfo. Host modules, by default, don't strip any symbols. Valid values include none to disable stripping, and all to strip everything, including the mini debuginfo. Additional values can be found in the Soong Modules Reference.

host_supported

For device modules, the host_supported parameter indicates whether the module should also provide a host variant.

Defining library dependencies

Rust modules can depend on both CC and Rust libraries through the following properties:

Property Name Description
rustlibs List of rust_library modules that are also dependencies. Use this as your preferred method of declaring dependencies, as it allows the build system to select the preferred linkage. (See When linking against Rust libraries, below)
rlibs List of rust_library modules that must be statically linked as rlibs. (Use with caution; see When linking against Rust libraries, below.)
shared_libs List of cc_library modules which must be dynamically linked as shared libraries.
static_libs List of cc_library modules which must be statically linked as static libraries.
whole_static_libs List of cc_library modules which should be statically linked as static libraries and included whole in the resulting library. For rust_ffi_static variants, whole_static_libraries will be included in the resulting static library archive. For rust_library_rlib variants, whole_static_libraries libraries will be bundled into the resulting rlib library.

When linking against Rust libraries, as a best practice, do so using the rustlibs property rather than rlibs or dylibs unless you have a specific reason to do so. This allows the build system to select the correct linkage based on what the root module requires, and it reduces the chance that a dependency tree contains both the rlib and dylib versions of a library (which will cause compilation to fail).

Unsupported and limited support build features

Soong's Rust offers limited support for vendor and vendor_ramdisk images and snapshots. However, staticlibs, cdylibs, rlibs, and binaries are supported. For vendor image build targets, the android_vndk cfg property is set. You can use this in code if there are differences between the system and vendor targets. rust_proc_macros aren't captured as part of vendor snapshots; if these are depended on, ensure you appropriately version-control them.

Product, VNDK, and Recovery images aren't supported.

Incremental builds

Developers can enable the incremental compilation of Rust source by setting the SOONG_RUSTC_INCREMENTAL environment variable to true.

Warning: This isn't guaranteed to produce binaries that are identical to those generated by buildbots. The addresses of functions or data contained in the object files may be different. To ensure that the generated artifacts are 100% identical to those built by the EngProd infrastructure, leave this value unset.