All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerard Ryan <g.m0n3y.2503@gmail.com>
To: linux-gpio@vger.kernel.org
Subject: [libgpiod] Generated Rust lang bindings
Date: Thu, 16 Dec 2021 18:56:28 +1000	[thread overview]
Message-ID: <CAKycSdDMxfto6oTqt06TbJxXY=S7p_gtEXWDQv8mz0d9zt3Gvw@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 39864 bytes --]

Hello,
I created a build script to generate rust sys/unsafe bindings to build
safe bindings upon.
I have not reserved the `libgpiod-sys` or `libgpiod` crate names on
crates.io as I figured it'd be easier for someone here to manage the
credentials for that.
Also, I'm not sure when I'll get time to work on the safe bindings
(`libgpiod`) but figured this would be a good starting point.
As for licensing, I couldn't find any agreements or preferred
licensing for submissions so I submit this under a tentative MIT
license.

Kind Regards,

Gerard

```
MIT License

Copyright (c) 2021 Gerard Ryan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

```
From 25d8abe9997747491d4e4178efaec116b811f690 Mon Sep 17 00:00:00 2001
From: Gerard Ryan <G.M0N3Y.2503@gmail.com>
Date: Sat, 6 Nov 2021 21:23:01 +1000
Subject: [PATCH 1/2] Added libgpiod FFI bindings generation crate

Signed-off-by: Gerard Ryan <G.M0N3Y.2503@gmail.com>
---
 bindings/rust/.gitignore              |   1 +
 bindings/rust/Cargo.lock              | 382 ++++++++++++++++++++++++++
 bindings/rust/Cargo.toml              |   2 +
 bindings/rust/libgpiod-sys/Cargo.toml |  14 +
 bindings/rust/libgpiod-sys/README.md  |   7 +
 bindings/rust/libgpiod-sys/build.rs   | 166 +++++++++++
 6 files changed, 572 insertions(+)
 create mode 100644 bindings/rust/.gitignore
 create mode 100644 bindings/rust/Cargo.lock
 create mode 100644 bindings/rust/Cargo.toml
 create mode 100644 bindings/rust/libgpiod-sys/Cargo.toml
 create mode 100644 bindings/rust/libgpiod-sys/README.md
 create mode 100644 bindings/rust/libgpiod-sys/build.rs

diff --git a/bindings/rust/.gitignore b/bindings/rust/.gitignore
new file mode 100644
index 0000000..2f7896d
--- /dev/null
+++ b/bindings/rust/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/bindings/rust/Cargo.lock b/bindings/rust/Cargo.lock
new file mode 100644
index 0000000..0243b1b
--- /dev/null
+++ b/bindings/rust/Cargo.lock
@@ -0,0 +1,382 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bindgen"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "clap",
+ "env_logger",
+ "lazy_static",
+ "lazycell",
+ "log",
+ "peeking_take_while",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "which",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitvec"
+version = "0.19.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "cexpr"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clang-sys"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "clap"
+version = "2.33.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "funty"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
+
+[[package]]
+name = "libgpiod-sys"
+version = "0.1.0"
+dependencies = [
+ "bindgen",
+ "pkg-config",
+]
+
+[[package]]
+name = "libloading"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+
+[[package]]
+name = "nom"
+version = "6.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
+dependencies = [
+ "bitvec",
+ "funty",
+ "memchr",
+ "version_check",
+]
+
+[[package]]
+name = "peeking_take_while"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
+
+[[package]]
+name = "regex"
+version = "1.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "shlex"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "which"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "wyz"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml
new file mode 100644
index 0000000..01551cf
--- /dev/null
+++ b/bindings/rust/Cargo.toml
@@ -0,0 +1,2 @@
+[workspace]
+members = [ "libgpiod-sys" ]
diff --git a/bindings/rust/libgpiod-sys/Cargo.toml
b/bindings/rust/libgpiod-sys/Cargo.toml
new file mode 100644
index 0000000..6c76f08
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "libgpiod-sys"
+version = "0.1.0"
+edition = "2021"
+links = "gpiod"
+repository = "https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git"
+
+[features]
+default = [ "pkg-config" ]
+generate = [ "bindgen" ]
+
+[build-dependencies]
+bindgen = { version = "0.59.1", optional = true }
+pkg-config = { version = "0.3.22", optional = true }
diff --git a/bindings/rust/libgpiod-sys/README.md
b/bindings/rust/libgpiod-sys/README.md
new file mode 100644
index 0000000..594dbf4
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/README.md
@@ -0,0 +1,7 @@
+# Generated libgpiod Rust FFI bindings
+Automatically generated Rust FFI bindings via
[bindgen](https://github.com/rust-lang/rust-bindgen).
+
+## Updating bindings
+1. Clone the source from
<https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/>
+2. run `cargo build --features generate` from `./bindings/rust/libgpiod-sys/`
+3. Commit changes in `./bindings/rust/libgpiod-sys/src/lib.rs`
diff --git a/bindings/rust/libgpiod-sys/build.rs
b/bindings/rust/libgpiod-sys/build.rs
new file mode 100644
index 0000000..cd71fc8
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/build.rs
@@ -0,0 +1,166 @@
+use std::{
+    error::Error,
+    path::{Path, PathBuf},
+};
+
+fn expect_env_var(key: &str) -> String {
+    std::env::var(key)
+        .unwrap_or_else(|err| panic!("Could not find environment
variable '{}': {}", key, err))
+}
+
+fn copy_files_in_dir(directory: std::fs::ReadDir, file_name_contains:
&str, destination: &Path) {
+    if destination.exists() && destination.is_dir() {
+        directory
+            .filter_map(|entry| {
+                if let Ok(entry) = entry {
+                    let path = entry.path();
+                    path.is_file().then(|| path)
+                } else {
+                    None
+                }
+            })
+            .for_each(|file_path| {
+                if let Some(file_name) =
+
file_path.file_name().map(std::ffi::OsStr::to_str).flatten()
+                {
+                    if file_name.contains(file_name_contains) {
+                        if let Err(err) = std::fs::copy(&file_path,
&destination.join(file_name)) {
+                            println!(
+                                "cargo:warning=Could not copy {} to {}: {}",
+                                file_path.display(),
+                                destination.display(),
+                                err
+                            );
+                        }
+                    }
+                }
+            });
+    } else {
+        println!(
+            "cargo:warning=destination directory not found: {}",
+            destination.display()
+        );
+    }
+}
+
+#[cfg(feature = "pkg-config")]
+fn link_with_pkg_config_library(link_name: &str, interface: &Path) ->
Result<PathBuf, String> {
+    let library_name = format!("lib{}", link_name);
+    let library = pkg_config::probe_library(&library_name)
+        .map_err(|err| format!("Could not find {}: {}", library_name, err))?;
+    library
+        .include_paths
+        .iter()
+        .map(|include_path| include_path.join(interface))
+        .fold(None, |current, header_path| {
+            if current.is_none() && header_path.exists() {
+                Some(header_path)
+            } else {
+                current
+            }
+        })
+        .ok_or_else(|| {
+            format!(
+                "Could not find {} in any of {:?}, provided by pkg-config",
+                interface.display(),
+                library.include_paths
+            )
+        })
+        .map_err(Into::into)
+}
+
+#[cfg(feature = "generate")]
+fn generate_bindings(header_file: &Path, out_file: &Path) {
+    const SYMBOL_PREFIX_REGEX: &str = "(?i)gpiod_.*";
+
+    let mut output = bindgen::builder()
+        .header(header_file.display().to_string())
+        .allowlist_function(SYMBOL_PREFIX_REGEX)
+        .allowlist_type(SYMBOL_PREFIX_REGEX)
+        .allowlist_var(SYMBOL_PREFIX_REGEX)
+        .generate_comments(false)
+        .generate()
+        .expect("Could not generate bindings")
+        .to_string();
+
+    // add some niceties after the autogenerated comment
+    output.insert_str(
+        output.find('\n').expect("Nothing was generated") + 1,
+        concat!(
+            "\n",
+            "#![allow(deref_nullptr)]\n",
+            "#![allow(non_camel_case_types)]\n",
+            "#![allow(non_snake_case)]\n",
+            "#![allow(non_upper_case_globals)]\n",
+            "#![doc = include_str!(\"../README.md\")]\n"
+        ),
+    );
+
+    output.push_str(concat!(
+        "\n",
+        "#[cfg(test)]\n",
+        "mod tests {\n",
+        "    use super::*;\n",
+        "\n",
+        "    #[test]\n",
+        "    fn link_check() {\n",
+        "        use std::ffi::CStr;\n",
+        "\n",
+        "        assert!(!unsafe { CStr::from_ptr(gpiod_version_string()) }\n",
+        "            .to_string_lossy()\n",
+        "            .is_empty());\n",
+        "    }\n",
+        "}\n"
+    ));
+
+    std::fs::write(out_file, &*output)
+        .unwrap_or_else(|err| panic!("Could not write to {}: {}",
out_file.display(), err));
+}
+
+fn main() {
+    let header_file_name = Path::new("gpiod.h");
+    let out_dir = PathBuf::from(expect_env_var("OUT_DIR"));
+    let library = expect_env_var("CARGO_MANIFEST_LINKS");
+
+    let rel_source_dir_root = Path::new("../../../");
+    let header_path =
rel_source_dir_root.join("include").join(header_file_name);
+    let library_path = rel_source_dir_root.join("lib").join(".libs");
+
+    #[allow(unused_mut)]
+    let mut header_path: Result<PathBuf, Box<dyn Error>> = if
header_path.exists() {
+        println!("cargo:rerun-if-changed={}", header_path.display());
+        println!("cargo:rerun-if-changed={}", library_path.display());
+        println!("cargo:rustc-link-lib={}", library);
+
+        if let Ok(dir_iter) = library_path.read_dir() {
+            println!("cargo:rustc-link-search={}", out_dir.display());
+            copy_files_in_dir(dir_iter, ".so", &out_dir);
+        } else {
+            println!(
+                "cargo:warning=Could not find library built in {}.
Linking may fail.",
+                library_path.display()
+            );
+        }
+
+        Ok(header_path)
+    } else {
+        Err("Could not find source directory".into())
+    };
+
+    #[cfg(feature = "pkg-config")]
+    if header_path.is_err() {
+        header_path = link_with_pkg_config_library(&library,
header_file_name).map_err(Into::into);
+    }
+
+    #[cfg(feature = "generate")]
+    generate_bindings(
+        header_path
+            .as_ref()
+            .unwrap_or_else(|err| panic!("Could not find {}: {}",
header_file_name.display(), err)),
+        Path::new("./src/lib.rs"),
+    );
+
+    if let Err(err) = header_path {
+        panic!("Could not find lib{}: {}", library, err);
+    }
+}
-- 
2.34.1

```

```
From 96b623298145f5f2d2e13e3aaa20098ca26e73bb Mon Sep 17 00:00:00 2001
From: Gerard Ryan <G.M0N3Y.2503@gmail.com>
Date: Sat, 6 Nov 2021 21:25:46 +1000
Subject: [PATCH 2/2] Generated rust sys bindings from 4da9f5b

Signed-off-by: Gerard Ryan <G.M0N3Y.2503@gmail.com>
---
 bindings/rust/libgpiod-sys/src/lib.rs | 588 ++++++++++++++++++++++++++
 1 file changed, 588 insertions(+)
 create mode 100644 bindings/rust/libgpiod-sys/src/lib.rs

diff --git a/bindings/rust/libgpiod-sys/src/lib.rs
b/bindings/rust/libgpiod-sys/src/lib.rs
new file mode 100644
index 0000000..470ff60
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/src/lib.rs
@@ -0,0 +1,588 @@
+/* automatically generated by rust-bindgen 0.59.1 */
+
+#![allow(deref_nullptr)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![doc = include_str!("../README.md")]
+
+pub type __time_t = ::std::os::raw::c_long;
+pub type __syscall_slong_t = ::std::os::raw::c_long;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct timespec {
+    pub tv_sec: __time_t,
+    pub tv_nsec: __syscall_slong_t,
+}
+#[test]
+fn bindgen_test_layout_timespec() {
+    assert_eq!(
+        ::std::mem::size_of::<timespec>(),
+        16usize,
+        concat!("Size of: ", stringify!(timespec))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<timespec>(),
+        8usize,
+        concat!("Alignment of ", stringify!(timespec))
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<timespec>())).tv_sec as
*const _ as usize },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(timespec),
+            "::",
+            stringify!(tv_sec)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<timespec>())).tv_nsec as
*const _ as usize },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(timespec),
+            "::",
+            stringify!(tv_nsec)
+        )
+    );
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_chip {
+    _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line {
+    _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line_bulk {
+    _unused: [u8; 0],
+}
+extern "C" {
+    pub fn gpiod_is_gpiochip_device(path: *const
::std::os::raw::c_char) -> bool;
+}
+extern "C" {
+    pub fn gpiod_chip_open(path: *const ::std::os::raw::c_char) ->
*mut gpiod_chip;
+}
+extern "C" {
+    pub fn gpiod_chip_ref(chip: *mut gpiod_chip) -> *mut gpiod_chip;
+}
+extern "C" {
+    pub fn gpiod_chip_unref(chip: *mut gpiod_chip);
+}
+extern "C" {
+    pub fn gpiod_chip_get_name(chip: *mut gpiod_chip) -> *const
::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_chip_get_label(chip: *mut gpiod_chip) -> *const
::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_chip_get_num_lines(chip: *mut gpiod_chip) ->
::std::os::raw::c_uint;
+}
+extern "C" {
+    pub fn gpiod_chip_get_line(
+        chip: *mut gpiod_chip,
+        offset: ::std::os::raw::c_uint,
+    ) -> *mut gpiod_line;
+}
+extern "C" {
+    pub fn gpiod_chip_get_lines(
+        chip: *mut gpiod_chip,
+        offsets: *mut ::std::os::raw::c_uint,
+        num_offsets: ::std::os::raw::c_uint,
+    ) -> *mut gpiod_line_bulk;
+}
+extern "C" {
+    pub fn gpiod_chip_get_all_lines(chip: *mut gpiod_chip) -> *mut
gpiod_line_bulk;
+}
+extern "C" {
+    pub fn gpiod_chip_find_line(
+        chip: *mut gpiod_chip,
+        name: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_new(max_lines: ::std::os::raw::c_uint) ->
*mut gpiod_line_bulk;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_reset(bulk: *mut gpiod_line_bulk);
+}
+extern "C" {
+    pub fn gpiod_line_bulk_free(bulk: *mut gpiod_line_bulk);
+}
+extern "C" {
+    pub fn gpiod_line_bulk_add_line(
+        bulk: *mut gpiod_line_bulk,
+        line: *mut gpiod_line,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_get_line(
+        bulk: *mut gpiod_line_bulk,
+        index: ::std::os::raw::c_uint,
+    ) -> *mut gpiod_line;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_num_lines(bulk: *mut gpiod_line_bulk) ->
::std::os::raw::c_uint;
+}
+pub const GPIOD_LINE_BULK_CB_NEXT: ::std::os::raw::c_uint = 0;
+pub const GPIOD_LINE_BULK_CB_STOP: ::std::os::raw::c_uint = 1;
+pub type _bindgen_ty_1 = ::std::os::raw::c_uint;
+pub type gpiod_line_bulk_foreach_cb = ::std::option::Option<
+    unsafe extern "C" fn(
+        arg1: *mut gpiod_line,
+        arg2: *mut ::std::os::raw::c_void,
+    ) -> ::std::os::raw::c_int,
+>;
+extern "C" {
+    pub fn gpiod_line_bulk_foreach_line(
+        bulk: *mut gpiod_line_bulk,
+        func: gpiod_line_bulk_foreach_cb,
+        data: *mut ::std::os::raw::c_void,
+    );
+}
+pub const GPIOD_LINE_DIRECTION_INPUT: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_DIRECTION_OUTPUT: ::std::os::raw::c_uint = 2;
+pub type _bindgen_ty_2 = ::std::os::raw::c_uint;
+pub const GPIOD_LINE_DRIVE_PUSH_PULL: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_DRIVE_OPEN_DRAIN: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_DRIVE_OPEN_SOURCE: ::std::os::raw::c_uint = 3;
+pub type _bindgen_ty_3 = ::std::os::raw::c_uint;
+pub const GPIOD_LINE_BIAS_UNKNOWN: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_BIAS_DISABLED: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_BIAS_PULL_UP: ::std::os::raw::c_uint = 3;
+pub const GPIOD_LINE_BIAS_PULL_DOWN: ::std::os::raw::c_uint = 4;
+pub type _bindgen_ty_4 = ::std::os::raw::c_uint;
+extern "C" {
+    pub fn gpiod_line_offset(line: *mut gpiod_line) -> ::std::os::raw::c_uint;
+}
+extern "C" {
+    pub fn gpiod_line_name(line: *mut gpiod_line) -> *const
::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_line_consumer(line: *mut gpiod_line) -> *const
::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_line_direction(line: *mut gpiod_line) ->
::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_is_active_low(line: *mut gpiod_line) -> bool;
+}
+extern "C" {
+    pub fn gpiod_line_bias(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_is_used(line: *mut gpiod_line) -> bool;
+}
+extern "C" {
+    pub fn gpiod_line_drive(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_get_chip(line: *mut gpiod_line) -> *mut gpiod_chip;
+}
+pub const GPIOD_LINE_REQUEST_DIRECTION_AS_IS: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_REQUEST_DIRECTION_INPUT: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_REQUEST_DIRECTION_OUTPUT: ::std::os::raw::c_uint = 3;
+pub const GPIOD_LINE_REQUEST_EVENT_FALLING_EDGE: ::std::os::raw::c_uint = 4;
+pub const GPIOD_LINE_REQUEST_EVENT_RISING_EDGE: ::std::os::raw::c_uint = 5;
+pub const GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES: ::std::os::raw::c_uint = 6;
+pub type _bindgen_ty_5 = ::std::os::raw::c_uint;
+pub const GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW: ::std::os::raw::c_uint = 4;
+pub const GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLED: ::std::os::raw::c_uint = 8;
+pub const GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN: ::std::os::raw::c_uint = 16;
+pub const GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP: ::std::os::raw::c_uint = 32;
+pub type _bindgen_ty_6 = ::std::os::raw::c_uint;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line_request_config {
+    pub consumer: *const ::std::os::raw::c_char,
+    pub request_type: ::std::os::raw::c_int,
+    pub flags: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_gpiod_line_request_config() {
+    assert_eq!(
+        ::std::mem::size_of::<gpiod_line_request_config>(),
+        16usize,
+        concat!("Size of: ", stringify!(gpiod_line_request_config))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<gpiod_line_request_config>(),
+        8usize,
+        concat!("Alignment of ", stringify!(gpiod_line_request_config))
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<gpiod_line_request_config>())).consumer
as *const _ as usize
+        },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_request_config),
+            "::",
+            stringify!(consumer)
+        )
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<gpiod_line_request_config>())).request_type
as *const _ as usize
+        },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_request_config),
+            "::",
+            stringify!(request_type)
+        )
+    );
+    assert_eq!(
+        unsafe {
&(*(::std::ptr::null::<gpiod_line_request_config>())).flags as *const
_ as usize },
+        12usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_request_config),
+            "::",
+            stringify!(flags)
+        )
+    );
+}
+extern "C" {
+    pub fn gpiod_line_request(
+        line: *mut gpiod_line,
+        config: *const gpiod_line_request_config,
+        default_val: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_input(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_output(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        default_val: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_rising_edge_events(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_falling_edge_events(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_both_edges_events(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_input_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_output_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+        default_val: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_rising_edge_events_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_falling_edge_events_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_both_edges_events_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk(
+        bulk: *mut gpiod_line_bulk,
+        config: *const gpiod_line_request_config,
+        default_vals: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_input(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_output(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        default_vals: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_rising_edge_events(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_falling_edge_events(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_both_edges_events(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_input_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_output_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+        default_vals: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_rising_edge_events_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_falling_edge_events_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_both_edges_events_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_release(line: *mut gpiod_line);
+}
+extern "C" {
+    pub fn gpiod_line_release_bulk(bulk: *mut gpiod_line_bulk);
+}
+extern "C" {
+    pub fn gpiod_line_get_value(line: *mut gpiod_line) ->
::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_get_value_bulk(
+        bulk: *mut gpiod_line_bulk,
+        values: *mut ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_value(
+        line: *mut gpiod_line,
+        value: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_value_bulk(
+        bulk: *mut gpiod_line_bulk,
+        values: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_config(
+        line: *mut gpiod_line,
+        direction: ::std::os::raw::c_int,
+        flags: ::std::os::raw::c_int,
+        value: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_config_bulk(
+        bulk: *mut gpiod_line_bulk,
+        direction: ::std::os::raw::c_int,
+        flags: ::std::os::raw::c_int,
+        values: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_flags(
+        line: *mut gpiod_line,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_flags_bulk(
+        bulk: *mut gpiod_line_bulk,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_input(line: *mut gpiod_line) ->
::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_input_bulk(bulk: *mut gpiod_line_bulk)
+        -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_output(
+        line: *mut gpiod_line,
+        value: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_output_bulk(
+        bulk: *mut gpiod_line_bulk,
+        values: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+pub const GPIOD_LINE_EVENT_RISING_EDGE: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_EVENT_FALLING_EDGE: ::std::os::raw::c_uint = 2;
+pub type _bindgen_ty_7 = ::std::os::raw::c_uint;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line_event {
+    pub ts: timespec,
+    pub event_type: ::std::os::raw::c_int,
+    pub offset: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_gpiod_line_event() {
+    assert_eq!(
+        ::std::mem::size_of::<gpiod_line_event>(),
+        24usize,
+        concat!("Size of: ", stringify!(gpiod_line_event))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<gpiod_line_event>(),
+        8usize,
+        concat!("Alignment of ", stringify!(gpiod_line_event))
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<gpiod_line_event>())).ts as
*const _ as usize },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_event),
+            "::",
+            stringify!(ts)
+        )
+    );
+    assert_eq!(
+        unsafe {
&(*(::std::ptr::null::<gpiod_line_event>())).event_type as *const _ as
usize },
+        16usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_event),
+            "::",
+            stringify!(event_type)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<gpiod_line_event>())).offset
as *const _ as usize },
+        20usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_event),
+            "::",
+            stringify!(offset)
+        )
+    );
+}
+extern "C" {
+    pub fn gpiod_line_event_wait(
+        line: *mut gpiod_line,
+        timeout: *const timespec,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_wait_bulk(
+        bulk: *mut gpiod_line_bulk,
+        timeout: *const timespec,
+        event_bulk: *mut gpiod_line_bulk,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read(
+        line: *mut gpiod_line,
+        event: *mut gpiod_line_event,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read_multiple(
+        line: *mut gpiod_line,
+        events: *mut gpiod_line_event,
+        num_events: ::std::os::raw::c_uint,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_get_fd(line: *mut gpiod_line) ->
::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read_fd(
+        fd: ::std::os::raw::c_int,
+        event: *mut gpiod_line_event,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read_fd_multiple(
+        fd: ::std::os::raw::c_int,
+        events: *mut gpiod_line_event,
+        num_events: ::std::os::raw::c_uint,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_version_string() -> *const ::std::os::raw::c_char;
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn link_check() {
+        use std::ffi::CStr;
+
+        assert!(!unsafe { CStr::from_ptr(gpiod_version_string()) }
+            .to_string_lossy()
+            .is_empty());
+    }
+}
-- 
2.34.1

```

[-- Attachment #2: LICENSE.txt --]
[-- Type: text/plain, Size: 1068 bytes --]

MIT License

Copyright (c) 2021 Gerard Ryan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

[-- Attachment #3: 0002-Generated-rust-sys-bindings-from-4da9f5b.patch --]
[-- Type: text/x-patch, Size: 19163 bytes --]

From 96b623298145f5f2d2e13e3aaa20098ca26e73bb Mon Sep 17 00:00:00 2001
From: Gerard Ryan <G.M0N3Y.2503@gmail.com>
Date: Sat, 6 Nov 2021 21:25:46 +1000
Subject: [PATCH 2/2] Generated rust sys bindings from 4da9f5b

Signed-off-by: Gerard Ryan <G.M0N3Y.2503@gmail.com>
---
 bindings/rust/libgpiod-sys/src/lib.rs | 588 ++++++++++++++++++++++++++
 1 file changed, 588 insertions(+)
 create mode 100644 bindings/rust/libgpiod-sys/src/lib.rs

diff --git a/bindings/rust/libgpiod-sys/src/lib.rs b/bindings/rust/libgpiod-sys/src/lib.rs
new file mode 100644
index 0000000..470ff60
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/src/lib.rs
@@ -0,0 +1,588 @@
+/* automatically generated by rust-bindgen 0.59.1 */
+
+#![allow(deref_nullptr)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![doc = include_str!("../README.md")]
+
+pub type __time_t = ::std::os::raw::c_long;
+pub type __syscall_slong_t = ::std::os::raw::c_long;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct timespec {
+    pub tv_sec: __time_t,
+    pub tv_nsec: __syscall_slong_t,
+}
+#[test]
+fn bindgen_test_layout_timespec() {
+    assert_eq!(
+        ::std::mem::size_of::<timespec>(),
+        16usize,
+        concat!("Size of: ", stringify!(timespec))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<timespec>(),
+        8usize,
+        concat!("Alignment of ", stringify!(timespec))
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<timespec>())).tv_sec as *const _ as usize },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(timespec),
+            "::",
+            stringify!(tv_sec)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<timespec>())).tv_nsec as *const _ as usize },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(timespec),
+            "::",
+            stringify!(tv_nsec)
+        )
+    );
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_chip {
+    _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line {
+    _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line_bulk {
+    _unused: [u8; 0],
+}
+extern "C" {
+    pub fn gpiod_is_gpiochip_device(path: *const ::std::os::raw::c_char) -> bool;
+}
+extern "C" {
+    pub fn gpiod_chip_open(path: *const ::std::os::raw::c_char) -> *mut gpiod_chip;
+}
+extern "C" {
+    pub fn gpiod_chip_ref(chip: *mut gpiod_chip) -> *mut gpiod_chip;
+}
+extern "C" {
+    pub fn gpiod_chip_unref(chip: *mut gpiod_chip);
+}
+extern "C" {
+    pub fn gpiod_chip_get_name(chip: *mut gpiod_chip) -> *const ::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_chip_get_label(chip: *mut gpiod_chip) -> *const ::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_chip_get_num_lines(chip: *mut gpiod_chip) -> ::std::os::raw::c_uint;
+}
+extern "C" {
+    pub fn gpiod_chip_get_line(
+        chip: *mut gpiod_chip,
+        offset: ::std::os::raw::c_uint,
+    ) -> *mut gpiod_line;
+}
+extern "C" {
+    pub fn gpiod_chip_get_lines(
+        chip: *mut gpiod_chip,
+        offsets: *mut ::std::os::raw::c_uint,
+        num_offsets: ::std::os::raw::c_uint,
+    ) -> *mut gpiod_line_bulk;
+}
+extern "C" {
+    pub fn gpiod_chip_get_all_lines(chip: *mut gpiod_chip) -> *mut gpiod_line_bulk;
+}
+extern "C" {
+    pub fn gpiod_chip_find_line(
+        chip: *mut gpiod_chip,
+        name: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_new(max_lines: ::std::os::raw::c_uint) -> *mut gpiod_line_bulk;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_reset(bulk: *mut gpiod_line_bulk);
+}
+extern "C" {
+    pub fn gpiod_line_bulk_free(bulk: *mut gpiod_line_bulk);
+}
+extern "C" {
+    pub fn gpiod_line_bulk_add_line(
+        bulk: *mut gpiod_line_bulk,
+        line: *mut gpiod_line,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_get_line(
+        bulk: *mut gpiod_line_bulk,
+        index: ::std::os::raw::c_uint,
+    ) -> *mut gpiod_line;
+}
+extern "C" {
+    pub fn gpiod_line_bulk_num_lines(bulk: *mut gpiod_line_bulk) -> ::std::os::raw::c_uint;
+}
+pub const GPIOD_LINE_BULK_CB_NEXT: ::std::os::raw::c_uint = 0;
+pub const GPIOD_LINE_BULK_CB_STOP: ::std::os::raw::c_uint = 1;
+pub type _bindgen_ty_1 = ::std::os::raw::c_uint;
+pub type gpiod_line_bulk_foreach_cb = ::std::option::Option<
+    unsafe extern "C" fn(
+        arg1: *mut gpiod_line,
+        arg2: *mut ::std::os::raw::c_void,
+    ) -> ::std::os::raw::c_int,
+>;
+extern "C" {
+    pub fn gpiod_line_bulk_foreach_line(
+        bulk: *mut gpiod_line_bulk,
+        func: gpiod_line_bulk_foreach_cb,
+        data: *mut ::std::os::raw::c_void,
+    );
+}
+pub const GPIOD_LINE_DIRECTION_INPUT: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_DIRECTION_OUTPUT: ::std::os::raw::c_uint = 2;
+pub type _bindgen_ty_2 = ::std::os::raw::c_uint;
+pub const GPIOD_LINE_DRIVE_PUSH_PULL: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_DRIVE_OPEN_DRAIN: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_DRIVE_OPEN_SOURCE: ::std::os::raw::c_uint = 3;
+pub type _bindgen_ty_3 = ::std::os::raw::c_uint;
+pub const GPIOD_LINE_BIAS_UNKNOWN: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_BIAS_DISABLED: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_BIAS_PULL_UP: ::std::os::raw::c_uint = 3;
+pub const GPIOD_LINE_BIAS_PULL_DOWN: ::std::os::raw::c_uint = 4;
+pub type _bindgen_ty_4 = ::std::os::raw::c_uint;
+extern "C" {
+    pub fn gpiod_line_offset(line: *mut gpiod_line) -> ::std::os::raw::c_uint;
+}
+extern "C" {
+    pub fn gpiod_line_name(line: *mut gpiod_line) -> *const ::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_line_consumer(line: *mut gpiod_line) -> *const ::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn gpiod_line_direction(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_is_active_low(line: *mut gpiod_line) -> bool;
+}
+extern "C" {
+    pub fn gpiod_line_bias(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_is_used(line: *mut gpiod_line) -> bool;
+}
+extern "C" {
+    pub fn gpiod_line_drive(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_get_chip(line: *mut gpiod_line) -> *mut gpiod_chip;
+}
+pub const GPIOD_LINE_REQUEST_DIRECTION_AS_IS: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_REQUEST_DIRECTION_INPUT: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_REQUEST_DIRECTION_OUTPUT: ::std::os::raw::c_uint = 3;
+pub const GPIOD_LINE_REQUEST_EVENT_FALLING_EDGE: ::std::os::raw::c_uint = 4;
+pub const GPIOD_LINE_REQUEST_EVENT_RISING_EDGE: ::std::os::raw::c_uint = 5;
+pub const GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES: ::std::os::raw::c_uint = 6;
+pub type _bindgen_ty_5 = ::std::os::raw::c_uint;
+pub const GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE: ::std::os::raw::c_uint = 2;
+pub const GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW: ::std::os::raw::c_uint = 4;
+pub const GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLED: ::std::os::raw::c_uint = 8;
+pub const GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN: ::std::os::raw::c_uint = 16;
+pub const GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP: ::std::os::raw::c_uint = 32;
+pub type _bindgen_ty_6 = ::std::os::raw::c_uint;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line_request_config {
+    pub consumer: *const ::std::os::raw::c_char,
+    pub request_type: ::std::os::raw::c_int,
+    pub flags: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_gpiod_line_request_config() {
+    assert_eq!(
+        ::std::mem::size_of::<gpiod_line_request_config>(),
+        16usize,
+        concat!("Size of: ", stringify!(gpiod_line_request_config))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<gpiod_line_request_config>(),
+        8usize,
+        concat!("Alignment of ", stringify!(gpiod_line_request_config))
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<gpiod_line_request_config>())).consumer as *const _ as usize
+        },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_request_config),
+            "::",
+            stringify!(consumer)
+        )
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<gpiod_line_request_config>())).request_type as *const _ as usize
+        },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_request_config),
+            "::",
+            stringify!(request_type)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<gpiod_line_request_config>())).flags as *const _ as usize },
+        12usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_request_config),
+            "::",
+            stringify!(flags)
+        )
+    );
+}
+extern "C" {
+    pub fn gpiod_line_request(
+        line: *mut gpiod_line,
+        config: *const gpiod_line_request_config,
+        default_val: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_input(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_output(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        default_val: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_rising_edge_events(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_falling_edge_events(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_both_edges_events(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_input_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_output_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+        default_val: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_rising_edge_events_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_falling_edge_events_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_both_edges_events_flags(
+        line: *mut gpiod_line,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk(
+        bulk: *mut gpiod_line_bulk,
+        config: *const gpiod_line_request_config,
+        default_vals: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_input(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_output(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        default_vals: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_rising_edge_events(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_falling_edge_events(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_both_edges_events(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_input_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_output_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+        default_vals: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_rising_edge_events_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_falling_edge_events_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_request_bulk_both_edges_events_flags(
+        bulk: *mut gpiod_line_bulk,
+        consumer: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_release(line: *mut gpiod_line);
+}
+extern "C" {
+    pub fn gpiod_line_release_bulk(bulk: *mut gpiod_line_bulk);
+}
+extern "C" {
+    pub fn gpiod_line_get_value(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_get_value_bulk(
+        bulk: *mut gpiod_line_bulk,
+        values: *mut ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_value(
+        line: *mut gpiod_line,
+        value: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_value_bulk(
+        bulk: *mut gpiod_line_bulk,
+        values: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_config(
+        line: *mut gpiod_line,
+        direction: ::std::os::raw::c_int,
+        flags: ::std::os::raw::c_int,
+        value: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_config_bulk(
+        bulk: *mut gpiod_line_bulk,
+        direction: ::std::os::raw::c_int,
+        flags: ::std::os::raw::c_int,
+        values: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_flags(
+        line: *mut gpiod_line,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_flags_bulk(
+        bulk: *mut gpiod_line_bulk,
+        flags: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_input(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_input_bulk(bulk: *mut gpiod_line_bulk)
+        -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_output(
+        line: *mut gpiod_line,
+        value: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_set_direction_output_bulk(
+        bulk: *mut gpiod_line_bulk,
+        values: *const ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+pub const GPIOD_LINE_EVENT_RISING_EDGE: ::std::os::raw::c_uint = 1;
+pub const GPIOD_LINE_EVENT_FALLING_EDGE: ::std::os::raw::c_uint = 2;
+pub type _bindgen_ty_7 = ::std::os::raw::c_uint;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct gpiod_line_event {
+    pub ts: timespec,
+    pub event_type: ::std::os::raw::c_int,
+    pub offset: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_gpiod_line_event() {
+    assert_eq!(
+        ::std::mem::size_of::<gpiod_line_event>(),
+        24usize,
+        concat!("Size of: ", stringify!(gpiod_line_event))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<gpiod_line_event>(),
+        8usize,
+        concat!("Alignment of ", stringify!(gpiod_line_event))
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<gpiod_line_event>())).ts as *const _ as usize },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_event),
+            "::",
+            stringify!(ts)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<gpiod_line_event>())).event_type as *const _ as usize },
+        16usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_event),
+            "::",
+            stringify!(event_type)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<gpiod_line_event>())).offset as *const _ as usize },
+        20usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(gpiod_line_event),
+            "::",
+            stringify!(offset)
+        )
+    );
+}
+extern "C" {
+    pub fn gpiod_line_event_wait(
+        line: *mut gpiod_line,
+        timeout: *const timespec,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_wait_bulk(
+        bulk: *mut gpiod_line_bulk,
+        timeout: *const timespec,
+        event_bulk: *mut gpiod_line_bulk,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read(
+        line: *mut gpiod_line,
+        event: *mut gpiod_line_event,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read_multiple(
+        line: *mut gpiod_line,
+        events: *mut gpiod_line_event,
+        num_events: ::std::os::raw::c_uint,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_get_fd(line: *mut gpiod_line) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read_fd(
+        fd: ::std::os::raw::c_int,
+        event: *mut gpiod_line_event,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_line_event_read_fd_multiple(
+        fd: ::std::os::raw::c_int,
+        events: *mut gpiod_line_event,
+        num_events: ::std::os::raw::c_uint,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn gpiod_version_string() -> *const ::std::os::raw::c_char;
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn link_check() {
+        use std::ffi::CStr;
+
+        assert!(!unsafe { CStr::from_ptr(gpiod_version_string()) }
+            .to_string_lossy()
+            .is_empty());
+    }
+}
-- 
2.34.1


[-- Attachment #4: 0001-Added-libgpiod-FFI-bindings-generation-crate.patch --]
[-- Type: text/x-patch, Size: 19080 bytes --]

From 25d8abe9997747491d4e4178efaec116b811f690 Mon Sep 17 00:00:00 2001
From: Gerard Ryan <G.M0N3Y.2503@gmail.com>
Date: Sat, 6 Nov 2021 21:23:01 +1000
Subject: [PATCH 1/2] Added libgpiod FFI bindings generation crate

Signed-off-by: Gerard Ryan <G.M0N3Y.2503@gmail.com>
---
 bindings/rust/.gitignore              |   1 +
 bindings/rust/Cargo.lock              | 382 ++++++++++++++++++++++++++
 bindings/rust/Cargo.toml              |   2 +
 bindings/rust/libgpiod-sys/Cargo.toml |  14 +
 bindings/rust/libgpiod-sys/README.md  |   7 +
 bindings/rust/libgpiod-sys/build.rs   | 166 +++++++++++
 6 files changed, 572 insertions(+)
 create mode 100644 bindings/rust/.gitignore
 create mode 100644 bindings/rust/Cargo.lock
 create mode 100644 bindings/rust/Cargo.toml
 create mode 100644 bindings/rust/libgpiod-sys/Cargo.toml
 create mode 100644 bindings/rust/libgpiod-sys/README.md
 create mode 100644 bindings/rust/libgpiod-sys/build.rs

diff --git a/bindings/rust/.gitignore b/bindings/rust/.gitignore
new file mode 100644
index 0000000..2f7896d
--- /dev/null
+++ b/bindings/rust/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/bindings/rust/Cargo.lock b/bindings/rust/Cargo.lock
new file mode 100644
index 0000000..0243b1b
--- /dev/null
+++ b/bindings/rust/Cargo.lock
@@ -0,0 +1,382 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bindgen"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "clap",
+ "env_logger",
+ "lazy_static",
+ "lazycell",
+ "log",
+ "peeking_take_while",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "which",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitvec"
+version = "0.19.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "cexpr"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clang-sys"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "clap"
+version = "2.33.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "funty"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
+
+[[package]]
+name = "libgpiod-sys"
+version = "0.1.0"
+dependencies = [
+ "bindgen",
+ "pkg-config",
+]
+
+[[package]]
+name = "libloading"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+
+[[package]]
+name = "nom"
+version = "6.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
+dependencies = [
+ "bitvec",
+ "funty",
+ "memchr",
+ "version_check",
+]
+
+[[package]]
+name = "peeking_take_while"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
+
+[[package]]
+name = "regex"
+version = "1.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "shlex"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "which"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "wyz"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml
new file mode 100644
index 0000000..01551cf
--- /dev/null
+++ b/bindings/rust/Cargo.toml
@@ -0,0 +1,2 @@
+[workspace]
+members = [ "libgpiod-sys" ]
diff --git a/bindings/rust/libgpiod-sys/Cargo.toml b/bindings/rust/libgpiod-sys/Cargo.toml
new file mode 100644
index 0000000..6c76f08
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "libgpiod-sys"
+version = "0.1.0"
+edition = "2021"
+links = "gpiod"
+repository = "https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git"
+
+[features]
+default = [ "pkg-config" ]
+generate = [ "bindgen" ]
+
+[build-dependencies]
+bindgen = { version = "0.59.1", optional = true }
+pkg-config = { version = "0.3.22", optional = true }
diff --git a/bindings/rust/libgpiod-sys/README.md b/bindings/rust/libgpiod-sys/README.md
new file mode 100644
index 0000000..594dbf4
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/README.md
@@ -0,0 +1,7 @@
+# Generated libgpiod Rust FFI bindings
+Automatically generated Rust FFI bindings via [bindgen](https://github.com/rust-lang/rust-bindgen).
+
+## Updating bindings
+1. Clone the source from <https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/>
+2. run `cargo build --features generate` from `./bindings/rust/libgpiod-sys/`
+3. Commit changes in `./bindings/rust/libgpiod-sys/src/lib.rs`
diff --git a/bindings/rust/libgpiod-sys/build.rs b/bindings/rust/libgpiod-sys/build.rs
new file mode 100644
index 0000000..cd71fc8
--- /dev/null
+++ b/bindings/rust/libgpiod-sys/build.rs
@@ -0,0 +1,166 @@
+use std::{
+    error::Error,
+    path::{Path, PathBuf},
+};
+
+fn expect_env_var(key: &str) -> String {
+    std::env::var(key)
+        .unwrap_or_else(|err| panic!("Could not find environment variable '{}': {}", key, err))
+}
+
+fn copy_files_in_dir(directory: std::fs::ReadDir, file_name_contains: &str, destination: &Path) {
+    if destination.exists() && destination.is_dir() {
+        directory
+            .filter_map(|entry| {
+                if let Ok(entry) = entry {
+                    let path = entry.path();
+                    path.is_file().then(|| path)
+                } else {
+                    None
+                }
+            })
+            .for_each(|file_path| {
+                if let Some(file_name) =
+                    file_path.file_name().map(std::ffi::OsStr::to_str).flatten()
+                {
+                    if file_name.contains(file_name_contains) {
+                        if let Err(err) = std::fs::copy(&file_path, &destination.join(file_name)) {
+                            println!(
+                                "cargo:warning=Could not copy {} to {}: {}",
+                                file_path.display(),
+                                destination.display(),
+                                err
+                            );
+                        }
+                    }
+                }
+            });
+    } else {
+        println!(
+            "cargo:warning=destination directory not found: {}",
+            destination.display()
+        );
+    }
+}
+
+#[cfg(feature = "pkg-config")]
+fn link_with_pkg_config_library(link_name: &str, interface: &Path) -> Result<PathBuf, String> {
+    let library_name = format!("lib{}", link_name);
+    let library = pkg_config::probe_library(&library_name)
+        .map_err(|err| format!("Could not find {}: {}", library_name, err))?;
+    library
+        .include_paths
+        .iter()
+        .map(|include_path| include_path.join(interface))
+        .fold(None, |current, header_path| {
+            if current.is_none() && header_path.exists() {
+                Some(header_path)
+            } else {
+                current
+            }
+        })
+        .ok_or_else(|| {
+            format!(
+                "Could not find {} in any of {:?}, provided by pkg-config",
+                interface.display(),
+                library.include_paths
+            )
+        })
+        .map_err(Into::into)
+}
+
+#[cfg(feature = "generate")]
+fn generate_bindings(header_file: &Path, out_file: &Path) {
+    const SYMBOL_PREFIX_REGEX: &str = "(?i)gpiod_.*";
+
+    let mut output = bindgen::builder()
+        .header(header_file.display().to_string())
+        .allowlist_function(SYMBOL_PREFIX_REGEX)
+        .allowlist_type(SYMBOL_PREFIX_REGEX)
+        .allowlist_var(SYMBOL_PREFIX_REGEX)
+        .generate_comments(false)
+        .generate()
+        .expect("Could not generate bindings")
+        .to_string();
+
+    // add some niceties after the autogenerated comment
+    output.insert_str(
+        output.find('\n').expect("Nothing was generated") + 1,
+        concat!(
+            "\n",
+            "#![allow(deref_nullptr)]\n",
+            "#![allow(non_camel_case_types)]\n",
+            "#![allow(non_snake_case)]\n",
+            "#![allow(non_upper_case_globals)]\n",
+            "#![doc = include_str!(\"../README.md\")]\n"
+        ),
+    );
+
+    output.push_str(concat!(
+        "\n",
+        "#[cfg(test)]\n",
+        "mod tests {\n",
+        "    use super::*;\n",
+        "\n",
+        "    #[test]\n",
+        "    fn link_check() {\n",
+        "        use std::ffi::CStr;\n",
+        "\n",
+        "        assert!(!unsafe { CStr::from_ptr(gpiod_version_string()) }\n",
+        "            .to_string_lossy()\n",
+        "            .is_empty());\n",
+        "    }\n",
+        "}\n"
+    ));
+
+    std::fs::write(out_file, &*output)
+        .unwrap_or_else(|err| panic!("Could not write to {}: {}", out_file.display(), err));
+}
+
+fn main() {
+    let header_file_name = Path::new("gpiod.h");
+    let out_dir = PathBuf::from(expect_env_var("OUT_DIR"));
+    let library = expect_env_var("CARGO_MANIFEST_LINKS");
+
+    let rel_source_dir_root = Path::new("../../../");
+    let header_path = rel_source_dir_root.join("include").join(header_file_name);
+    let library_path = rel_source_dir_root.join("lib").join(".libs");
+
+    #[allow(unused_mut)]
+    let mut header_path: Result<PathBuf, Box<dyn Error>> = if header_path.exists() {
+        println!("cargo:rerun-if-changed={}", header_path.display());
+        println!("cargo:rerun-if-changed={}", library_path.display());
+        println!("cargo:rustc-link-lib={}", library);
+
+        if let Ok(dir_iter) = library_path.read_dir() {
+            println!("cargo:rustc-link-search={}", out_dir.display());
+            copy_files_in_dir(dir_iter, ".so", &out_dir);
+        } else {
+            println!(
+                "cargo:warning=Could not find library built in {}. Linking may fail.",
+                library_path.display()
+            );
+        }
+
+        Ok(header_path)
+    } else {
+        Err("Could not find source directory".into())
+    };
+
+    #[cfg(feature = "pkg-config")]
+    if header_path.is_err() {
+        header_path = link_with_pkg_config_library(&library, header_file_name).map_err(Into::into);
+    }
+
+    #[cfg(feature = "generate")]
+    generate_bindings(
+        header_path
+            .as_ref()
+            .unwrap_or_else(|err| panic!("Could not find {}: {}", header_file_name.display(), err)),
+        Path::new("./src/lib.rs"),
+    );
+
+    if let Err(err) = header_path {
+        panic!("Could not find lib{}: {}", library, err);
+    }
+}
-- 
2.34.1


             reply	other threads:[~2021-12-16  8:56 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-16  8:56 Gerard Ryan [this message]
2021-12-16  9:11 ` [libgpiod] Generated Rust lang bindings Viresh Kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAKycSdDMxfto6oTqt06TbJxXY=S7p_gtEXWDQv8mz0d9zt3Gvw@mail.gmail.com' \
    --to=g.m0n3y.2503@gmail.com \
    --cc=linux-gpio@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.