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 bir paket 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 bölümüne bakın.
Rust'tan çağrılacak örnek C kitaplığı
Aşağıda, Rust'ta kullanılmak üzere bir yapı ve işlev tanımlayan bir C kitaplığı örneği 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ı başlıkları içeren bir sarmalayıcı başlık (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 ile ilgili 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) }
}
Ardından, ikili dosyayı oluşturmak için m hello_bindgen'ı arayın.
Test bindgen bağlamaları
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.
rust_test içinde bir external/rust/hello_bindgen/Android.bp modülü tanımlayarak bunlar için test ikili programı oluşturabilirsiniz:
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 küçük olur. Bunun nedeni, tür tanımları, işlev imzaları ve ilgili sabitlerden oluşmalarıdır. Bu nedenle, bu kitaplıkları dinamik olarak bağlamak gereksizdir. Bu modüller için dinamik bağlantıyı devre dışı bıraktık. Böylece, bu modüller rustlibs ile kullanıldığında statik bir varyant otomatik olarak seçilir.
Varsayılan olarak, rust_bindgen modüllerinin visibility özelliği [":__subpackages__"]'dir. Bu özellik, aynı Android.bp dosyasındaki veya dizin hiyerarşisinde bu dosyanın altında yer alan modüllerin dosyayı görmesine izin verir. Bu durum 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.
Bağlamalarla aynı dizin ağacına eklediğiniz oluşturulmuş modülün etrafında, diğer geliştiricilerin kullanması için tasarlanmış güvenli bir sarmalayıcı kitaplık sağlamanız gerekir. Bu yöntem kullanım alanınız için işe yaramazsa visibility'a ek paketler ekleyebilirsiniz.
Ek görünürlük kapsamları eklerken, gelecekte aynı işleme bağlanabilecek iki kapsam eklemeyin. Aksi takdirde bağlantı oluşturulamayabilir.
Önemli rust_bindgen özellikleri
Bu bölümde tanımlanan özellikler, tüm modüller için geçerli olan önemli ortak özelliklere ek olarak verilmiştir. Bunlar, Rust bindgen modülleri için ö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ık özellikleri başlıklı makaleyi inceleyin.
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 değilse bunun bir C başlığı 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. Bu alan, bağlamaları bir paket olarak kullanıyor olsanız bile 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 üzerinden sandık olarak değil, 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 olun. Bağımlı modüller, SourceProvider
srcs içinde tanımlanan tüm bağımlılıkların kaynaklarını ortak bir OUT_DIR dizinine kopyalar. Bu nedenle, source_stem içindeki ç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 burada listelenmiştir:
- Belirli bir sürüm (ör.
gnu11) experimental,build/soong/cc/config/global.goiçinde derleme sistemi tarafından tanımlanan bir değerdir. Bu değer,build/soong/cc/config/global.goiçinde kullanılabildiğinde 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 ayarlanamaz.
cpp_std
cpp_std, hangi C standardı sürümünün kullanılacağını gösteren bir dizedir. Geçerli değerler burada listelenmiştir:
- Belirli bir sürüm (ör.
gnu++11) experimental,build/soong/cc/config/global.goiçinde derleme sistemi tarafından tanımlanan bir değerdir. Bu değer,build/soong/cc/config/global.goiçinde kullanılabildiğinde 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 ayarlanamaz.
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ımla ilgili bir örnek 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 functions
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: ["."],
}