Generadores de fuentes

Esta página proporciona una vista de alto nivel de cómo se admite la fuente generada y cómo se puede usar en el sistema de compilación.

Todos los generadores de fuentes proporcionan una funcionalidad de sistema de compilación similar. Los tres casos de uso de generación de fuentes compatibles con el sistema de compilación están generando enlaces C mediante bindgen, interfaces AIDL e interfaces protobuf.

Cajas de la fuente generada

Cada módulo de Rust que genera código fuente se puede usar como una caja, exactamente como si estuviera definido como rust_library . (Esto significa que se puede definir como una dependencia en las rustlibs , rlibs y dylibs ). El mejor patrón de uso para el código de la plataforma es emplear la fuente generada como una caja. Aunque el include! macro es compatible con la fuente generada, su propósito principal es admitir código de terceros que reside en external/ .

Hay casos en los que el código de la plataforma aún puede usar la fuente generada a través de la macro include!() , como cuando usa un módulo genrule para generar la fuente de una manera única.

Usando include!() para incluir la fuente generada

El uso de la fuente generada como una caja está cubierto por los ejemplos en cada página de módulo específica (respectiva). Esta sección muestra cómo hacer referencia a la fuente generada a través de la macro include!() . Tenga en cuenta que este proceso es similar para todos los generadores de fuentes.

Requisito previo

Este ejemplo se basa en la suposición de que ha definido un módulo rust_bindgen ( libbuzz_bindgen ) y puede continuar con los Pasos para incluir la fuente generada para usar la macro include!() . Si no lo ha hecho, vaya a Definición de un módulo rust bindgen , cree libbuzz_bindgen y vuelva aquí.

Tenga en cuenta que las partes del archivo de compilación de esto se aplican a todos los generadores de código fuente.

Pasos para incluir la fuente generada

Cree external/rust/hello_bindgen/Android.bp con los siguientes contenidos:

rust_binary {
   name: "hello_bzip_bindgen_include",
   srcs: [
         // The primary rust source file must come first in this list.
         "src/lib.rs",

         // The module providing the bindgen bindings is
         // included in srcs prepended by ":".
         ":libbuzz_bindgen",
    ],

    // Dependencies need to be redeclared when generated source is used via srcs.
    shared_libs: [
        "libbuzz",
    ],
}

Cree external/rust/hello_bindgen/src/bindings.rs con los siguientes contenidos:

#![allow(clippy::all)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
#![allow(missing_docs)]

// Note that "bzip_bindings.rs" here must match the source_stem property from
// the rust_bindgen module.
include!(concat!(env!("OUT_DIR"), "/bzip_bindings.rs"));

Cree external/rust/hello_bindgen/src/lib.rs con los siguientes contenidos:

mod bindings;

fn main() {
    let mut x = bindings::foo { x: 2 };
    unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}

¿Por qué cajas para la fuente generada?

A diferencia de los compiladores C/C++, rustc solo acepta un único archivo fuente que representa un punto de entrada a un binario o biblioteca. Espera que el árbol de origen esté estructurado de tal manera que todos los archivos de origen necesarios puedan descubrirse automáticamente. Esto significa que la fuente generada debe colocarse en el árbol de fuentes o proporcionarse a través de una directiva de inclusión en la fuente:

include!("/path/to/hello.rs");

La comunidad de Rust depende de los scripts de build.rs y de las suposiciones sobre el entorno de construcción de Cargo para trabajar con esta diferencia . Cuando se compila, el comando cargo establece una variable de entorno OUT_DIR en la que se espera que los scripts de build.rs el código fuente generado. Use el siguiente comando para incluir el código fuente:

include!(concat!(env!("OUT_DIR"), "/hello.rs"));

Esto presenta un desafío para Soong ya que las salidas de cada módulo se colocan en su propio directorio out/ 1 . No hay un solo OUT_DIR donde las dependencias generen su fuente generada.

Para el código de la plataforma, AOSP prefiere empaquetar la fuente generada en una caja que se puede importar, por varias razones:

  • Evite que los nombres de los archivos de origen generados colisionen.
  • Reduzca el registro de código repetitivo en todo el árbol que requiere mantenimiento. Cualquier repetitivo que se requiera para hacer que la fuente generada se compile en una caja se puede mantener de forma centralizada.
  • Evite 2 interacciones implícitas entre el código generado y la caja circundante.
  • Reduzca la presión sobre la memoria y el disco mediante la vinculación dinámica de las fuentes generadas de uso común.

Como resultado, todos los tipos de módulos de generación de código fuente de Rust de Android producen código que se puede compilar y usar como una caja . Soong aún admite cajas de terceros sin modificaciones si todas las dependencias de origen generadas para un módulo se copian en un solo directorio por módulo, similar a Cargo. En tales casos, Soong establece la variable de entorno OUT_DIR en ese directorio al compilar el módulo, de modo que se pueda encontrar la fuente generada. Sin embargo, por las razones ya descritas, la mejor práctica es usar este mecanismo solo en el código de la plataforma cuando sea absolutamente necesario.


  1. Esto no presenta ningún problema para C/C++ y lenguajes similares, ya que la ruta a la fuente generada se proporciona directamente al compilador.

  2. Desde include! funciona por inclusión textual, puede hacer referencia a valores del espacio de nombres adjunto, modificar el espacio de nombres o usar construcciones como #![foo] . Estas interacciones implícitas pueden ser difíciles de mantener. Siempre prefiera las macros cuando realmente se requiera la interacción con el resto de la caja.