이 페이지에서는 생성된 소스가 지원되는 방식과 빌드 시스템에서 소스를 사용하는 방법을 개략적으로 설명합니다.
모든 소스 생성기는 비슷한 빌드 시스템 기능을 제공합니다. 빌드 시스템에서 지원되는 세 가지 소스 생성 사용 사례는 bindgen, AIDL 인터페이스 및 protobuf 인터페이스를 사용하여 C 바인딩을 생성하는 것입니다.
생성된 소스를 크레이트로 사용
소스 코드를 생성하는 모든 Rust 모듈은 모듈이 rust_library
로서 정의된 경우와 똑같은 방식으로 크레이트로 사용할 수 있습니다. (즉, rustlibs
, rlibs
, dylibs
속성에서 종속 항목으로 정의할 수 있습니다.) 플랫폼 코드의 가장 좋은 사용 패턴은 생성된 소스를 크레이트로 사용하는 것입니다. include!
매크로는 생성된 소스에서 지원되지만, 주된 목적은 external/
에 있는 타사 코드를 지원하는 것입니다.
플랫폼 코드가 include!()
매크로를 통해 생성된 소스를 사용하는 사례도 있습니다(예: genrule
모듈을 사용하여 고유한 방식으로 소스를 생성하는 경우).
생성된 소스를 include!()를 사용하여 포함
생성된 소스를 크레이트로 사용하는 방법은 각 모듈 페이지에 예로 나와 있습니다. 이 섹션에서는 생성된 소스를 include!()
매크로를 통해 참조하는 방법을 보여줍니다. 이 프로세스는 모든 소스 생성기에서 비슷합니다.
사전 요구 사항
이 예에서는 rust_bindgen
모듈(libbuzz_bindgen
)을 정의했고 include!()
매크로를 사용하기 위해 생성된 소스를 포함하는 방법으로 넘어갈 준비가 되었다고 가정합니다. 준비가 되지 않았다면 Rust bindgen 모듈 정의로 이동하여 libbuzz_bindgen
을 만든 후 다시 돌아오세요.
이 예의 build-file 부분은 모든 소스 생성기에 적용됩니다.
생성된 소스를 포함하는 방법
다음 콘텐츠로 external/rust/hello_bindgen/Android.bp
를 만듭니다.
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",
],
}
다음 콘텐츠로 external/rust/hello_bindgen/src/bindings.rs
를 만듭니다.
#![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"));
다음 콘텐츠로 external/rust/hello_bindgen/src/lib.rs
를 만듭니다.
mod bindings;
fn main() {
let mut x = bindings::foo { x: 2 };
unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}
생성된 소스를 크레이트로 사용하는 이유
rustc
는 C/C++ 컴파일러와 달리 바이너리 또는 라이브러리의 진입점을 나타내는 단일 소스 파일만 허용합니다. 소스 트리는 필요한 모든 소스 파일을 자동으로 검색할 수 있도록 구성되어 있어야 합니다. 즉, 생성된 소스는 소스 트리에 배치하거나 소스에서 include 지시어를 통해 제공해야 합니다.
include!("/path/to/hello.rs");
Rust 커뮤니티는 이 차이를 해결하기 위해 build.rs
스크립트와 Cargo 빌드 환경에 관한 가정을 사용합니다.
cargo
명령어는 빌드 시점에 OUT_DIR
환경 변수를 설정하는데, 여기에 build.rs
스크립트가 생성된 소스 코드를 배치해야 합니다. 다음 명령어를 사용하여 소스 코드를 포함합니다.
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
위 명령어의 경우 각 모듈의 출력이 자체 out/
디렉터리1에 배치되므로 이는 Soong에 문제가 됩니다. 종속 항목이 생성된 소스를 출력하는 단일 OUT_DIR
은 없습니다.
플랫폼 코드의 경우 AOSP는 생성된 소스를 가져오기가 가능한 크레이트로 패키징하는 것을 선호하는데, 그 이유는 다음과 같습니다.
- 생성된 소스 파일 이름의 충돌을 방지합니다.
- 트리에 유지 관리가 필요한 상용구 코드가 체크인되는 양을 줄입니다. 생성된 소스가 크레이트로 컴파일되도록 하는 모든 상용구는 중앙에서 유지 관리가 가능합니다.
- 생성된 코드와 관련 크레이트 간의 암시적2 상호작용을 방지합니다.
- 흔히 사용되는 생성된 코드를 동적으로 링크하여 메모리와 디스크의 부담을 줄입니다.
결과적으로, Android의 모든 Rust 소스 생성 모듈 유형은 크레이트로서 컴파일되고 사용될 수 있는 코드를 생성합니다.
Soong은 모듈의 모든 생성된 소스 종속 항목이 Cargo에서처럼 모듈당 하나의 디렉터리로 복사된 경우에는 여전히 타사 크레이트를 수정 없이 지원합니다. 이 경우 Soong은 모듈을 컴파일할 때 생성된 소스를 찾을 수 있도록 OUT_DIR
환경 변수를 이 디렉터리로 설정합니다.
그러나 위에서 설명한 이유로 인해, 플랫폼 코드에서는 반드시 필요한 경우에만 이 메커니즘을 사용하는 것이 좋습니다.