Questa pagina fornisce una visione generale di come l'origine generata è supportata e e come può essere usata nel sistema di compilazione.
Tutti i generatori di codice sorgente offrono funzionalità di sistema di compilazione simili. I tre i casi d'uso di generazione di origini supportati dal sistema di build stanno generando associazioni C utilizzando bindgen, interfacce AIDL e interfacce Protobuf.
Casse da origine generata
Ogni modulo Rust che genera codice sorgente può essere usato come una cassa, esattamente come
se è definito come rust_library
. Ciò significa che può essere definito
dipendenza nelle proprietà rustlibs
, rlibs
e dylibs
. Utilizzo ottimale
per il codice della piattaforma prevede l'utilizzo di un'origine generata come una cassa. Sebbene
La macro include!
è supportata per l'origine generata; il suo scopo principale è
Supportano il codice di terze parti che risiede in external/
.
In alcuni casi il codice della piattaforma potrebbe continuare a utilizzare il codice sorgente generato tramite
Macro include!()
, ad esempio quando utilizzi un modulo genrule
per generare un'origine
in modo peculiare.
Utilizza include!() per includere l'origine generata
L'utilizzo dell'origine generata come cassa è illustrato negli esempi di ogni specifica
(rispettivamente) pagina del modulo. Questa sezione mostra come fare riferimento all'origine generata
attraverso la macro include!()
. Tieni presente che questa procedura è simile per tutte le origini
generatori.
Prerequisito
Questo esempio si basa sul presupposto che tu abbia definito un valore rust_bindgen
(libbuzz_bindgen
) e può andare alla sezione Passaggi per includere l'origine generata
per utilizzare la macro include!()
. In caso contrario, vai a Definizione di un modulo Rust bindgen
crea libbuzz_bindgen
, quindi torna qui.
Tieni presente che le parti del file di build sono applicabili a tutti i generatori di codice sorgente.
Passaggi per includere l'origine generata
Crea external/rust/hello_bindgen/Android.bp
con i seguenti contenuti:
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",
],
}
Crea external/rust/hello_bindgen/src/bindings.rs
con i seguenti contenuti:
#![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"));
Crea external/rust/hello_bindgen/src/lib.rs
con i seguenti contenuti:
mod bindings;
fn main() {
let mut x = bindings::foo { x: 2 };
unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}
Perché creare casse per l'origine generata
A differenza dei compilatori C/C++, rustc
accetta un solo file di origine
che rappresentano un punto di ingresso a un file binario o a una libreria. Si aspetta che l'origine
è strutturato in modo che tutti i file di origine richiesti possano essere automaticamente
sono state rilevate. Ciò significa che l'origine generata deve essere inserita nell'origine
o fornita tramite una direttiva di inclusione nell'origine:
include!("/path/to/hello.rs");
La community di Rust si basa su build.rs
script e sulle ipotesi
dell'ambiente di costruzione Cargo, per evitare questa differenza.
Durante la creazione, il comando cargo
imposta una variabile di ambiente OUT_DIR
.
in cui è previsto che build.rs
script inseriscano il codice sorgente generato. Utilizza la
seguente comando per includere il codice sorgente:
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
Questo presenta una sfida per Chooseg, poiché gli output per ogni modulo vengono inseriti
la propria directory out/
1. Non esiste un solo OUT_DIR
in cui
delle dipendenze restituiscono l'origine generata.
Per il codice della piattaforma, AOSP preferisce pacchettizzare l'origine generata in una cassa in grado di per diversi motivi:
- Impedisci la collisione dei nomi dei file di origine generati.
- Riduci il codice boilerplate. fare il check-in in tutto l'albero che richiede manutenzione. Qualsiasi boilerplate necessaria per effettuare la compilazione dell'origine generata in una cassa può essere sottoposta a manutenzione.
- Evita interazioni implicite2 tra il codice generato e la cassa circostante.
- Riduci la pressione sulla memoria e sul disco collegando dinamicamente le origini generate di uso comune.
Di conseguenza, tutti i tipi di moduli di generazione di origine Rust di Android producono codice
che possono essere compilati e utilizzati come una cassa.
Presto supporta ancora casse di terze parti senza modifiche se tutte
le dipendenze dell'origine generate per un modulo vengono copiate in un
simile a Cargo. In questi casi, Quickg imposta la variabile di ambiente OUT_DIR
a quella directory durante la compilazione del modulo, in modo che sia possibile trovare l'origine generata.
Tuttavia, per i motivi già descritti, conviene utilizzare solo
questo meccanismo nel codice della piattaforma
quando è assolutamente necessario.
-
Questo non presenta alcun problema per C/C++ e linguaggi simili, poiché dell'origine generata viene fornito direttamente al compilatore.↩
-
Poiché
include!
funziona tramite inclusione testuale, potrebbe fare riferimento ai valori di che lo contiene, modificare lo spazio dei nomi o utilizzare costrutti come#![foo]
. Queste interazioni implicite possono essere difficili da gestire. Preferisco sempre quando è veramente richiesta l'interazione con il resto della cassa.↩