comparison 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
comparison
equal deleted inserted replaced
109:bb465393621f 110:2346fd501b7a
1 //! This absurd build script basically sets up everything for libpam-sys-impl.
2 //!
3 //! 1. It's the definition site for the [`PamImpl`] enum, which then gets
4 //! output to the `OUT_DIR/pam_impl_enum.rs` file for parsing/inclusion
5 //! into the `__pam_impl_enum__` macro.
6 //! 2. It detects the current PAM implementation and sets an env var for
7 //! the macros in `libpam-sys-impl`.
8
9 use std::{env, fs};
1 use strum::EnumString; 10 use strum::EnumString;
11 use proc_macro2::TokenStream;
12 use quote::quote;
2 13
3 fn main() { 14 fn main() {
4 let pam_impl = match option_env!("LIBPAMSYS_IMPL") { 15 let pam_impl = match option_env!("LIBPAMSYS_IMPL") {
5 // The default option: Guess what PAM impl we're using based on OS. 16 // The default option: Guess what PAM impl we're using based on OS.
6 None => { 17 None => {
7 // Otherwise, guess what PAM impl we're using based on the OS.
8 if cfg!(target_os = "linux") { 18 if cfg!(target_os = "linux") {
9 PamImpl::LinuxPam 19 PamImpl::LinuxPam
10 } else if cfg!(any( 20 } else if cfg!(any(
11 target_os = "macos", 21 target_os = "macos",
12 target_os = "freebsd", 22 target_os = "freebsd",
13 target_os = "netbsd", 23 target_os = "netbsd",
14 target_os = "dragonfly", 24 target_os = "dragonfly",
15 target_os = "openbsd" 25 target_os = "openbsd"
16 )) { 26 )) {
17 PamImpl::OpenPam 27 PamImpl::OpenPam
18 } else if cfg!(any()) { 28 } else if cfg!(any(
19 PamImpl::Illumos 29 target_os = "illumos",
30 target_os = "solaris",
31 )) {
32 PamImpl::Sun
20 } else { 33 } else {
21 PamImpl::MinimalOpenPam 34 PamImpl::MinimalOpenPam
22 } 35 }
23 } 36 }
24 Some("_detect") => { 37 Some("_detect") => {
26 if header_exists("security/_pam_types.h") { 39 if header_exists("security/_pam_types.h") {
27 PamImpl::LinuxPam 40 PamImpl::LinuxPam
28 } else if header_exists("security/openpam.h") { 41 } else if header_exists("security/openpam.h") {
29 PamImpl::OpenPam 42 PamImpl::OpenPam
30 } else if header_exists("security/pam_appl.h") { 43 } else if header_exists("security/pam_appl.h") {
31 // We figure we're *probably* on Illumos or something like that. 44 // We figure we're *probably* on a Sun derivative.
32 PamImpl::Illumos 45 PamImpl::Sun
33 } else { 46 } else {
34 // If all else fails, assume the bare minimum. 47 // If all else fails, assume the bare minimum.
35 PamImpl::MinimalOpenPam 48 PamImpl::MinimalOpenPam
36 } 49 }
37 } 50 }
38 Some(other) => match PamImpl::try_from(other) { 51 Some(other) => match PamImpl::try_from(other) {
39 Ok(i) => i, 52 Ok(i) => i,
40 Err(_) => panic!("unknown PAM implementation {other:?}"), 53 Err(_) => panic!("unknown PAM implementation {other:?}"),
41 }, 54 },
42 }; 55 };
56 fs::write(format!("{}/pam_impl_enum.rs", env::var("OUT_DIR").unwrap()), PamImpl::enum_tokens().to_string()).unwrap();
43 println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}"); 57 println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}");
44 } 58 }
45 59
46 #[derive(Debug, EnumString)] 60 /// This defines a local enum with an `enum_tokens()` method that can spit out
47 enum PamImpl { 61 /// its own contents.
48 Illumos, 62 macro_rules! self_aware_enum {
49 LinuxPam, 63 (
50 OpenPam, 64 $(#here[$here:meta])*
51 MinimalOpenPam, 65 $(#[$attr:meta])*
66 $name:ident {
67 $($tt:tt)*
68 }
69 ) => {
70 $(#[$here])*
71 $(#[$attr])*
72 pub enum $name {
73 $($tt)*
74 }
75
76 impl $name {
77 fn enum_tokens() -> TokenStream {
78 quote!(
79 $(#[$attr])*
80 pub enum $name {
81 $($tt)*
82 }
83 )
84 }
85 }
86 }
52 } 87 }
88
89 self_aware_enum!(
90 #here[derive(EnumString, strum::Display)]
91 /// The PAM implementations supported by `libpam-sys`.
92 #[derive(Clone, Copy, Debug, PartialEq)]
93 PamImpl {
94 /// [Linux-PAM] is provided by most Linux distributions.
95 ///
96 /// [Linux-PAM]: https://github.com/linux-pam/linux-pam
97 LinuxPam,
98 /// [OpenPAM] is used by most BSDs, including Mac OS X.
99 ///
100 /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM
101 OpenPam,
102 /// Illumos and Solaris use a derivative of [Sun's implementation][sun].
103 ///
104 /// [sun]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam
105 Sun,
106 /// Only the functionality in [the PAM spec], with OpenPAM/Sun consts.
107 ///
108 /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm
109 MinimalOpenPam,
110 }
111 );
53 112
54 fn header_exists(header: &str) -> bool { 113 fn header_exists(header: &str) -> bool {
55 bindgen::Builder::default() 114 bindgen::Builder::default()
56 .blocklist_item(".*") 115 .blocklist_item(".*")
57 .header_contents("header.h", &format!("#include <{header}>")) 116 .header_contents("header.h", &format!("#include <{header}>"))