Derleme sistemi, rust_bindgen
modül türü aracılığıyla bindgen bağlamalarının oluşturulmasını destekler. Bindgen, C kitaplıkları için Rust FFI bağlamaları sağlar (bazı sınırlı C++ desteğiyle birlikte, bu da cppstd özelliğinin ayarlanmasını gerektirir).
Temel rust_bindgen kullanımı
Aşağıda, bindgen kullanan bir modülün nasıl tanımlanacağı ve bu modülün nasıl sandık olarak kullanılacağı ile ilgili bir örnek verilmiştir. Harici kod gibi durumlarda include!() makrosu aracılığıyla bindgen bağlamalarını kullanmanız gerekiyorsa Kaynak Oluşturucular sayfasına bakın.
Rust'tan çağrılacak örnek C kitaplığı
Bir yapıyı ve işlevi tanımlayan örnek bir C kitaplığı aşağıda verilmiştir.
external/rust/libbuzz/libbuzz.h
typedef struct foo {
int x;
} foo;
void fizz(int i, foo* cs);
external/rust/libbuzz/libbuzz.c
#include <stdio.h>
#include "libbuzz.h"
void fizz(int i, foo* my_foo){
printf("hello from c! i = %i, my_foo->x = %i\n", i, my_foo->x);
}
rust_bindgen modülü tanımlama
Tüm alakalı üstbilgileri içeren bir sarmalayıcı üstbilgisi (external/rust/libbuzz/libbuzz_wrapper.h) tanımlayın:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
Android.bp dosyasını external/rust/libbuzz/Android.bp olarak tanımlayın:
cc_library {
name: "libbuzz",
srcs: ["libbuzz.c"],
}
rust_bindgen {
name: "libbuzz_bindgen",
// Crate name that's used to generate the rust_library variants.
crate_name: "buzz_bindgen",
// Path to the wrapper source file.
wrapper_src: "libbuzz_wrapper.h",
// 'source_stem' controls the output filename.
// This is the filename that's used in an include! macro.
//
// In this case, we just use "bindings", which produces
// "bindings.rs".
source_stem: "bindings",
// Bindgen-specific flags and options to customize the bindings.
// See the bindgen manual for more information.
bindgen_flags: ["--verbose"],
// Clang flags to be used when generating the bindings.
cflags: ["-DSOME_FLAG"],
// Shared, static, and header libraries which export the necessary
// include directories must be specified.
//
// These libraries will also be included in the crate if static,
// or propagated to dependents if shared.
// static_libs: ["libbuzz"]
// header_libs: ["libbuzz"]
shared_libs: ["libbuzz"],
}
Bindgen işaretlerini kullanma hakkında daha fazla bilgi edinmek için Oluşturulan Bağlantıları Özelleştirme başlıklı bindgen kılavuzu bölümüne bakın.
Bu bölümü kullanarak rust_bindgen modülünü include!() makrosunu kullanmak için ön koşul olarak tanımladıysanız Kaynak Oluşturucular sayfasındaki Ön koşul bölümüne dönün. Aksi takdirde, sonraki bölümlere geçin.
Bağlamaları sandık olarak kullanma
Aşağıdaki içerikle external/rust/hello_bindgen/Android.bp oluşturun:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
Aşağıdaki içerikle external/rust/hello_bindgen/src/main.rs oluşturun:
//! Example crate for testing bindgen bindings
fn main() {
let mut x = buzz_bindgen::foo { x: 2 };
unsafe { buzz_bindgen::fizz(1, &mut x as *mut buzz_bindgen::foo) }
}
Son olarak, ikiliyi oluşturmak için m hello_bindgen komutunu çağırın.
Bindgen bağlamalarını test etme
Bindgen bağlamaları, genellikle bellek düzeni uyuşmazlıklarını önlemek için bir dizi oluşturulmuş düzen testi içerir. AOSP, bu testler için tanımlanmış bir test modülünüz olmasını ve testlerin projenizin normal test paketi kapsamında çalıştırılmasını önerir.
Bunlar için test ikilisi, external/rust/hello_bindgen/Android.bp içinde rust_test modülü tanımlanarak kolayca oluşturulabilir:
rust_test {
name: "bindings_test",
srcs: [
":libbuzz_bindgen",
],
crate_name: "buzz_bindings_test",
test_suites: ["general-tests"],
auto_gen_config: true,
// Be sure to disable lints as the generated source
// is not guaranteed to be lint-free.
clippy_lints: "none",
lints: "none",
}
Görünürlük ve bağlantı
Oluşturulan bağlamalar genellikle çok küçüktür. Çünkü tür tanımları, işlev imzaları ve ilgili sabitlerden oluşurlar. Bu nedenle, bu kitaplıkları dinamik olarak bağlamak genellikle gereksizdir. Bu modüller için dinamik bağlantıyı devre dışı bıraktık. Böylece, bu modüllerin rustlibs üzerinden kullanılması statik bir varyantı otomatik olarak seçecek.
Varsayılan olarak, rust_bindgen modüllerinin visibility özelliği [":__subpackages__"]'dir. Bu özellik, yalnızca aynı Android.bp dosyasındaki veya dizin hiyerarşisinde bu dosyanın altında yer alan modüllerin bu özelliği görmesine izin verir. Bu işlem iki amaca hizmet eder:
- Ağacın başka yerlerinde ham C bağlamalarının kullanılmasını engeller.
- Statik ve dinamik bağlantı karışımıyla elmas bağlantı sorunlarını önler.
Genellikle, oluşturulan modülün etrafında güvenli bir sarmalayıcı kitaplık sağlamanız gerekir. Bu kitaplık, bağlamalarla aynı dizin ağacına eklenir ve diğer geliştiricilerin kullanması amaçlanır. Bu yöntem kullanım alanınız için işe yaramazsa görünürlüğe ek paketler ekleyebilirsiniz. Ek görünürlük kapsamları eklerken lütfen gelecekte aynı işleme bağlanabilecek iki kapsam eklememeye dikkat edin. Aksi takdirde bağlantı oluşturulamayabilir.
Önemli rust_bindgen özellikleri
Aşağıda tanımlanan özellikler, tüm modüller için geçerli olan önemli ortak özelliklere ek olarak verilmiştir. Bunlar, Rustbindgen modülleri için özellikle önemlidir veya rust_bindgen modül türüne özgü benzersiz davranışlar sergiler.
stem, name, crate_name
rust_bindgen kitaplık varyantları oluşturur. Bu nedenle, stem, name ve crate_name özellikleri için rust_library modülleriyle aynı koşulları paylaşırlar. Referans için Önemli Rust kitaplığı özellikleri bölümüne bakın.
wrapper_src
Bu, bu bağlamalar için gereken üst dosyaları içeren bir sarmalayıcı üst dosyasının göreli yoludur. Dosya uzantısı, başlığın nasıl yorumlanacağını ve varsayılan olarak hangi -std işaretinin kullanılacağını belirler. Uzantı .hh veya .hpp olmadığı sürece bunun bir C üstbilgisi olduğu varsayılır. C++ başlığınızın başka bir uzantısı olması gerekiyorsa dosyanın C dosyası olduğunu varsayan varsayılan davranışı geçersiz kılmak için cpp_std özelliğini ayarlayın.
source_stem
Bu, oluşturulan kaynak dosyanın dosya adıdır. Bağlamaları bir paket olarak kullanıyor olsanız bile bu alan tanımlanmalıdır. Bunun nedeni, stem özelliğinin yalnızca oluşturulan kitaplık varyantlarının çıkış dosya adını kontrol etmesidir.
Bir modül, rustlibs aracılığıyla paket olarak değil de kaynak olarak birden fazla kaynak oluşturucuya (ör. bindgen ve protobuf) bağlıysa bu modülün bağımlılıkları olan tüm kaynak oluşturucuların benzersiz source_stem değerlerine sahip olduğundan emin olmanız gerekir. Bağımlı modüller, SourceProvider bağımlılıklarındaki kaynakları srcs içinde tanımlanmış tüm SourceProvider bağımlılıklarından ortak bir OUT_DIR dizinine kopyalar. Bu nedenle, source_stem'deki çakışmalar, oluşturulan kaynak dosyaların OUT_DIR dizininde üzerine yazılmasına neden olur.
c_std
Bu, hangi C standardı sürümünün kullanılacağını gösteren bir dizedir. Geçerli değerler aşağıda listelenmiştir:
- Belirli bir sürüm (ör.
"gnu11"). build/soong/cc/config/global.goiçinde derleme sistemi tarafından tanımlanan bir değer olan"experimental", kullanılabilir olduğunda C++1z gibi taslak sürümleri kullanabilir.- Derleme sistemi varsayılanının kullanılması gerektiğini belirten ayarlanmamış veya
"".
Bu ayar belirlenirse dosya uzantısı yoksayılır ve üstbilginin C üstbilgisi olduğu varsayılır. Bu ayar, cpp_std ile aynı anda yapılamaz.
cpp_std
cpp_std, hangi C standardı sürümünün kullanılacağını gösteren bir dizedir. Geçerli değerler:
"gnu++11"gibi belirli bir sürümbuild/soong/cc/config/global.goiçinde derleme sistemi tarafından tanımlanan bir değer olan"experimental", kullanılabilir olduğunda C++1z gibi taslak sürümleri kullanabilir.- Derleme sistemi varsayılanının kullanılması gerektiğini belirten ayarlanmamış veya
"".
Bu ayar belirlenirse dosya uzantısı yoksayılır ve başlığın C++ başlığı olduğu varsayılır. Bu ayar, c_std ile aynı anda yapılamaz.
cflags
cflags, başlıkların doğru şekilde yorumlanması için gereken Clang işaretlerinin dize listesini sağlar.
custom_bindgen
İleri seviye kullanım alanları için bindgen, özel bir Rust ikili programının parçası olarak değiştirilebilen bir API sağlayan bir kitaplık olarak kullanılabilir. custom_bindgen alanı, normal bindgen ikili programı yerine bindgen API'sini kullanan bir rust_binary_host modülünün modül adını alır.
Bu özel ikili, bindgen'ya benzer şekilde bağımsız değişkenler beklemelidir. Örneğin:
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
Bu işlemlerin çoğu bindgen kitaplığı tarafından gerçekleştirilir. Bu kullanımın bir örneğini görmek için external/rust/crates/libsqlite3-sys/android/build.rs adresini ziyaret edin.
Ayrıca, kitaplığın derlenmesini kontrol etmek için kitaplık özelliklerinin tamamı kullanılabilir. Ancak bu özelliklerin tanımlanması veya değiştirilmesi nadiren gerekir.
handle_static_inline ve static_inline_library
Bu iki özellik birlikte kullanılmak üzere tasarlanmıştır ve dışa aktarılan bindgen bağlamalarına dahil edilebilecek statik satır içi işlevler için sarmalayıcıların oluşturulmasına olanak tanır.
Bu işlevleri kullanmak için handle_static_inline: true ve static_inline_library değerini, rust_bindgen modülünü kaynak girişi olarak tanımlayan ilgili cc_library_static olarak ayarlayın.
Örnek kullanım:
rust_bindgen {
name: "libbindgen",
wrapper_src: "src/any.h",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
// Produce bindings for static inline fucntions
handle_static_inline: true,
static_inline_library: "libbindgen_staticfns"
}
cc_library_static {
name: "libbindgen_staticfns",
// This is the rust_bindgen module defined above
srcs: [":libbindgen"],
// The include path to the header file in the generated c file is
// relative to build top.
include_dirs: ["."],
}