diff libpam-sys/libpam-sys-impls/build.rs @ 110:2346fd501b7a

Add tests for constants and do other macro niceties. - Adds tests for all the constants. Pretty sweet. - Moves documentation for cfg-pam-impl macro to `libpam-sys`. - Renames `Illumos` to `Sun`. - other stuff
author Paul Fisher <paul@pfish.zone>
date Sun, 29 Jun 2025 02:15:46 -0400
parents bb465393621f
children 178310336596
line wrap: on
line diff
--- a/libpam-sys/libpam-sys-impls/build.rs	Sat Jun 28 02:49:35 2025 -0400
+++ b/libpam-sys/libpam-sys-impls/build.rs	Sun Jun 29 02:15:46 2025 -0400
@@ -1,10 +1,20 @@
+//! This absurd build script basically sets up everything for libpam-sys-impl.
+//!
+//!  1. It's the definition site for the [`PamImpl`] enum, which then gets
+//!     output to the `OUT_DIR/pam_impl_enum.rs` file for parsing/inclusion
+//!     into the `__pam_impl_enum__` macro.
+//!  2. It detects the current PAM implementation and sets an env var for
+//!     the macros in `libpam-sys-impl`.
+
+use std::{env, fs};
 use strum::EnumString;
+use proc_macro2::TokenStream;
+use quote::quote;
 
 fn main() {
     let pam_impl = match option_env!("LIBPAMSYS_IMPL") {
         // The default option: Guess what PAM impl we're using based on OS.
         None => {
-            // Otherwise, guess what PAM impl we're using based on the OS.
             if cfg!(target_os = "linux") {
                 PamImpl::LinuxPam
             } else if cfg!(any(
@@ -15,8 +25,11 @@
                 target_os = "openbsd"
             )) {
                 PamImpl::OpenPam
-            } else if cfg!(any()) {
-                PamImpl::Illumos
+            } else if cfg!(any(
+                target_os = "illumos",
+                target_os = "solaris",
+            )) {
+                PamImpl::Sun
             } else {
                 PamImpl::MinimalOpenPam
             }
@@ -28,8 +41,8 @@
             } else if header_exists("security/openpam.h") {
                 PamImpl::OpenPam
             } else if header_exists("security/pam_appl.h") {
-                // We figure we're *probably* on Illumos or something like that.
-                PamImpl::Illumos
+                // We figure we're *probably* on a Sun derivative.
+                PamImpl::Sun
             } else {
                 // If all else fails, assume the bare minimum.
                 PamImpl::MinimalOpenPam
@@ -40,17 +53,63 @@
             Err(_) => panic!("unknown PAM implementation {other:?}"),
         },
     };
+    fs::write(format!("{}/pam_impl_enum.rs", env::var("OUT_DIR").unwrap()), PamImpl::enum_tokens().to_string()).unwrap();
     println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}");
 }
 
-#[derive(Debug, EnumString)]
-enum PamImpl {
-    Illumos,
-    LinuxPam,
-    OpenPam,
-    MinimalOpenPam,
+/// This defines a local enum with an `enum_tokens()` method that can spit out
+/// its own contents.
+macro_rules! self_aware_enum {
+    (
+        $(#here[$here:meta])*
+        $(#[$attr:meta])*
+        $name:ident {
+            $($tt:tt)*
+        }
+    ) => {
+        $(#[$here])*
+        $(#[$attr])*
+        pub enum $name {
+            $($tt)*
+        }
+
+        impl $name {
+            fn enum_tokens() -> TokenStream {
+                quote!(
+                    $(#[$attr])*
+                    pub enum $name {
+                        $($tt)*
+                    }
+                )
+            }
+        }
+    }
 }
 
+self_aware_enum!(
+    #here[derive(EnumString, strum::Display)]
+    /// The PAM implementations supported by `libpam-sys`.
+    #[derive(Clone, Copy, Debug, PartialEq)]
+    PamImpl {
+        /// [Linux-PAM] is provided by most Linux distributions.
+        ///
+        /// [Linux-PAM]: https://github.com/linux-pam/linux-pam
+        LinuxPam,
+        /// [OpenPAM] is used by most BSDs, including Mac OS X.
+        ///
+        /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM
+        OpenPam,
+        /// Illumos and Solaris use a derivative of [Sun's implementation][sun].
+        ///
+        /// [sun]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam
+        Sun,
+        /// Only the functionality in [the PAM spec], with OpenPAM/Sun consts.
+        ///
+        /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm
+        MinimalOpenPam,
+    }
+);
+
 fn header_exists(header: &str) -> bool {
     bindgen::Builder::default()
         .blocklist_item(".*")