Auto generate rust bindings using rust bindgen (#4723)

* squash bingen work

* check generated code in ci
This commit is contained in:
youyuanwu 2025-01-08 03:51:32 -08:00 коммит произвёл GitHub
Родитель 86bab8a85d
Коммит cc31197848
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
8 изменённых файлов: 11530 добавлений и 2 удалений

4
.github/workflows/cargo.yml поставляемый
Просмотреть файл

@ -17,7 +17,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-xlarge]
features: ["", "--features static", "--features schannel", "--features schannel,static"]
features: ["", "--features static", "--features schannel", "--features schannel,static", "--features overwrite"]
exclude:
- os: ubuntu-latest
features: "--features schannel"
@ -60,6 +60,8 @@ jobs:
run: cargo clippy --all-targets -- -D warnings
- name: Cargo build
run: cargo build --all ${{ matrix.features }}
- name: Check all generated files with git
run: git diff --exit-code
- name: Cargo test
run: cargo test --all ${{ matrix.features }}
- name: Cargo Publish (dry run)

Просмотреть файл

@ -34,7 +34,7 @@ include = [
"/submodules/openssl/VMS",
"/submodules/xdp-for-windows/published/external",
"/scripts/build.rs",
"/src/*.rs",
"/src/**/*.rs",
"/src/bin",
"/src/core",
"/src/inc",
@ -49,9 +49,12 @@ default = []
schannel = []
static = []
preview-api = []
# Overwrite generated binding by reruning the bindgen
overwrite = [ "dep:bindgen" ]
[build-dependencies]
cmake = "0.1"
bindgen = { version = "0.71", optional = true }
[dependencies]
bitfield = "0.17.0"

Просмотреть файл

@ -63,4 +63,47 @@ fn main() {
}
println!("cargo:rustc-link-lib=static=msquic");
}
#[cfg(all(feature = "overwrite", not(target_os = "macos")))]
overwrite_bindgen();
}
/// Read the c header and generate rust bindings.
/// TODO: macos currently uses linux bindings.
#[cfg(all(feature = "overwrite", not(target_os = "macos")))]
fn overwrite_bindgen() {
let manifest_dir = std::path::PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let root_dir = manifest_dir;
// include msquic headers
let inc_dir = root_dir.join("src").join("inc");
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header(root_dir.join("src/ffi/wrapper.hpp").to_str().unwrap())
.clang_arg(format!("-I{}", inc_dir.to_string_lossy()))
.allowlist_recursively(false)
.allowlist_item("QUIC.*|BOOLEAN|BYTE|HQUIC|HRESULT")
.blocklist_type("QUIC_ADDR")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write bindings to the sys mod.
let out_path = root_dir.join("src/ffi");
#[cfg(target_os = "windows")]
let binding_file = "win_bindings.rs";
#[cfg(target_os = "linux")]
let binding_file = "linux_bindings.rs";
// TODO: support macos.
bindings
.write_to_file(out_path.join(binding_file))
.expect("Couldn't write bindings!");
}

5695
src/ffi/linux_bindings.rs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

20
src/ffi/mod.rs Normal file
Просмотреть файл

@ -0,0 +1,20 @@
#![allow(
non_snake_case,
non_upper_case_globals,
non_camel_case_types,
dead_code,
clippy::all
)]
pub type QUIC_ADDR = std::ffi::c_void;
// TODO: macos currently is using the linux bindings.
#[cfg(not(target_os = "windows"))]
pub type sa_family_t = u16;
#[cfg(not(target_os = "windows"))]
include!("linux_bindings.rs");
#[cfg(target_os = "windows")]
pub type ADDRESS_FAMILY = u16;
#[cfg(target_os = "windows")]
include!("win_bindings.rs");

5720
src/ffi/win_bindings.rs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

44
src/ffi/wrapper.hpp Normal file
Просмотреть файл

@ -0,0 +1,44 @@
// header wrapper to feed into bindgen
#include "msquic.h"
// bindgen or clang has problem with c marcro functions
// This forces clang to evaluate macros.
// Cannot reuse QUIC_STATUS as the name because it is an macro type.
typedef enum QUIC_ERROR {
SUCCESS = QUIC_STATUS_SUCCESS,
PENDING = QUIC_STATUS_PENDING,
CONTINUE = QUIC_STATUS_CONTINUE,
OUT_OF_MEMORY = QUIC_STATUS_OUT_OF_MEMORY,
INVALID_PARAMETER = QUIC_STATUS_INVALID_PARAMETER,
INVALID_STATE = QUIC_STATUS_INVALID_STATE,
NOT_SUPPORTED = QUIC_STATUS_NOT_SUPPORTED,
NOT_FOUND = QUIC_STATUS_NOT_FOUND,
BUFFER_TOO_SMALL = QUIC_STATUS_BUFFER_TOO_SMALL,
HANDSHAKE_FAILURE = QUIC_STATUS_HANDSHAKE_FAILURE,
ABORTED = QUIC_STATUS_ABORTED,
ADDRESS_IN_USE = QUIC_STATUS_ADDRESS_IN_USE,
INVALID_ADDRESS = QUIC_STATUS_INVALID_ADDRESS,
CONNECTION_TIMEOUT = QUIC_STATUS_CONNECTION_TIMEOUT,
CONNECTION_IDLE = QUIC_STATUS_CONNECTION_IDLE,
UNREACHABLE = QUIC_STATUS_UNREACHABLE,
INTERNAL_ERROR = QUIC_STATUS_INTERNAL_ERROR,
CONNECTION_REFUSED = QUIC_STATUS_CONNECTION_REFUSED,
PROTOCOL_ERROR = QUIC_STATUS_PROTOCOL_ERROR,
VER_NEG_ERROR = QUIC_STATUS_VER_NEG_ERROR,
TLS_ERROR = QUIC_STATUS_TLS_ERROR,
USER_CANCELED = QUIC_STATUS_USER_CANCELED,
ALPN_NEG_FAILURE = QUIC_STATUS_ALPN_NEG_FAILURE,
STREAM_LIMIT_REACHED = QUIC_STATUS_STREAM_LIMIT_REACHED,
ALPN_IN_USE = QUIC_STATUS_ALPN_IN_USE,
CLOSE_NOTIFY = QUIC_STATUS_CLOSE_NOTIFY,
BAD_CERTIFICATE = QUIC_STATUS_BAD_CERTIFICATE,
UNSUPPORTED_CERTIFICATE = QUIC_STATUS_UNSUPPORTED_CERTIFICATE,
REVOKED_CERTIFICATE = QUIC_STATUS_REVOKED_CERTIFICATE,
EXPIRED_CERTIFICATE = QUIC_STATUS_EXPIRED_CERTIFICATE,
UNKNOWN_CERTIFICATE = QUIC_STATUS_UNKNOWN_CERTIFICATE,
REQUIRED_CERTIFICATE = QUIC_STATUS_REQUIRED_CERTIFICATE,
CERT_EXPIRED = QUIC_STATUS_CERT_EXPIRED,
CERT_UNTRUSTED_ROOT = QUIC_STATUS_CERT_UNTRUSTED_ROOT,
CERT_NO_CERT = QUIC_STATUS_CERT_NO_CERT
} QUIC_ERROR;

Просмотреть файл

@ -23,6 +23,7 @@ use std::result::Result;
use std::sync::Once;
#[macro_use]
extern crate bitfield;
pub mod ffi;
//
// The following starts the C interop layer of MsQuic API.