소스 생성기

이 페이지는 생성된 소스가 지원되는 방법과 빌드 시스템에서 사용되는 방법에 대한 상위 수준 보기를 제공합니다.

모든 소스 생성기는 유사한 빌드 시스템 기능을 제공합니다. 세 가지 빌드 시스템 지원 소스 생성 사용 사례는 bindgen, AIDL 인터페이스 및 protobuf 인터페이스를 사용하여 C 바인딩을 생성하는 것입니다.

생성된 소스의 크레이트

소스 코드를 생성하는 모든 Rust 모듈은 마치 rust_library 로 정의된 것처럼 크레이트로 사용할 수 있습니다. (이는 이것이 rustlibs , rlibsdylibs 속성의 종속성으로 정의될 수 있음을 의미합니다.) 플랫폼 코드에 대한 최상의 사용 패턴은 생성된 소스를 크레이트로 사용하는 것입니다. include! 매크로는 생성된 소스에 대해 지원되며 주요 목적은 external/ 에 있는 타사 코드를 지원하는 것입니다.

genrule 모듈을 사용하여 고유한 방식으로 소스를 생성하는 경우와 같이 플랫폼 코드가 include!() 매크로를 통해 생성된 소스를 계속 사용할 수 있는 경우가 있습니다.

include!()를 사용하여 생성된 소스 포함

생성된 소스를 크레이트로 사용하는 것은 각 특정(각) 모듈 페이지의 예제에서 다룹니다. 이 섹션에서는 include!() 매크로를 통해 생성된 소스를 참조하는 방법을 보여줍니다. 이 프로세스는 모든 소스 생성기에 대해 유사합니다.

전제 조건

이 예제는 rust_bindgen 모듈( libbuzz_bindgen )을 정의했고 include!() 매크로를 사용하기 위해 생성된 소스를 포함하는 단계로 진행할 수 있다는 가정을 기반으로 합니다. 그렇지 않은 경우 Rust bindgen 모듈 정의 로 이동하여 libbuzz_bindgen 을 생성한 다음 여기로 돌아오십시오.

이것의 빌드 파일 부분은 모든 소스 생성기에 적용할 수 있습니다.

생성된 소스를 포함하는 단계

다음 내용으로 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) }
}

생성된 소스를 위한 크레이트가 필요한 이유

C/C++ 컴파일러와 달리 rustc 는 바이너리 또는 라이브러리에 대한 진입점을 나타내는 단일 소스 파일만 허용합니다. 필요한 모든 소스 파일이 자동으로 검색될 수 있도록 소스 트리가 구성될 것으로 예상합니다. 이것은 생성된 소스가 소스 트리에 배치되거나 소스의 include 지시문을 통해 제공되어야 함을 의미합니다.

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

Rust 커뮤니티는 이러한 차이점을 해결 하기 위해 build.rs 스크립트와 Cargo 빌드 환경에 대한 가정에 의존합니다. 빌드할 때, cargo 명령은 build.rs 스크립트가 생성된 소스 코드를 배치할 것으로 예상되는 OUT_DIR 환경 변수 를 설정합니다. 다음 명령을 사용하여 소스 코드를 포함합니다.

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

이것은 각 모듈에 대한 출력이 고유 out/ 디렉토리 1 에 배치되기 때문에 Soong에 대한 문제를 나타냅니다. 종속성이 생성된 소스를 출력하는 단일 OUT_DIR 이 없습니다.

플랫폼 코드의 경우 AOSP는 다음과 같은 몇 가지 이유로 인해 생성된 소스를 가져올 수 있는 상자에 패키징하는 것을 선호합니다.

  • 생성된 소스 파일 이름이 충돌하지 않도록 합니다.
  • 유지 관리가 필요한 트리 전체에 체크인된 상용구 코드를 줄입니다. 생성된 소스를 크레이트로 컴파일 하는 데 필요한 모든 상용구는 중앙에서 유지 관리할 수 있습니다.
  • 생성된 코드와 주변 크레이트 간의 암시적 2 상호 작용을 피하십시오.
  • 일반적으로 사용되는 생성 소스를 동적으로 연결하여 메모리와 디스크에 대한 부담을 줄입니다.

결과적으로 Android의 모든 Rust 소스 생성 모듈 유형은 컴파일 하여 크레이트로 사용할 수 있는 코드를 생성합니다. Soong은 모듈에 대해 생성된 모든 소스 종속성이 Cargo와 유사한 단일 모듈 디렉토리에 복사되는 경우 수정 없이 타사 크레이트를 계속 지원합니다. 이 경우 Soong은 모듈을 컴파일할 때 OUT_DIR 환경 변수를 해당 디렉터리로 설정하여 생성된 소스를 찾을 수 있도록 합니다. 그러나 이미 설명한 이유 때문에 절대적으로 필요한 경우에만 플랫폼 코드에서 이 메커니즘을 사용하는 것이 가장 좋습니다.


  1. 이것은 생성된 소스에 대한 경로가 컴파일러에 직접 제공되기 때문에 C/C++ 및 유사한 언어에 대한 문제를 나타내지 않습니다.

  2. include! 텍스트 포함으로 작동하며, 둘러싸는 네임스페이스의 값을 참조하거나, 네임스페이스를 수정하거나, #![foo] 와 같은 구성을 사용할 수 있습니다. 이러한 암시적 상호 작용은 유지 관리하기 어려울 수 있습니다. 상자의 나머지 부분과의 상호 작용이 정말로 필요한 경우 항상 매크로를 선호합니다.