### Install CI dependencies Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Zlib.md Command to install required system packages for building Zlib bindings in a CI environment. ```bash apt-get install libclang-dev zlib1g-dev ``` -------------------------------- ### Install ClangSharpPInvokeGenerator Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Install the tool as a .NET global tool to enable command-line usage. ```bash dotnet tool install --global ClangSharpPInvokeGenerator ``` -------------------------------- ### Configure bnd-linux dependencies Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Example of selecting specific features when adding bnd-linux as a dependency. ```toml [dependencies] bnd-linux = { path = "../bnd-linux", features = ["posix_fcntl", "posix_unistd", "linux_epoll"] } ``` -------------------------------- ### Define Partition Header Includes Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Background.md Example of a main.cpp file used to include necessary Windows headers for a specific partition. ```cpp #include "intrinfix.h" #include "windows.fixed.h" #include #include #include #include #include #include ``` -------------------------------- ### Install OpenSSL Dependencies Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Required system packages for building and testing OpenSSL bindings on Linux. ```bash apt-get install libssl-dev libclang-dev ``` -------------------------------- ### Clang AST Representation Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/bugs/SonarForwardDeclSkipsEnum.md Example of the Clang AST structure showing a forward declaration followed by a full definition. ```text EnumDecl fs_value_type ← forward decl (no children) ... EnumDecl prev 0x... fs_value_type ← definition (has children) ``` -------------------------------- ### Clang Header Search Path Resolution Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md Example output showing the order in which clang resolves system headers on Debian/Ubuntu x86-64. ```text #include <...> search starts here: /usr/lib/llvm-18/lib/clang/18/include /usr/local/include /usr/include/x86_64-linux-gnu ← arch-specific, searched first /usr/include ← generic End of search list. ``` -------------------------------- ### Define __SOCKADDR_COMMON macro Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md Example of the glibc macro used to define the sockaddr structure. ```c #define __SOCKADDR_COMMON(sa_prefix) sa_family_t sa_prefix##family struct sockaddr { __SOCKADDR_COMMON(sa_); // expands to: sa_family_t sa_family; char sa_data[14]; }; ``` -------------------------------- ### Emit TypeRef Metadata Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/CrossWinmdReferences.md Example of the resulting metadata entry for an external type reference. ```text TypeRef(namespace="libc.posix.time", name="tm") ``` -------------------------------- ### Define Cargo.toml feature flags Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Example of the auto-generated feature structure within Cargo.toml. ```toml [features] Foundation = [] # generated features linux = ["Foundation"] linux_epoll = ["linux"] linux_eventfd = ["linux"] ... posix = ["Foundation"] posix_dirent = ["posix"] posix_signal = ["posix"] ... ``` -------------------------------- ### Define struct addrinfo Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md Example of a self-referential C structure used in network programming. ```c struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socklen_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; // self-referential pointer }; ``` -------------------------------- ### Define Cacheline-Aligned Structs in C Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/CachelineAlignedFix.md Example C structures demonstrating the use of __attribute__((aligned(64))) and the resulting field offsets. ```c struct AlignedInner { long a; long b; } __attribute__((aligned(64))); struct EmbeddingAligned { long before_a; // offset 0 long before_b; // offset 8 struct AlignedInner aligned_member; // offset 64 (not 16!) int after; // offset 128 }; // sizeof(EmbeddingAligned) == 192 ``` -------------------------------- ### NativeBitfieldAttribute Usage in C# Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/bugs/BitfieldLayoutNotPreserved.md Example of how NativeBitfieldAttribute is used in the win32metadata ecosystem to define bitfield layouts. ```csharp public struct FLICK_DATA { [NativeBitfield("iFlickActionCommandCode", 0L, 5L)] [NativeBitfield("iFlickDirection", 5L, 3L)] [NativeBitfield("fControlModifier", 8L, 1L)] // ... public int _bitfield; } ``` -------------------------------- ### Triggering C fixed-size array parameter Source: https://github.com/youyuanwu/bnd/blob/main/docs/bugs/element-type-array-mismatch.md Example of a C function signature that triggers the ELEMENT_TYPE_ARRAY encoding issue. ```c // extern int futimens(int __fd, const struct timespec __times[2]); ``` -------------------------------- ### Configure Partition in bnd-linux.toml Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Define the namespace, library, and headers for the new partition. Ensure the POSIX types partition remains first. ```toml [[partition]] namespace = "libc.." library = "c" headers = ["
.h"] traverse = [ "
.h", "bits/.h", ] ``` -------------------------------- ### Configure multiple partitions Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/AuthoringBindings.md Use multiple partition entries to handle different headers or shared libraries within the same configuration. ```toml [[partition]] namespace = "zstd.compress" library = "zstd" headers = ["zstd.h"] traverse = ["zstd.h"] [[partition]] namespace = "zstd.dict" library = "zstd" headers = ["zstd.h", "zdict.h"] traverse = ["zdict.h"] ``` -------------------------------- ### Implement the generator main entry point Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Initializes tracing and invokes the generation process. ```rust use std::path::PathBuf; fn main() { tracing_subscriber::fmt() .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .init(); let workspace_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(".."); let output_dir = workspace_dir.join("bnd-zstd"); bnd_zstd_gen::generate(&output_dir); println!("Generated bnd-zstd crate at {}", output_dir.display()); } ``` -------------------------------- ### Dependency Graph Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Visual representation of the BndLinux build and dependency flow. ```text bnd-linux-gen │ ▼ bnd-linux.winmd (libc.posix.* + libc.linux.*) │ ▼ bnd-linux (crate) │ ▼ bnd-openssl-gen ──▶ reads bnd-linux.winmd --reference bnd_linux,full,libc │ ▼ bnd-openssl (crate) ──▶ depends on bnd-linux ``` -------------------------------- ### Implement simplified emitter Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Pseudocode demonstrating the minimum viable pipeline for compiling generated C# files into a WinMD file. ```csharp // Pseudocode for the simplified pipeline var trees = Directory.GetFiles("obj/generated", "*.cs", SearchOption.AllDirectories) .Select(f => CSharpSyntaxTree.ParseText(File.ReadAllText(f), null, f)); var compilation = CSharpCompilation.Create( null, trees, new[] { MetadataReference.CreateFromFile(netstandardDllPath) }, new CSharpCompilationOptions(OutputKind.WindowsRuntimeMetadata, allowUnsafe: true)); // Apply remaps if needed // trees = trees.Select(t => MetadataSyntaxTreeCleaner.CleanSyntaxTree(t, remaps, ...)); var sourceCompilation = new ClangSharpSourceCompilation(compilation, typeImports); var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( sourceCompilation, typeImports: new Dictionary(), reducePointerLevels: new HashSet(), forceGuidConsts: new HashSet(), version: new Version(1, 0, 0, 0), outputFileName: "output/MyLibrary.winmd"); ``` -------------------------------- ### LHASH macro structure definition Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Example of the struct generated by the DEFINE_LHASH_OF_INTERNAL macro containing an anonymous union. ```c struct lhash_st_ERR_STRING_DATA { union lh_ERR_STRING_DATA_dummy { ... } dummy; // ... }; ``` -------------------------------- ### Configure multi-partition build in multi.toml Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Testing.md TOML configuration defining multiple partitions for the winmd output. ```toml [output] name = "MultiTest" file = "multi_test.winmd" [[partition]] namespace = "MultiTest.Types" library = "simple" headers = ["types.h"] traverse = ["types.h"] [[partition]] namespace = "MultiTest.Widgets" library = "simple" headers = ["types.h", "widget.h"] traverse = ["widget.h"] ``` -------------------------------- ### Partition Configuration for stdio.h Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md Configuration block defining the namespace, library, and headers for the stdio.h partition. ```toml [[partition]] namespace = "posix.stdio" library = "c" headers = ["stdio.h"] traverse = [ "stdio.h", "bits/stdio_lim.h", "bits/types/__fpos_t.h", "bits/types/__mbstate_t.h", "bits/types/struct_FILE.h", "bits/types/cookie_io_functions_t.h", ] ``` -------------------------------- ### Define 1D Anonymous Struct Array Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/bugs/AnonymousStructArrayField.md Example of a 1D array of anonymous structs that is currently supported. ```c struct { uint16_t vlan_id; uint64_t pools; } pool_map[RTE_ETH_VMDQ_MAX_VLAN_FILTERS]; ``` -------------------------------- ### Configure bnd-winmd via TOML Source: https://github.com/youyuanwu/bnd/blob/main/bnd-winmd/README.md Define output settings and partitions in a TOML file to map C headers to WinMD namespaces. ```toml [output] name = "MyLib" file = "mylib.winmd" # Optional: extra include search paths # include_paths = ["/usr/include/x86_64-linux-gnu"] [[partition]] namespace = "MyLib" library = "mylib" headers = ["mylib.h"] traverse = ["mylib.h"] ``` -------------------------------- ### Example of dropped anonymous union Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/AnonymousUnionFix.md Demonstrates a C struct containing an anonymous union that was previously ignored during extraction. ```c struct inode { u64 i_ino; union { unsigned int i_nlink; unsigned int __i_nlink; }; // was dropped dev_t i_rdev; }; ``` -------------------------------- ### Combine metadata and reference flags Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/CrossWinmdReferences.md Full command configuration to resolve dependencies from an external crate while filtering output to the target namespace. ```bash --in bnd-linux.winmd # metadata for resolution --in openssl.winmd # metadata to generate --filter openssl # only emit openssl.* types --reference bnd_linux,full,libc # libc.* types come from bnd_linux crate ``` -------------------------------- ### C Struct with Bitfields Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/bugs/BitfieldLayoutNotPreserved.md Example of a C struct containing adjacent bitfields that require merging to preserve memory layout. ```c struct { unsigned a:4; // offset 0, width 4 unsigned b:4; // offset 4, width 4 unsigned c:16; // offset 8, width 16 int x; // regular field }; ``` -------------------------------- ### Configure build.rs for Zlib bindings Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Zlib.md This script generates winmd files, creates Rust bindings using windows-bindgen, and links the system zlib library. ```rust fn main() { let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let fixtures = manifest_dir.join("../../tests/fixtures/zlib"); // Step 1: Generate winmd let winmd_path = out_dir.join("zlib.winmd"); bnd_winmd::run(&fixtures.join("zlib.toml"), Some(&winmd_path)) .expect("bnd-winmd failed"); // Step 2: Generate bindings (flat + sys for multi-partition) let bindings_path = manifest_dir.join("src/bindings.rs"); windows_bindgen::bindgen([ "--in", winmd_path.to_str().unwrap(), "--out", bindings_path.to_str().unwrap(), "--filter", "Zlib", "--flat", "--sys", ]).unwrap(); // Step 3: Link system libz println!("cargo:rustc-link-lib=dylib=z"); } ``` -------------------------------- ### Define 2D Anonymous Struct Array Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/bugs/AnonymousStructArrayField.md Example of a 2D array of anonymous structs that currently faces upstream limitations. ```c struct rte_eth_dcb_tc_queue_mapping { struct { uint16_t base; uint16_t nb_queue; } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS]; }; ``` -------------------------------- ### Implement the product crate library Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Define the library module and alias the macros crate for proper resolution. ```rust extern crate bnd_macros as windows_link; pub mod zstd; ``` -------------------------------- ### Configure Partition for dirent.h Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md Defines the partition namespace and library headers for the dirent implementation. ```toml [[partition]] namespace = "posix.dirent" library = "c" headers = ["dirent.h"] traverse = ["dirent.h", "bits/dirent.h"] ``` -------------------------------- ### Registry Summary Log Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/DebuggingFeatures.md Displays the total count of types, partitions, injected types, and imported types after the registry is built. ```text INFO type registry built types=342 partitions=8 injected=3 imported=45 ``` -------------------------------- ### Initialize ClangSharpSourceCompilation Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Defines the entry point for creating a compilation instance with necessary mappings and architecture settings. ```csharp public static ClangSharpSourceCompilation Create( string sourceDirectory, // path to generated .cs files string arch, // "x64", "x86", "arm64" Dictionary remaps, Dictionary enumAdditions, // const → enum member mappings Dictionary typeImports, // type → external winmd references Dictionary requiredNamespaces, // type → correct namespace HashSet reducePointerLevels, // types needing pointer reduction IReadOnlyCollection addedRefs, // additional assembly references Dictionary staticLibs, // function → DLL name mapping Dictionary apiNamesToNamespaces // function → namespace override ) ``` -------------------------------- ### OpenSSL Library Partitioning Diagram Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Visual representation of how OpenSSL headers map to specific libraries and the resulting winmd structure. ```text openssl/types.h ──────────────────────────────────┐ openssl/crypto.h ──→ openssl.crypto (crypto) │ openssl/err.h ──→ (skipped — LHASH issue) │ openssl/rand.h ──→ openssl.rand (crypto) │ openssl/bn.h ──→ openssl.bn (crypto) ├── openssl.winmd openssl/evp.h ──→ openssl.evp (crypto) │ openssl/sha.h ──→ openssl.sha (crypto) │ openssl/bio.h ──→ openssl.bio (crypto) │ openssl/ssl.h ──→ openssl.ssl (ssl) │ │ openssl.winmd ◄──────────┘ │ windows-bindgen --sys --package │ ▼ bnd-openssl/src/openssl/ ──→ links libssl + libcrypto ├── mod.rs #[cfg(feature)] pub mod … ├── types/mod.rs opaque typedefs ├── crypto/mod.rs version, memory ├── evp/mod.rs digest, cipher ├── ssl/mod.rs TLS protocol └── … ``` -------------------------------- ### Use OpenSSL EVP and SHA functions Source: https://github.com/youyuanwu/bnd/blob/main/bnd-openssl/README.md Demonstrates basic usage of EVP and SHA modules. All function calls require an unsafe block as they interface directly with OpenSSL shared libraries. ```rust use bnd_openssl::openssl::{evp, sha}; unsafe { let md = evp::EVP_sha256(); assert!(!md.is_null()); assert_eq!(sha::SHA256_DIGEST_LENGTH, 32); } ``` -------------------------------- ### Configure Partition Response File Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Background.md Response file settings specifying headers to traverse and the target C# namespace for ClangSharp. ```text --traverse /um/winreg.h /um/statehelpers.h /um/regstr.h --namespace Windows.Win32.System.Registry ``` -------------------------------- ### Configure OpenSSL bindings in openssl.toml Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Defines the include paths, output file, and partitions for various OpenSSL libraries to generate Windows metadata. ```toml include_paths = ["/usr/include/x86_64-linux-gnu", "/usr/include"] [output] name = "openssl" file = "openssl.winmd" # Partition 1: Opaque type forward declarations # 120 typedef struct foo_st FOO patterns — no functions [[partition]] namespace = "openssl.types" library = "crypto" headers = ["openssl/types.h"] traverse = ["openssl/types.h"] # Partition 2: Library version + core utilities [[partition]] namespace = "openssl.crypto" library = "crypto" headers = ["openssl/crypto.h"] traverse = ["openssl/crypto.h", "bits/types/struct_tm.h", "bits/types/struct_FILE.h"] # Partition 3: Random number generation [[partition]] namespace = "openssl.rand" library = "crypto" headers = ["openssl/rand.h"] traverse = ["openssl/rand.h"] # Partition 4: Error queue # NOTE: openssl/err.h uses DEFINE_LHASH_OF_INTERNAL which generates # a struct with an inline union field (lh_ERR_STRING_DATA_dummy) that # bnd-winmd extracts but cannot emit correctly. Skipped for now. # [[partition]] # namespace = "openssl.err" # library = "crypto" # headers = ["openssl/err.h"] # traverse = ["openssl/err.h"] # Partition 5: Big number arithmetic (opaque BIGNUM) [[partition]] namespace = "openssl.bn" library = "crypto" headers = ["openssl/bn.h"] traverse = ["openssl/bn.h"] # Partition 6: EVP high-level crypto (digest, cipher) [[partition]] namespace = "openssl.evp" library = "crypto" headers = ["openssl/evp.h"] traverse = ["openssl/evp.h"] # Partition 7: SHA one-shot hash + context structs [[partition]] namespace = "openssl.sha" library = "crypto" headers = ["openssl/sha.h"] traverse = ["openssl/sha.h"] # Partition 8: BIO I/O abstraction [[partition]] namespace = "openssl.bio" library = "crypto" headers = ["openssl/bio.h"] traverse = ["openssl/bio.h"] # Partition 9: TLS protocol — links libssl [[partition]] namespace = "openssl.ssl" library = "ssl" headers = ["openssl/ssl.h"] traverse = ["openssl/ssl.h", "openssl/tls1.h"] ``` -------------------------------- ### OpenSSL Iterative Development Phases Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Summary of the phased approach taken to expand OpenSSL partition support. ```text Phase 1: Types + Crypto + Rand ← proved multi-partition extraction - Fixed: crypto traverse needed bits/types/struct_tm.h, struct_FILE.h - Fixed: include_paths needed /usr/include/x86_64-linux-gnu Phase 2: + Bn + Evp + Sha + Bio ← bulk expansion, all worked first try Phase 3: + Ssl ← fixed traverse (needed openssl/tls1.h) Phase 4: Err attempted → skipped ← LHASH macro generates unresolvable types ``` -------------------------------- ### Configure Zlib bindings in TOML Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Zlib.md Defines the output file and partitions for Zlib headers, ensuring typedefs and structs are mapped to the correct namespaces. ```toml [output] name = "Zlib" file = "zlib.winmd" # Partition 1: base typedefs from zconf.h [[partition]] namespace = "Zlib.Types" library = "z" headers = ["/usr/include/zconf.h"] traverse = ["/usr/include/zconf.h"] # Partition 2: zlib.h structs, functions, constants [[partition]] namespace = "Zlib" library = "z" headers = ["/usr/include/zlib.h"] traverse = ["/usr/include/zlib.h"] ``` -------------------------------- ### Add bnd-winmd dependencies Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/AuthoringBindings.md Include the necessary macros and build-time dependencies in your Cargo.toml file. ```toml [dependencies] bnd-macros = "0.0.1" [build-dependencies] bnd-winmd = "0.1" windows-bindgen = "0.66" ``` -------------------------------- ### Run Workspace Tests Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Command to verify all tests within the workspace. ```bash cargo test ``` -------------------------------- ### Use POSIX and Linux system APIs Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Demonstrates importing and using both POSIX file operations and Linux-specific epoll functionality within an unsafe block. ```rust use bnd_linux::libc::posix::{fcntl, stat, unistd}; use bnd_linux::libc::linux::{epoll, eventfd, timerfd}; // POSIX: create a file let path = c"/tmp/example.txt"; let fd = unsafe { fcntl::creat(path.as_ptr(), 0o644) }; assert!(fd >= 0); unsafe { unistd::close(fd) }; // Linux: create an epoll instance let epfd = unsafe { epoll::epoll_create1(0) }; assert!(epfd >= 0); ``` -------------------------------- ### Implement the generator library Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Contains the logic to run bnd-winmd and windows-bindgen to generate the bindings. ```rust use std::path::Path; pub fn generate(output_dir: &Path) { let workspace_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join(".."); let fixtures = workspace_dir.join("tests/fixtures/zstd"); let winmd_path = output_dir.join("bnd-zstd.winmd"); bnd_winmd::run(&fixtures.join("zstd.toml"), Some(&winmd_path)) .expect("bnd-winmd failed"); windows_bindgen::bindgen([ "--in", winmd_path.to_str().unwrap(), "--out", output_dir.to_str().unwrap(), "--filter", "zstd", "--sys", "--package", ]).unwrap(); std::fs::remove_file(&winmd_path).ok(); } ``` -------------------------------- ### Generate .winmd from configuration Source: https://github.com/youyuanwu/bnd/blob/main/bnd-winmd/README.md Use the run function to generate a .winmd file based on a TOML configuration, typically within a build.rs script. ```rust use std::path::Path; bnd_winmd::run(Path::new("bnd-winmd.toml"), None).unwrap(); ``` -------------------------------- ### BND Partition Layout Configuration Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md TOML configuration for defining include paths and partitions for POSIX system headers. ```toml include_paths = [ "/usr/include/x86_64-linux-gnu", "/usr/include", ] [output] name = "posix" file = "bnd-posix.winmd" # Partition 1: fcntl — creat + O_* flags # open/openat/fcntl are variadic and will be auto-skipped [[partition]] namespace = "posix.fcntl" library = "c" headers = ["fcntl.h"] traverse = ["fcntl.h", "bits/fcntl-linux.h"] # Partition 2: unistd — read/write/close/lseek [[partition]] namespace = "posix.unistd" library = "c" headers = ["unistd.h"] traverse = ["unistd.h"] # Partition 3: sys/stat — struct stat + stat/fstat/chmod + S_* constants [[partition]] namespace = "posix.stat" library = "c" headers = ["sys/stat.h"] traverse = [ "sys/stat.h", "bits/struct_stat.h", # struct stat definition "bits/types/struct_timespec.h", # struct timespec for st_atim etc. ] ``` -------------------------------- ### Crate Layout Structure Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Zlib.md Directory structure for the bnd-winmd zlib testing environment. ```text bnd-winmd/tests/ ├── fixtures/zlib/ │ └── zlib.toml ← two-partition config ├── roundtrip_zlib.rs ← 6 winmd roundtrip tests (own LazyLock) tests/e2e-zlib/ ├── Cargo.toml ├── build.rs ← bnd-winmd + windows-bindgen + link libz ├── src/ │ ├── lib.rs ← mod bindings; pub use bindings*; │ └── bindings.rs ← generated (216 lines) └── tests/ └── zlib_e2e.rs ← 12 FFI integration tests ``` -------------------------------- ### Write E2E Tests Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Create a test file and add the corresponding feature to the test crate's Cargo.toml. ```rust use bnd_linux::libc::::; #[test] fn _constants() { assert_eq!(::SOME_CONST, expected_value); } ``` -------------------------------- ### Configure the product crate Cargo.toml Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Define the package metadata and dependencies, ensuring the generated features marker is present. ```toml [package] name = "bnd-zstd" version = "0.1.0" edition = "2024" [dependencies] bnd-macros.workspace = true [features] default = ["zstd"] Foundation = [] # generated features ``` -------------------------------- ### Generate bindings Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Commands to execute the generator and optionally enable debug logging for troubleshooting. ```sh cargo run -p bnd-zstd-gen ``` ```sh RUST_LOG=bnd_winmd=debug cargo run -p bnd-zstd-gen ``` -------------------------------- ### Initialize CMake Project and Cargo Source: https://github.com/youyuanwu/bnd/blob/main/CMakeLists.txt Sets the minimum CMake version and locates the Cargo executable required for project tasks. ```cmake cmake_minimum_required(VERSION 3.20) project(bnd NONE) # no native compiler needed find_program(CARGO cargo REQUIRED) ``` -------------------------------- ### Configure bnd-linux dependencies Source: https://github.com/youyuanwu/bnd/blob/main/bnd-linux/README.md Add the crate to your Cargo.toml file, specifying only the required feature flags to minimize dependencies. ```toml [dependencies] bnd-linux = { version = "0.0.1", features = ["posix_socket", "posix_signal", "linux_epoll"] } ``` -------------------------------- ### Configure build-time linking Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Use build.rs to specify link directives if the library requires them. ```rust fn main() { println!("cargo:rustc-link-lib=zstd"); } ``` -------------------------------- ### Define the extraction configuration Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Create a TOML file to specify the library name, output file, and header parsing rules. ```toml # Optional: extra include search paths for platform headers # include_paths = ["/usr/include/x86_64-linux-gnu"] [output] name = "zstd" file = "zstd.winmd" [[partition]] namespace = "zstd" library = "zstd" headers = ["zstd.h"] traverse = ["zstd.h"] ``` -------------------------------- ### Use bnd-linux FFI bindings Source: https://github.com/youyuanwu/bnd/blob/main/bnd-linux/README.md Import the desired modules and invoke the FFI functions within an unsafe block, ensuring all C-level preconditions are met. ```rust use bnd_linux::libc::posix::signal::*; use bnd_linux::libc::linux::epoll::*; // All FFI functions are unsafe let epfd = unsafe { epoll_create1(0) }; assert!(epfd >= 0); unsafe { raise(0) }; ``` -------------------------------- ### Configure ClangSharp Response File Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Define input files, output directories, namespaces, and ClangSharp-specific behaviors in a .rsp file. ```rsp # Input --file my_header.h # Where to find includes --include-directory /usr/include --include-directory ./vendor/include # Output directory --output ./generated/cs # Namespace for generated types --namespace MyLibrary.Interop # Only traverse (emit types from) these files, not all transitive includes --traverse my_header.h # Language mode -x c # or: -x c++ # Header to prepend (for platform defines, missing types) --headerFile ./preamble.h # Library path for DllImport --with-librarypath MyFunction=libmylib.so # ClangSharp behavior config --config compatible-codegen generate-native-bitfield-attribute exclude-empty-records exclude-funcs-with-body log-exclusions # Method class name (where free functions go) --methodClassName Apis # Type remapping --remap _some_internal_tag=PublicName # Exclude specific symbols --exclude _INTERNAL_ONLY_STRUCT # Force a symbol to a specific C# type --with-type MY_FLAGS=uint ``` -------------------------------- ### Define 2-partition layout for POSIX sockets Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md An alternative configuration that groups inet, arpa, and netdb headers into a single partition. ```toml # Partition 1: sys/socket.h types + functions [[partition]] namespace = "posix.socket" library = "c" headers = ["/usr/include/sys/socket.h"] traverse = ["/usr/include/sys/socket.h"] # Partition 2: inet + arpa + netdb [[partition]] namespace = "posix.inet" library = "c" headers = [ "/usr/include/netinet/in.h", "/usr/include/arpa/inet.h", "/usr/include/netdb.h", ] traverse = [ "/usr/include/netinet/in.h", "/usr/include/arpa/inet.h", "/usr/include/netdb.h", ] ``` -------------------------------- ### Identify API Surface Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Use grep or clang to inspect header files for external definitions. ```sh grep -E "^extern" /usr/include/
.h clang -E -H /usr/include/
.h 2>&1 | head -80 ``` -------------------------------- ### Project Directory Structure Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/RustGenerator.md Visual representation of the project's file hierarchy, including source modules and test directories. ```text bnd-winmd/ ├── Cargo.toml ├── src/ │ ├── lib.rs # Public API + module declarations │ ├── config.rs # TOML config deserialization │ ├── model.rs # Intermediate types: StructDef, CType, TypeRegistry │ ├── extract.rs # clang Entity/Type → model │ └── emit.rs # model → windows-metadata writer calls └── tests/ ├── roundtrip_simple.rs # simple.h fixture ├── roundtrip_multi.rs # multi-partition fixture ├── roundtrip_posixfile.rs # bnd-linux fixture ├── roundtrip_zlib.rs # zlib system header ├── roundtrip_openssl.rs # openssl multi-library + cross-winmd refs └── roundtrip_validation.rs # pre-emit type-reference validation tests/ ├── fixtures/ │ ├── simple/ (simple.h, simple.toml) │ ├── multi/ (graphics.h, audio.h, multi.toml) │ ├── unresolved/ (unresolved.h, unresolved_dep.h, unresolved.toml) │ └── zlib/ (zlib.toml — references system headers) ├── simple-impl/ # Native C lib for e2e-simple ├── e2e-simple/ # E2E tests (single partition + unions) ├── e2e-multi/ # E2E tests (multi-partition) └── e2e-zlib/ # E2E tests (system header, real libz.so) bnd-linux/ ├── Cargo.toml # Feature-gated sub-modules ├── src/ │ ├── lib.rs # Hand-written module root │ └── libc/ # Auto-generated namespace modules │ ├── mod.rs │ ├── posix/ # POSIX API families │ │ ├── mod.rs │ │ ├── dirent/mod.rs │ │ ├── dl/mod.rs │ │ ├── errno/mod.rs │ │ ├── fcntl/mod.rs │ │ ├── inet/mod.rs │ │ ├── mmap/mod.rs │ │ ├── netdb/mod.rs │ │ ├── pthread/mod.rs │ │ ├── sched/mod.rs │ │ ├── signal/mod.rs │ │ ├── socket/mod.rs │ │ ├── stat/mod.rs │ │ ├── stdio/mod.rs │ │ ├── time/mod.rs │ │ ├── types/mod.rs │ │ └── unistd/mod.rs │ └── linux/ # Linux-specific API families │ └── ... └── tests/ # E2E tests (one per partition) ├── posixfile_e2e.rs # Fcntl/Unistd ├── stat_e2e.rs # Stat ├── mmap_e2e.rs # Mmap ├── dirent_e2e.rs # Dirent ├── dl_e2e.rs # Dlfcn ├── errno_e2e.rs # Errno ├── inet_e2e.rs # Inet ├── netdb_e2e.rs # Netdb ├── pthread_e2e.rs # Pthread ├── sched_e2e.rs # Sched ├── signal_e2e.rs # Signal ├── socket_e2e.rs # Socket ├── stdio_e2e.rs # Stdio └── time_e2e.rs # Time bnd-openssl/ ├── Cargo.toml # Feature-gated sub-modules, depends on bnd-linux ├── build.rs # cargo:rustc-link-lib=crypto / ssl ├── src/ │ ├── lib.rs # Hand-written module root │ └── openssl/ # Auto-generated namespace modules (8 partitions) │ ├── mod.rs │ ├── bio/mod.rs │ ├── bn/mod.rs │ ├── crypto/mod.rs │ ├── evp/mod.rs │ ├── rand/mod.rs │ ├── sha/mod.rs │ ├── ssl/mod.rs │ └── types/mod.rs └── tests/ # E2E tests (one per partition) ├── bio_e2e.rs ├── bn_e2e.rs ├── crypto_e2e.rs ├── evp_e2e.rs ├── rand_e2e.rs ├── sha_e2e.rs └── ssl_e2e.rs ``` -------------------------------- ### Regenerate bindings Source: https://github.com/youyuanwu/bnd/blob/main/bnd-linux/README.md Use the bnd-linux-gen tool to regenerate the bindings from C headers. Do not manually edit the generated files. ```sh cargo run -p bnd-linux-gen ``` -------------------------------- ### Locate netstandard.dll on Linux Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Path to the required netstandard.dll (2.1) on Linux systems for the Emitter component. ```bash $DOTNET_ROOT/packs/NETStandard.Library.Ref/2.1.0/ref/netstandard2.1/netstandard.dll ``` -------------------------------- ### Configure MSBuild Project for WinmdGenerator Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Background.md Define the project SDK and specify header files and namespaces for metadata generation. ```xml output/MyLib.winmd 1.0.0.0 @(Headers) MyLib ``` -------------------------------- ### Configure Flat Mode Bindings Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/AuthoringBindings.md Use flat mode to generate a single output file for bindings. ```rust use std::path::Path; fn main() { println!("cargo:rustc-link-lib=zstd"); let winmd = bnd_winmd::run(Path::new("bnd-winmd.toml"), None).unwrap(); windows_bindgen::bindgen([ "--in", winmd.to_str().unwrap(), "--out", "src/bindings.rs", "--filter", "zstd", "--flat", "--sys", ]).unwrap(); } ``` ```rust extern crate bnd_macros as windows_link; mod bindings; pub use bindings::*; ``` -------------------------------- ### Load metadata with --in Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/CrossWinmdReferences.md Merges multiple WinMD files into a single reader for TypeRef resolution. ```bash --in bnd-linux.winmd --in openssl.winmd ``` -------------------------------- ### Define project directory structure Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Standard layout for a bnd-winmd project including headers, configuration, and optional preamble. ```text project/ ├── headers/ │ ├── mylib.h │ └── mylib_types.h ├── bnd-winmd.toml # Project configuration └── preamble.h # (optional) Platform defines, missing types ``` -------------------------------- ### Reference win32metadata projects via ProjectReference Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Use this XML configuration in a .csproj file to include external win32metadata projects as git submodules. ```xml ``` -------------------------------- ### Configure posix.mmap partition Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md TOML configuration for the posix.mmap partition, specifying the library and headers to traverse. ```toml [[partition]] namespace = "posix.mmap" library = "c" headers = ["sys/mman.h"] traverse = ["sys/mman.h", "bits/mman-linux.h", "bits/mman-map-flags-generic.h"] ``` -------------------------------- ### Configure Package Mode Bindings Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/AuthoringBindings.md Use package mode to generate a module tree with feature-gated sub-modules. ```rust use std::path::Path; fn main() { println!("cargo:rustc-link-lib=zstd"); let winmd = bnd_winmd::run(Path::new("bnd-winmd.toml"), None).unwrap(); windows_bindgen::bindgen([ "--in", winmd.to_str().unwrap(), "--out", env!("CARGO_MANIFEST_DIR"), "--filter", "zstd", "--sys", "--package", ]).unwrap(); } ``` ```toml [features] Foundation = [] # generated features ``` ```rust extern crate bnd_macros as windows_link; pub mod zstd; ``` -------------------------------- ### Specify per-partition clang arguments Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/AuthoringBindings.md Append partition-specific clang flags to the global configuration arguments. ```toml # Global: applied to all partitions clang_args = ["-D_GNU_SOURCE"] [[partition]] namespace = "linux.mount" library = "c" headers = ["sys/mount.h"] traverse = ["sys/mount.h"] # Partition-specific: appended after global args clang_args = ["-D_LINUX_MOUNT_H"] ``` -------------------------------- ### Execute End-to-End Tests Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Testing.md Commands to run specific test partitions or the entire workspace. ```bash cargo test -p e2e-simple ``` ```bash cargo test -p e2e-multi ``` ```bash cargo test --workspace ``` -------------------------------- ### Execute generation command Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/CSharpGenerator.md Command to trigger the generation process. ```text bnd-winmd generate ``` -------------------------------- ### OpenSSL Crate Layout Structure Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/Openssl.md Directory structure showing the separation between the generator crate and the product crate. ```text bnd-openssl-gen/ ← generator (cargo run -p bnd-openssl-gen) ├── Cargo.toml ├── src/ │ ├── lib.rs ← generate(&Path) → bnd-winmd → windows-bindgen --package │ └── main.rs ← fn main() { generate(&bnd_openssl_dir) } └── tests/ └── up_to_date.rs ← regen-to-tempdir and diff bnd-openssl/ ← product crate ├── Cargo.toml ← hand-written header + # generated features ├── build.rs ← emits cargo:rustc-link-lib=crypto/ssl ├── src/ │ ├── lib.rs ← hand-written: pub mod openssl; │ └── openssl/ ← GENERATED by windows-bindgen --package │ ├── mod.rs ← #[cfg(feature="types")] pub mod types; … │ ├── types/mod.rs ← opaque typedefs (EVP_MD, SSL, BIO, …) │ ├── crypto/mod.rs ← OpenSSL_version, OPENSSL_VERSION_* │ ├── rand/mod.rs ← RAND_bytes, RAND_status, … │ ├── bn/mod.rs ← BN_new, BN_free, BN_set_word, … │ ├── evp/mod.rs ← EVP_MD_CTX_new, EVP_DigestInit_ex, … │ ├── sha/mod.rs ← SHA256, SHA_DIGEST_LENGTH, SHA_CTX, … │ ├── bio/mod.rs ← BIO_new, BIO_read, BIO_write, … │ └── ssl/mod.rs ← SSL_CTX_new, SSL_connect, TLS_*, … bnd-openssl-gen/ ├── openssl.toml ← multi-partition config bnd-winmd/tests/ └── roundtrip_openssl.rs ← winmd roundtrip tests ``` -------------------------------- ### Update Partition Configuration Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/CrossWinmdReferences.md Comparison of partition configuration before and after removing system header traversal. ```toml [[partition]] namespace = "openssl.crypto" library = "crypto" headers = ["openssl/crypto.h"] traverse = ["openssl/crypto.h", "bits/types/struct_tm.h", "bits/types/struct_FILE.h"] ``` ```toml [[partition]] namespace = "openssl.crypto" library = "crypto" headers = ["openssl/crypto.h"] traverse = ["openssl/crypto.h"] [[type_import]] winmd = "../bnd-linux/winmd/bnd-linux.winmd" namespace = "libc" ``` -------------------------------- ### Project Directory Structure Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/BndLinux.md Visual representation of the crate layout, including the generator, product, and test crates. ```text bnd-linux-gen/ ← generator (cargo run -p bnd-linux-gen) ├── Cargo.toml ├── bnd-linux.toml ← merged multi-partition config (25 partitions) ├── src/ │ ├── lib.rs ← generate(&Path) → bnd-winmd → windows-bindgen --package │ └── main.rs └── tests/ └── up_to_date.rs ← regen-to-tempdir and diff bnd-linux/ ← product crate ├── Cargo.toml ← hand-written header + auto-generated features ├── winmd/ │ └── bnd-linux.winmd ← preserved for downstream cross-WinMD refs ├── src/ │ ├── lib.rs ← hand-written: pub mod libc; │ └── libc/ ← GENERATED by windows-bindgen --package │ ├── mod.rs │ ├── posix/ │ │ ├── mod.rs │ │ ├── fcntl/mod.rs │ │ ├── stat/mod.rs │ │ └── ... │ └── linux/ │ ├── mod.rs │ ├── epoll/mod.rs │ ├── timerfd/mod.rs │ └── ... tests/bnd-linux-tests/ ← E2E tests (separate crate, all features enabled) ├── Cargo.toml ├── src/lib.rs └── tests/ ├── posixfile_e2e.rs ├── stat_e2e.rs ├── epoll_e2e.rs ├── timerfd_e2e.rs └── ... ``` -------------------------------- ### Define 4-partition layout for POSIX sockets Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/systesting/bnd-linux.md Configures the bnd-winmd output to split socket-related headers into four distinct namespaces for granular control. ```toml [output] name = "posix" file = "posixsocket.winmd" # Partition 1: socket types and core API [[partition]] namespace = "posix.socket" library = "c" headers = ["/usr/include/sys/socket.h"] traverse = ["/usr/include/sys/socket.h"] # Partition 2: IPv4/IPv6 structs and constants [[partition]] namespace = "posix.inet" library = "c" headers = ["/usr/include/netinet/in.h"] traverse = ["/usr/include/netinet/in.h"] # Partition 3: address conversion functions [[partition]] namespace = "posix.arpa" library = "c" headers = ["/usr/include/arpa/inet.h"] traverse = ["/usr/include/arpa/inet.h"] # Partition 4: name resolution [[partition]] namespace = "posix.netdb" library = "c" headers = ["/usr/include/netdb.h"] traverse = ["/usr/include/netdb.h"] ``` -------------------------------- ### Define Module Structure Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Testing.md Organize generated bindings into nested modules. ```rust pub mod MultiTest { pub mod Types { ... } pub mod Widgets { ... } } ``` -------------------------------- ### Redirect windows-link to bnd-macros Source: https://github.com/youyuanwu/bnd/blob/main/bnd-macros/README.md Configures an extern crate alias in the crate root to redirect generated windows-bindgen code to bnd-macros. ```rust extern crate bnd_macros as windows_link; pub mod my_bindings; ``` -------------------------------- ### Cross-Winmd Reference Implementation Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/features/CrossWinmdReferences.md Demonstrates the transition from local struct duplication to referencing types from an external winmd file. ```rust // openssl/crypto/mod.rs windows_link::link!("crypto" "C" fn OPENSSL_gmtime(timer : *const i64, result : *mut tm) -> *mut tm); pub struct tm { pub tm_sec: i32, pub tm_min: i32, // ... 9 fields duplicated from bnd-linux } ``` ```rust // openssl/crypto/mod.rs #[cfg(feature = "types")] windows_link::link!("crypto" "C" fn OPENSSL_gmtime( timer : *const i64, result : *mut bnd_linux::libc::posix::time::tm ) -> *mut bnd_linux::libc::posix::time::tm); // No local `struct tm` — it lives in bnd_linux::libc::posix::time ``` -------------------------------- ### Define Constants Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Testing.md Map C define constants to Rust constants. ```rust pub const MAX_WIDGETS: i32 = 256i32 ``` -------------------------------- ### FFI Generation Pipeline Source: https://github.com/youyuanwu/bnd/blob/main/README.md Visual representation of the data flow from C headers to Rust FFI modules. ```text C Headers ──→ libclang ──→ bnd-winmd ──→ .winmd ──→ windows-bindgen ──→ Rust FFI module ``` -------------------------------- ### Configure Cargo.toml for the generator crate Source: https://github.com/youyuanwu/bnd/blob/main/docs/guide/ContributingBindings.md Defines the package metadata and dependencies required for the generator crate. ```toml [package] name = "bnd-zstd-gen" version = "0.1.0" edition = "2024" publish = false [dependencies] bnd-winmd = { path = "../bnd-winmd" } tracing-subscriber = { version = "0.3", features = ["env-filter"] } windows-bindgen = "0.66" [dev-dependencies] tempfile = "3" ``` -------------------------------- ### Define Cross-partition References Source: https://github.com/youyuanwu/bnd/blob/main/docs/design/Testing.md Reference types across different modules. ```rust super::Types::Color, super::Types::Rect ```