diff libpam-sys/build.rs @ 108:e97534be35e3

Make some proc macros for doing cfg-like stuff for PAM impls.
author Paul Fisher <paul@pfish.zone>
date Sat, 28 Jun 2025 00:34:45 -0400
parents 49d9e2b5c189
children
line wrap: on
line diff
--- a/libpam-sys/build.rs	Thu Jun 26 22:42:32 2025 -0400
+++ b/libpam-sys/build.rs	Sat Jun 28 00:34:45 2025 -0400
@@ -1,143 +1,3 @@
-use bindgen::MacroTypeVariation;
-use std::error::Error;
-use std::fmt::{Debug, Display, Formatter};
-use std::path::PathBuf;
-use std::{env, fs};
-
-enum PamImpl {
-    Illumos,
-    LinuxPam,
-    OpenPam,
-}
-
-#[derive(Debug)]
-struct InvalidEnum(String);
-
-impl Display for InvalidEnum {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        write!(f, "invalid PAM impl {:?}", self.0)
-    }
-}
-
-impl Error for InvalidEnum {}
-
-impl TryFrom<&str> for PamImpl {
-    type Error = InvalidEnum;
-    fn try_from(value: &str) -> Result<Self, Self::Error> {
-        Ok(match value {
-            "illumos" => Self::Illumos,
-            "linux-pam" => Self::LinuxPam,
-            "openpam" => Self::OpenPam,
-            other => return Err(InvalidEnum(other.to_owned())),
-        })
-    }
-}
-
-impl Debug for PamImpl {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        Debug::fmt(
-            match self {
-                Self::Illumos => "illumos",
-                Self::LinuxPam => "linux-pam",
-                Self::OpenPam => "openpam",
-            },
-            f,
-        )
-    }
-}
-
 fn main() {
     println!("cargo:rustc-link-lib=pam");
-    let out_file = PathBuf::from(env::var("OUT_DIR").unwrap()).join("constants.rs");
-    let pam_impl = do_detection();
-
-    if cfg!(feature = "use-system-headers") {
-        let builder = bindgen::Builder::default()
-            .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
-            .blocklist_function(".*")
-            .blocklist_type(".*")
-            .allowlist_var(".*")
-            .default_macro_constant_type(MacroTypeVariation::Unsigned);
-
-        let builder = match pam_impl {
-            PamImpl::Illumos => builder.header_contents(
-                "illumos.h",
-                "\
-                        #include <security/pam_appl.h>
-                        #include <security/pam_modules.h>
-                    ",
-            ),
-            PamImpl::LinuxPam => builder.header_contents(
-                "linux-pam.h",
-                "\
-                        #include <security/_pam_types.h>
-                        #include <security/pam_appl.h>
-                        #include <security/pam_ext.h>
-                        #include <security/pam_modules.h>
-                    ",
-            ),
-            PamImpl::OpenPam => builder.header_contents(
-                "openpam.h",
-                "\
-                        #include <security/pam_types.h>
-                        #include <security/openpam.h>
-                        #include <security/pam_appl.h>
-                        #include <security/pam_constants.h>
-                    ",
-            ),
-        };
-        let bindings = builder.generate().unwrap();
-        bindings.write_to_file(out_file).unwrap();
-    } else {
-        // Just write empty data to the file to avoid conditional compilation
-        // shenanigans.
-        fs::write(out_file, "").unwrap();
-    }
 }
-
-fn do_detection() -> PamImpl {
-    println!(r#"cargo:rustc-check-cfg=cfg(pam_impl, values("illumos", "linux-pam", "openpam"))"#);
-    let pam_impl = _detect_internal();
-    println!("cargo:rustc-cfg=pam_impl={pam_impl:?}");
-    pam_impl
-}
-
-fn _detect_internal() -> PamImpl {
-    if let Some(pam_impl) = option_env!("LIBPAMSYS_PAM_IMPL") {
-        pam_impl.try_into().unwrap()
-    } else if cfg!(feature = "use-system-headers") {
-        // Detect which impl it is from system headers.
-        if header_exists("security/_pam_types.h") {
-            PamImpl::LinuxPam
-        } else if header_exists("security/openpam.h") {
-            PamImpl::OpenPam
-        } else if header_exists("security/pam_appl.h") {
-            PamImpl::Illumos
-        } else {
-            panic!("could not detect PAM implementation")
-        }
-    } else {
-        // Otherwise, guess what PAM impl we're using based on the OS.
-        if cfg!(target_os = "linux") {
-            PamImpl::LinuxPam
-        } else if cfg!(any(
-            target_os = "macos",
-            target_os = "freebsd",
-            target_os = "netbsd",
-            target_os = "dragonfly",
-            target_os = "openbsd"
-        )) {
-            PamImpl::OpenPam
-        } else {
-            PamImpl::Illumos
-        }
-    }
-}
-
-fn header_exists(header: &str) -> bool {
-    bindgen::Builder::default()
-        .blocklist_item(".*")
-        .header_contents("header.h", &format!("#include <{header}>"))
-        .generate()
-        .is_ok()
-}